re re revised oberon compiler for RISC works -- noch

This commit is contained in:
Norayr Chilingarian 2014-09-14 06:09:09 +04:00
parent c8cc104507
commit c900218965
11 changed files with 1771 additions and 572 deletions

677
src/voc07R/CompatFiles.Mod Normal file
View file

@ -0,0 +1,677 @@
MODULE CompatFiles; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files *)
(* modified version of Files, which opens only the file provided and does not scan any path in any environment variable, also ReadLine procedure added; -- noch *)
IMPORT SYSTEM, Unix, Kernel, Args, Console;
(* standard data type I/O
little endian,
Sint:1, Int:2, Lint:4
ORD({0}) = 1,
false = 0, true =1
IEEE real format,
null terminated strings,
compact numbers according to M.Odersky *)
CONST
nofbufs = 4;
bufsize = 4096;
fileTabSize = 64;
noDesc = -1;
notDone = -1;
(* file states *)
open = 0; create = 1; close = 2;
TYPE
FileName = ARRAY 101 OF CHAR;
File* = POINTER TO Handle;
Buffer = POINTER TO BufDesc;
Handle = RECORD
workName, registerName: FileName;
tempFile: BOOLEAN;
dev, ino, mtime: LONGINT;
fd-, len, pos: LONGINT;
bufs: ARRAY nofbufs OF Buffer;
swapper, state: INTEGER
END ;
BufDesc = RECORD
f: File;
chg: BOOLEAN;
org, size: LONGINT;
data: ARRAY bufsize OF SYSTEM.BYTE
END ;
Rider* = RECORD
res*: LONGINT;
eof*: BOOLEAN;
buf: Buffer;
org, offset: LONGINT
END ;
Time = POINTER TO TimeDesc;
TimeDesc = RECORD
sec*, min*, hour*, mday*, mon*, year*, wday*, isdst*, zone*, gmtoff*: LONGINT;
(* sec*, min*, hour*, mday*, mon*, year*, wday*, isdst*, zone*, gmtoff*: INTEGER;*)
END ;
VAR
fileTab: ARRAY fileTabSize OF LONGINT (*=File*);
tempno: INTEGER;
(* for localtime *)
PROCEDURE -includetime()
'#include "time.h"';
PROCEDURE -localtime(VAR clock: LONGINT): Time
"(CompatFiles_Time) localtime(clock)";
PROCEDURE -getcwd(VAR cwd: Unix.Name)
"getcwd(cwd, cwd__len)";
PROCEDURE -IdxTrap "__HALT(-1)";
PROCEDURE^ Finalize(o: SYSTEM.PTR);
PROCEDURE Err(s: ARRAY OF CHAR; f: File; errno: LONGINT);
BEGIN
Console.Ln; Console.String("-- "); Console.String(s); Console.String(": ");
IF f # NIL THEN
IF f.registerName # "" THEN Console.String(f.registerName) ELSE Console.String(f.workName) END
END ;
IF errno # 0 THEN Console.String(" errno = "); Console.Int(errno, 1) END ;
Console.Ln;
HALT(99)
END Err;
PROCEDURE MakeFileName(dir, name: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
VAR i, j: INTEGER;
BEGIN i := 0; j := 0;
WHILE dir[i] # 0X DO dest[i] := dir[i]; INC(i) END ;
IF dest[i-1] # "/" THEN dest[i] := "/"; INC(i) END ;
WHILE name[j] # 0X DO dest[i] := name[j]; INC(i); INC(j) END ;
dest[i] := 0X
END MakeFileName;
PROCEDURE GetTempName(finalName: ARRAY OF CHAR; VAR name: ARRAY OF CHAR);
VAR n, i, j: LONGINT;
BEGIN
INC(tempno); n := tempno; i := 0;
IF finalName[0] # "/" THEN (* relative pathname *)
WHILE Kernel.CWD[i] # 0X DO name[i] := Kernel.CWD[i]; INC(i) END;
IF Kernel.CWD[i-1] # "/" THEN name[i] := "/"; INC(i) END
END;
j := 0;
WHILE finalName[j] # 0X DO name[i] := finalName[j]; INC(i); INC(j) END;
DEC(i);
WHILE name[i] # "/" DO DEC(i) END;
name[i+1] := "."; name[i+2] := "t"; name[i+3] := "m"; name[i+4] := "p"; name[i+5] := "."; INC(i, 6);
WHILE n > 0 DO name[i] := CHR(n MOD 10 + ORD("0")); n := n DIV 10; INC(i) END;
name[i] := "."; INC(i); n := SHORT(Unix.Getpid());
WHILE n > 0 DO name[i] := CHR(n MOD 10 + ORD("0")); n := n DIV 10; INC(i) END;
name[i] := 0X
END GetTempName;
PROCEDURE Create(f: File);
VAR stat: Unix.Status; done: BOOLEAN;
errno: LONGINT; err: ARRAY 32 OF CHAR;
BEGIN
IF f.fd = noDesc THEN
IF f.state = create THEN GetTempName(f.registerName, f.workName); f.tempFile := TRUE
ELSIF f.state = close THEN
f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE
END ;
errno := Unix.Unlink(f.workName); (*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
f.fd := Unix.Open(f.workName, Unix.rdwr + Unix.creat + Unix.trunc, {2, 4,5, 7,8});
done := f.fd >= 0; errno := Unix.errno();
IF (~done & ((errno = Unix.ENFILE) OR (errno = Unix.EMFILE))) OR (done & (f.fd >= fileTabSize)) THEN
IF done & (f.fd >= fileTabSize) THEN errno := Unix.Close(f.fd) END ;
Kernel.GC(TRUE);
f.fd := Unix.Open(f.workName, Unix.rdwr + Unix.creat + Unix.trunc, {2, 4,5, 7,8});
done := f.fd >= 0
END ;
IF done THEN
IF f.fd >= fileTabSize THEN errno := Unix.Close(f.fd); Err("too many files open", f, 0)
ELSE fileTab[f.fd] := SYSTEM.VAL(LONGINT, f); INC(Kernel.nofiles); Kernel.RegisterObject(f, Finalize);
f.state := open; f.pos := 0; errno := Unix.Fstat(f.fd, stat);
f.dev := stat.dev; f.ino := stat.ino; f.mtime := stat.mtime
END
ELSE errno := Unix.errno();
IF errno = Unix.ENOENT THEN err := "no such directory"
ELSIF (errno = Unix.ENFILE) OR (errno = Unix.EMFILE) THEN err := "too many files open"
ELSE err := "file not created"
END ;
Err(err, f, errno)
END
END
END Create;
PROCEDURE Flush(buf: Buffer);
VAR res: LONGINT; f: File; stat: Unix.Status;
BEGIN
IF buf.chg THEN f := buf.f; Create(f);
IF buf.org # f.pos THEN res := Unix.Lseek(f.fd, buf.org, 0) END ;
res := Unix.Write(f.fd, SYSTEM.ADR(buf.data), buf.size);
IF res < 0 THEN Err("error in writing file", f, Unix.errno()) END ;
f.pos := buf.org + buf.size;
buf.chg := FALSE;
res := Unix.Fstat(f.fd, stat);
f.mtime := stat.mtime
END
END Flush;
PROCEDURE Close* (f: File);
VAR i, res: LONGINT;
BEGIN
IF (f.state # create) OR (f.registerName # "") THEN
Create(f); i := 0;
WHILE (i < nofbufs) & (f.bufs[i] # NIL) DO Flush(f.bufs[i]); INC(i) END ;
res := Unix.Fsync(f.fd);
IF res < 0 THEN Err("error in writing file", f, Unix.errno()) END
END
END Close;
PROCEDURE Length* (f: File): LONGINT;
BEGIN RETURN f.len
END Length;
PROCEDURE New* (name: ARRAY OF CHAR): File;
VAR f: File;
BEGIN
NEW(f); f.workName := ""; COPY(name, f.registerName);
f.fd := noDesc; f.state := create; f.len := 0; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*)
RETURN f
END New;
(*
PROCEDURE ScanPath(VAR pos: INTEGER; VAR dir: ARRAY OF CHAR); (* supports ~, ~user and blanks inside path *)
VAR i: INTEGER; ch: CHAR; home: ARRAY 256 OF CHAR;
BEGIN
i := 0; ch := Kernel.OBERON[pos];
WHILE (ch = " ") OR (ch = ":") DO INC(pos); ch := Kernel.OBERON[pos] END ;
IF ch = "~" THEN
INC(pos); ch := Kernel.OBERON[pos];
home := ""; Args.GetEnv("HOME", home);
WHILE home[i] # 0X DO dir[i] := home[i]; INC(i) END ;
IF (ch # "/") & (ch # 0X) & (ch # ":") & (ch # " ") THEN
WHILE (i > 0) & (dir[i-1] # "/") DO DEC(i) END
END
END ;
WHILE (ch # 0X) & (ch # ":") DO dir[i] := ch; INC(i); INC(pos); ch := Kernel.OBERON[pos] END ;
WHILE (i > 0) & (dir[i-1] = " ") DO DEC(i) END ;
dir[i] := 0X
END ScanPath;
*)
PROCEDURE HasDir(VAR name: ARRAY OF CHAR): BOOLEAN;
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0; ch := name[0];
WHILE (ch # 0X) & (ch # "/") DO INC(i); ch := name[i] END ;
RETURN ch = "/"
END HasDir;
PROCEDURE CacheEntry(dev, ino: LONGINT; mtime: LONGINT): File;
VAR f: File; i: INTEGER; stat: Unix.Status; res: LONGINT;
BEGIN i := 0;
WHILE i < fileTabSize DO
f := SYSTEM.VAL(File, fileTab[i]);
IF (f # NIL) & (ino = f.ino) & (dev = f.dev) THEN
IF mtime # f.mtime THEN i := 0;
WHILE i < nofbufs DO
IF f.bufs[i] # NIL THEN f.bufs[i].org := -1; f.bufs[i] := NIL END ;
INC(i)
END ;
f.swapper := -1; f.mtime := mtime;
res := Unix.Fstat(f.fd, stat); f.len := stat.size
END ;
RETURN f
END ;
INC(i)
END ;
RETURN NIL
END CacheEntry;
PROCEDURE Old* (name: ARRAY OF CHAR): File;
VAR f: File; fd, res, errno: LONGINT; pos: INTEGER; done: BOOLEAN;
dir, path: ARRAY 256 OF CHAR;
stat: Unix.Status;
BEGIN
IF name # "" THEN
IF HasDir(name) THEN dir := ""; COPY(name, path)
ELSE
pos := 0;
COPY(name, path); (* -- noch *)
(*ScanPath(pos, dir);*) (*MakeFileName(dir, name, path);*) (*ScanPath(pos, dir)*)
END ;
LOOP
fd := Unix.Open(path, Unix.rdwr, {}); done := fd >= 0; errno := Unix.errno();
IF (~done & ((errno = Unix.ENFILE) OR (errno = Unix.EMFILE))) OR (done & (fd >= fileTabSize)) THEN
IF done & (fd >= fileTabSize) THEN res := Unix.Close(fd) END ;
Kernel.GC(TRUE);
fd := Unix.Open(path, Unix.rdwr, {});
done := fd >= 0; errno := Unix.errno();
IF ~done & ((errno = Unix.ENFILE) OR (errno = Unix.EMFILE)) THEN Err("too many files open", f, errno) END
END ;
IF ~done & ((errno = Unix.EACCES) OR (errno = Unix.EROFS) OR (errno = Unix.EAGAIN)) THEN
(* errno EAGAIN observed on Solaris 2.4 *)
fd := Unix.Open(path, Unix.rdonly, {}); done := fd >= 0; errno := Unix.errno()
END ;
IF (~done) & (errno # Unix.ENOENT) THEN
Console.String("warning Files.Old "); Console.String(name);
Console.String(" errno = "); Console.Int(errno, 0); Console.Ln;
END ;
IF done THEN
res := Unix.Fstat(fd, stat);
f := CacheEntry(stat.dev, stat.ino, stat.mtime);
IF f # NIL THEN res := Unix.Close(fd); RETURN f
ELSIF fd >= fileTabSize THEN res := Unix.Close(fd); Err("too many files open", f, 0)
ELSE NEW(f); fileTab[fd] := SYSTEM.VAL(LONGINT, f); INC(Kernel.nofiles); Kernel.RegisterObject(f, Finalize);
f.fd := fd; f.state := open; f.len := stat.size; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*)
COPY(name, f.workName); f.registerName := ""; f.tempFile := FALSE;
f.dev := stat.dev; f.ino := stat.ino; f.mtime := stat.mtime;
RETURN f
END
ELSIF dir = "" THEN RETURN NIL
ELSE (*MakeFileName(dir, name, path);*) (*ScanPath(pos, dir)*)
RETURN NIL
END
END
ELSE RETURN NIL
END
END Old;
PROCEDURE Purge* (f: File);
VAR i: INTEGER; stat: Unix.Status; res: LONGINT;
BEGIN i := 0;
WHILE i < nofbufs DO
IF f.bufs[i] # NIL THEN f.bufs[i].org := -1; f.bufs[i] := NIL END ;
INC(i)
END ;
IF f.fd # noDesc THEN res := Unix.Ftruncate(f.fd, 0); res := Unix.Lseek(f.fd, 0, 0) END ;
f.pos := 0; f.len := 0; f.swapper := -1;
res := Unix.Fstat(f.fd, stat); f.mtime := stat.mtime
END Purge;
PROCEDURE GetDate* (f: File; VAR t, d: LONGINT);
VAR stat: Unix.Status; clock, res: LONGINT; time: Time;
BEGIN
Create(f); res := Unix.Fstat(f.fd, stat);
time := localtime(stat.mtime);
t := time.sec + ASH(time.min, 6) + ASH(time.hour, 12);
d := time.mday + ASH(time.mon+1, 5) + ASH(time.year MOD 100, 9)
END GetDate;
PROCEDURE Pos* (VAR r: Rider): LONGINT;
BEGIN RETURN r.org + r.offset
END Pos;
PROCEDURE Set* (VAR r: Rider; f: File; pos: LONGINT);
VAR org, offset, i, n, res: LONGINT; buf: Buffer;
BEGIN
IF f # NIL THEN
IF pos > f.len THEN pos := f.len ELSIF pos < 0 THEN pos := 0 END ;
offset := pos MOD bufsize; org := pos - offset; i := 0;
WHILE (i < nofbufs) & (f.bufs[i] # NIL) & (org # f.bufs[i].org) DO INC(i) END ;
IF i < nofbufs THEN
IF f.bufs[i] = NIL THEN NEW(buf); buf.chg := FALSE; buf.org := -1; buf.f := f; f.bufs[i] := buf
ELSE buf := f.bufs[i]
END
ELSE
f.swapper := (f.swapper + 1) MOD nofbufs;
buf := f.bufs[f.swapper];
Flush(buf)
END ;
IF buf.org # org THEN
IF org = f.len THEN buf.size := 0
ELSE Create(f);
IF f.pos # org THEN res := Unix.Lseek(f.fd, org, 0) END ;
n := Unix.ReadBlk(f.fd, buf.data);
IF n < 0 THEN Err("read from file not done", f, Unix.errno()) END ;
f.pos := org + n;
buf.size := n
END ;
buf.org := org; buf.chg := FALSE
END
ELSE buf := NIL; org := 0; offset := 0
END ;
r.buf := buf; r.org := org; r.offset := offset; r.eof := FALSE; r.res := 0
END Set;
PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE);
VAR offset: LONGINT; buf: Buffer;
BEGIN
buf := r.buf; offset := r.offset;
IF r.org # buf.org THEN Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset END ;
IF (offset < buf.size) THEN
x := buf.data[offset]; r.offset := offset + 1
ELSIF r.org + offset < buf.f.len THEN
Set(r, r.buf.f, r.org + offset);
x := r.buf.data[0]; r.offset := 1
ELSE
x := 0X; r.eof := TRUE
END
END Read;
PROCEDURE ReadBytes* (VAR r: Rider; VAR x: ARRAY OF SYSTEM.BYTE; n: LONGINT);
VAR xpos, min, restInBuf, offset: LONGINT; buf: Buffer;
BEGIN
IF n > LEN(x) THEN IdxTrap END ;
xpos := 0; buf := r.buf; offset := r.offset;
WHILE n > 0 DO
IF (r.org # buf.org) OR (offset >= bufsize) THEN
Set(r, buf.f, r.org + offset);
buf := r.buf; offset := r.offset
END ;
restInBuf := buf.size - offset;
IF restInBuf = 0 THEN r.res := n; r.eof := TRUE; RETURN
ELSIF n > restInBuf THEN min := restInBuf ELSE min := n END ;
SYSTEM.MOVE(SYSTEM.ADR(buf.data) + offset, SYSTEM.ADR(x) + xpos, min);
INC(offset, min); r.offset := offset; INC(xpos, min); DEC(n, min)
END ;
r.res := 0; r.eof := FALSE
END ReadBytes;
PROCEDURE ReadByte* (VAR r : Rider; VAR x : ARRAY OF SYSTEM.BYTE);
BEGIN
ReadBytes(r, x, 1);
END ReadByte;
PROCEDURE Base* (VAR r: Rider): File;
BEGIN RETURN r.buf.f
END Base;
PROCEDURE Write* (VAR r: Rider; x: SYSTEM.BYTE);
VAR buf: Buffer; offset: LONGINT;
BEGIN
buf := r.buf; offset := r.offset;
IF (r.org # buf.org) OR (offset >= bufsize) THEN
Set(r, buf.f, r.org + offset);
buf := r.buf; offset := r.offset
END ;
buf.data[offset] := x;
buf.chg := TRUE;
IF offset = buf.size THEN
INC(buf.size); INC(buf.f.len)
END ;
r.offset := offset + 1; r.res := 0
END Write;
PROCEDURE WriteByte* (VAR r : Rider; x : SYSTEM.BYTE); (* added for compatibility with PO 2013, -- noch *)
BEGIN
Write(r, x);
END WriteByte;
PROCEDURE WriteBytes* (VAR r: Rider; VAR x: ARRAY OF SYSTEM.BYTE; n: LONGINT);
VAR xpos, min, restInBuf, offset: LONGINT; buf: Buffer;
BEGIN
IF n > LEN(x) THEN IdxTrap END ;
xpos := 0; buf := r.buf; offset := r.offset;
WHILE n > 0 DO
IF (r.org # buf.org) OR (offset >= bufsize) THEN
Set(r, buf.f, r.org + offset);
buf := r.buf; offset := r.offset
END ;
restInBuf := bufsize - offset;
IF n > restInBuf THEN min := restInBuf ELSE min := n END ;
SYSTEM.MOVE(SYSTEM.ADR(x) + xpos, SYSTEM.ADR(buf.data) + offset, min);
INC(offset, min); r.offset := offset;
IF offset > buf.size THEN INC(buf.f.len, offset - buf.size); buf.size := offset END ;
INC(xpos, min); DEC(n, min); buf.chg := TRUE
END ;
r.res := 0
END WriteBytes;
(* another solution would be one that is similar to ReadBytes, WriteBytes.
No code duplication, more symmetric, only two ifs for
Read and Write in buffer, buf.size replaced by bufsize in Write ops, buf.size and len
must be made consistent with offset (if offset > buf.size) in a lazy way.
PROCEDURE Write* (VAR r: Rider; x: SYSTEM.BYTE);
VAR buf: Buffer; offset: LONGINT;
BEGIN
buf := r.buf; offset := r.offset;
IF (offset >= bufsize) OR (r.org # buf.org) THEN
Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset;
END ;
buf.data[offset] := x; r.offset := offset + 1; buf.chg := TRUE
END Write;
PROCEDURE WriteBytes ...
PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE);
VAR offset: LONGINT; buf: Buffer;
BEGIN
buf := r.buf; offset := r.offset;
IF (offset >= buf.size) OR (r.org # buf.org) THEN
IF r.org + offset >= buf.f.len THEN x := 0X; r.eof := TRUE; RETURN
ELSE Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset
END
END ;
x := buf.data[offset]; r.offset := offset + 1
END Read;
but this would also affect Set, Length, and Flush.
Especially Length would become fairly complex.
*)
PROCEDURE Delete* (name: ARRAY OF CHAR; VAR res: INTEGER);
BEGIN
res := SHORT(Unix.Unlink(name));
res := SHORT(Unix.errno())
END Delete;
PROCEDURE Rename* (old, new: ARRAY OF CHAR; VAR res: INTEGER);
VAR fdold, fdnew, n, errno, r: LONGINT;
ostat, nstat: Unix.Status;
buf: ARRAY 4096 OF CHAR;
BEGIN
r := Unix.Stat(old, ostat);
IF r >= 0 THEN
r := Unix.Stat(new, nstat);
IF (r >= 0) & ((ostat.dev # nstat.dev) OR (ostat.ino # nstat.ino)) THEN
Delete(new, res); (* work around stale nfs handles *)
END ;
r := Unix.Rename(old, new);
IF r < 0 THEN res := SHORT(Unix.errno());
IF res = Unix.EXDEV THEN (* cross device link, move the file *)
fdold := Unix.Open(old, Unix.rdonly, {});
IF fdold < 0 THEN res := 2; RETURN END ;
fdnew := Unix.Open(new, Unix.rdwr + Unix.creat + Unix.trunc, {2, 4,5, 7,8});
IF fdnew < 0 THEN r := Unix.Close(fdold); res := 3; RETURN END ;
n := Unix.Read(fdold, SYSTEM.ADR(buf), bufsize);
WHILE n > 0 DO
r := Unix.Write(fdnew, SYSTEM.ADR(buf), n);
IF r < 0 THEN errno := Unix.errno(); r := Unix.Close(fdold); r := Unix.Close(fdnew);
Err("cannot move file", NIL, errno)
END ;
n := Unix.Read(fdold, SYSTEM.ADR(buf), bufsize)
END ;
errno := Unix.errno();
r := Unix.Close(fdold); r := Unix.Close(fdnew);
IF n = 0 THEN r := Unix.Unlink(old); res := 0
ELSE Err("cannot move file", NIL, errno)
END ;
ELSE RETURN (* res is Unix.Rename return code *)
END
END ;
res := 0
ELSE res := 2 (* old file not found *)
END
END Rename;
PROCEDURE Register* (f: File);
VAR idx, errno: INTEGER; f1: File; file: ARRAY 104 OF CHAR;
BEGIN
IF (f.state = create) & (f.registerName # "") THEN f.state := close (* shortcut renaming *) END ;
Close(f);
IF f.registerName # "" THEN
Rename(f.workName, f.registerName, errno);
IF errno # 0 THEN COPY(f.registerName, file); HALT(99) END ;
f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE
END
END Register;
PROCEDURE ChangeDirectory*(path: ARRAY OF CHAR; VAR res: INTEGER);
BEGIN
res := SHORT(Unix.Chdir(path));
getcwd(Kernel.CWD)
END ChangeDirectory;
PROCEDURE FlipBytes(VAR src, dest: ARRAY OF SYSTEM.BYTE);
VAR i, j: LONGINT;
BEGIN
IF ~Kernel.littleEndian THEN i := LEN(src); j := 0;
WHILE i > 0 DO DEC(i); dest[j] := src[i]; INC(j) END
ELSE SYSTEM.MOVE(SYSTEM.ADR(src), SYSTEM.ADR(dest), LEN(src))
END
END FlipBytes;
PROCEDURE ReadBool* (VAR R: Rider; VAR x: BOOLEAN);
BEGIN Read(R, SYSTEM.VAL(CHAR, x))
END ReadBool;
(* PROCEDURE ReadInt* (VAR R: Rider; VAR x: INTEGER);
VAR b: ARRAY 2 OF CHAR;
BEGIN ReadBytes(R, b, 2);
x := ORD(b[0]) + ORD(b[1])*256
END ReadInt;
*)
PROCEDURE ReadInt* (VAR R: Rider; VAR x: LONGINT); (* to compile OR compiler; -- noch *)
VAR b: ARRAY 4 OF CHAR;
BEGIN ReadBytes(R, b, 4);
x := ORD(b[0]) + ORD(b[1])*100H + ORD(b[2])*10000H + ORD(b[3])*1000000H
END ReadInt;
PROCEDURE ReadLInt* (VAR R: Rider; VAR x: LONGINT);
VAR b: ARRAY 4 OF CHAR;
BEGIN ReadBytes(R, b, 4);
x := ORD(b[0]) + ORD(b[1])*100H + ORD(b[2])*10000H + ORD(b[3])*1000000H
END ReadLInt;
PROCEDURE ReadSet* (VAR R: Rider; VAR x: SET);
VAR b: ARRAY 4 OF CHAR;
BEGIN ReadBytes(R, b, 4);
x := SYSTEM.VAL(SET, ORD(b[0]) + ORD(b[1])*100H + ORD(b[2])*10000H + ORD(b[3])*1000000H)
END ReadSet;
PROCEDURE ReadReal* (VAR R: Rider; VAR x: REAL);
VAR b: ARRAY 4 OF CHAR;
BEGIN ReadBytes(R, b, 4); FlipBytes(b, x)
END ReadReal;
PROCEDURE ReadLReal* (VAR R: Rider; VAR x: LONGREAL);
VAR b: ARRAY 8 OF CHAR;
BEGIN ReadBytes(R, b, 8); FlipBytes(b, x)
END ReadLReal;
PROCEDURE ReadString* (VAR R: Rider; VAR x: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0;
REPEAT Read(R, ch); x[i] := ch; INC(i) UNTIL ch = 0X
END ReadString;
(* need to read line; -- noch *)
PROCEDURE ReadLine* (VAR R: Rider; VAR x: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR; b : BOOLEAN;
BEGIN i := 0;
b := FALSE;
REPEAT
Read(R, ch);
IF ((ch = 0X) OR (ch = 0AX) OR (ch = 0DX)) THEN
b := TRUE
ELSE
x[i] := ch;
INC(i);
END;
UNTIL b
END ReadLine;
PROCEDURE ReadNum* (VAR R: Rider; VAR x: LONGINT);
VAR s: SHORTINT; ch: CHAR; n: LONGINT;
BEGIN s := 0; n := 0; Read(R, ch);
WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); Read(R, ch) END;
INC(n, ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s) );
x := n
END ReadNum;
PROCEDURE WriteBool* (VAR R: Rider; x: BOOLEAN);
BEGIN Write(R, SYSTEM.VAL(CHAR, x))
END WriteBool;
(* PROCEDURE WriteInt* (VAR R: Rider; x: INTEGER);
VAR b: ARRAY 2 OF CHAR;
BEGIN b[0] := CHR(x); b[1] := CHR(x DIV 256);
WriteBytes(R, b, 2);
END WriteInt;
*)
PROCEDURE WriteInt* (VAR R: Rider; x: LONGINT); (* to compile OR compiler; -- noch *)
VAR b: ARRAY 4 OF CHAR;
BEGIN
b[0] := CHR(x); b[1] := CHR(x DIV 100H); b[2] := CHR(x DIV 10000H); b[3] := CHR(x DIV 1000000H);
WriteBytes(R, b, 4);
END WriteInt;
PROCEDURE WriteLInt* (VAR R: Rider; x: LONGINT);
VAR b: ARRAY 4 OF CHAR;
BEGIN
b[0] := CHR(x); b[1] := CHR(x DIV 100H); b[2] := CHR(x DIV 10000H); b[3] := CHR(x DIV 1000000H);
WriteBytes(R, b, 4);
END WriteLInt;
PROCEDURE WriteSet* (VAR R: Rider; x: SET);
VAR b: ARRAY 4 OF CHAR; i: LONGINT;
BEGIN i := SYSTEM.VAL(LONGINT, x);
b[0] := CHR(i); b[1] := CHR(i DIV 100H); b[2] := CHR(i DIV 10000H); b[3] := CHR(i DIV 1000000H);
WriteBytes(R, b, 4);
END WriteSet;
PROCEDURE WriteReal* (VAR R: Rider; x: REAL);
VAR b: ARRAY 4 OF CHAR;
BEGIN FlipBytes(x, b); WriteBytes(R, b, 4)
END WriteReal;
PROCEDURE WriteLReal* (VAR R: Rider; x: LONGREAL);
VAR b: ARRAY 8 OF CHAR;
BEGIN FlipBytes(x, b); WriteBytes(R, b, 8)
END WriteLReal;
PROCEDURE WriteString* (VAR R: Rider; x: ARRAY [1] OF CHAR);
VAR i: INTEGER;
BEGIN i := 0;
WHILE x[i] # 0X DO INC(i) END ;
WriteBytes(R, x, i+1)
END WriteString;
PROCEDURE WriteNum* (VAR R: Rider; x: LONGINT);
BEGIN
WHILE (x < - 64) OR (x > 63) DO Write(R, CHR(x MOD 128 + 128)); x := x DIV 128 END;
Write(R, CHR(x MOD 128))
END WriteNum;
PROCEDURE GetName*(f: File; VAR name: ARRAY OF CHAR);
BEGIN
COPY (f.workName, name);
END GetName;
PROCEDURE Finalize(o: SYSTEM.PTR);
VAR f: File; res: LONGINT;
BEGIN
f := SYSTEM.VAL(File, o);
IF f.fd >= 0 THEN
fileTab[f.fd] := 0; res := Unix.Close(f.fd); f.fd := -1; DEC(Kernel.nofiles);
IF f.tempFile THEN res := Unix.Unlink(f.workName) END
END
END Finalize;
PROCEDURE Init;
VAR i: LONGINT;
BEGIN
i := 0; WHILE i < fileTabSize DO fileTab[i] := 0; INC(i) END ;
tempno := -1; Kernel.nofiles := 0
END Init;
BEGIN Init
END CompatFiles.

581
src/voc07R/CompatTexts.Mod Normal file
View file

@ -0,0 +1,581 @@
MODULE CompatTexts; (*JG 21.11.90 / NW 11.7.90 / 24.12.95 / 22.11.10 / 26.3.2014*)
IMPORT Files := CompatFiles, Fonts;
TYPE INTEGER = LONGINT; (* voc adaptation by noch *)
BYTE = CHAR;
CONST (*scanner symbol classes*)
Inval* = 0; (*invalid symbol*)
Name* = 1; (*name s (length len)*)
String* = 2; (*literal string s (length len)*)
Int* = 3; (*integer i (decimal or hexadecimal)*)
Real* = 4; (*real number x*)
Char* = 6; (*special character c*)
(* TextBlock = TextTag "1" offset run {run} "0" len {AsciiCode}.
run = fnt [name] col voff len. *)
TAB = 9X; CR = 0DX; maxD = 9;
TextTag = 0F1X;
replace* = 0; insert* = 1; delete* = 2; unmark* = 3; (*op-codes*)
TYPE Piece = POINTER TO PieceDesc;
PieceDesc = RECORD
f: Files.File;
off, len: LONGINT;
fnt: Fonts.Font;
col, voff: INTEGER;
prev, next: Piece
END;
Text* = POINTER TO TextDesc;
Notifier* = PROCEDURE (T: Text; op: INTEGER; beg, end: LONGINT);
TextDesc* = RECORD
len*: LONGINT;
changed*: BOOLEAN;
notify*: Notifier;
trailer: Piece;
pce: Piece; (*cache*)
org: LONGINT; (*cache*)
END;
Reader* = RECORD
eot*: BOOLEAN;
fnt*: Fonts.Font;
col*, voff*: INTEGER;
ref: Piece;
org: LONGINT;
off: LONGINT;
rider: Files.Rider
END;
Scanner* = RECORD (Reader)
nextCh*: CHAR;
line*, class*: INTEGER;
i*: LONGINT;
x*: REAL;
y*: LONGREAL;
c*: CHAR;
len*: INTEGER;
s*: ARRAY 32 OF CHAR
END;
Buffer* = POINTER TO BufDesc;
BufDesc* = RECORD
len*: LONGINT;
header, last: Piece
END;
Writer* = RECORD
buf*: Buffer;
fnt*: Fonts.Font;
col*, voff*: INTEGER;
rider: Files.Rider
END;
VAR TrailerFile: Files.File;
(* voc adaptation by noch *)
PROCEDURE FLOOR(x : REAL): INTEGER;
BEGIN
RETURN ENTIER(x)
END FLOOR;
PROCEDURE LSL (x, n : INTEGER): INTEGER;
BEGIN
RETURN ASH(x, n);
END LSL;
PROCEDURE ASR (x, n : INTEGER): INTEGER;
BEGIN
RETURN ASH(x, n);
END ASR;
(* -------------------- Filing ------------------------*)
PROCEDURE Trailer(): Piece;
VAR Q: Piece;
BEGIN NEW(Q);
Q.f := TrailerFile; Q.off := -1; Q.len := 1; Q.fnt := NIL; Q.col := 0; Q.voff := 0; RETURN Q
END Trailer;
PROCEDURE Load* (VAR R: Files.Rider; T: Text);
VAR Q, q, p: Piece;
off: LONGINT;
N, fno: INTEGER; bt: BYTE;
f: Files.File;
FName: ARRAY 32 OF CHAR;
Dict: ARRAY 32 OF Fonts.Font;
BEGIN f := Files.Base(R); N := 1; Q := Trailer(); p := Q;
Files.ReadInt(R, off); Files.ReadByte(R, bt);
(*fno := bt;*)
fno := ORD(bt); (* voc adaptation by noch *)
WHILE fno # 0 DO
IF fno = N THEN
Files.ReadString(R, FName);
Dict[N] := Fonts.This(FName); INC(N)
END;
NEW(q); q.fnt := Dict[fno];
Files.ReadByte(R, bt);
(*q.col := bt;*)
q.col := ORD(bt); (* voc adaptation by noch *)
Files.ReadByte(R, bt);
(*q.voff := ASR(LSL(bt, -24), 24);*)
q.voff := ASR(LSL(ORD(bt), -24), 24); (* voc adaptation by noch *)
Files.ReadInt(R, q.len);
Files.ReadByte(R, bt);
(*fno := bt;*)
fno := ORD(bt); (* voc adaptation by noch *)
q.f := f; q.off := off; off := off + q.len;
p.next := q; q.prev := p; p := q
END;
p.next := Q; Q.prev := p;
T.trailer := Q; Files.ReadInt(R, T.len); (*Files.Set(R, f, Files.Pos(R) + T.len)*)
END Load;
PROCEDURE Open* (T: Text; name: ARRAY OF CHAR);
VAR f: Files.File; R: Files.Rider; Q, q: Piece;
tag: CHAR; len: LONGINT;
BEGIN f := Files.Old(name);
IF f # NIL THEN
Files.Set(R, f, 0); Files.Read(R, tag);
IF tag = TextTag THEN Load(R, T)
ELSE (*Ascii file*)
len := Files.Length(f); Q := Trailer();
NEW(q); q.fnt := Fonts.Default; q.col := 1; q.voff := 0; q.f := f; q.off := 0; q.len := len;
Q.next := q; q.prev := Q; q.next := Q; Q.prev := q; T.trailer := Q; T.len := len
END
ELSE (*create new text*)
Q := Trailer(); Q.next := Q; Q.prev := Q; T.trailer := Q; T.len := 0
END ;
T.changed := FALSE; T.org := -1; T.pce := T.trailer (*init cache*)
END Open;
PROCEDURE Store* (VAR W: Files.Rider; T: Text);
VAR p, q: Piece;
R: Files.Rider;
off, rlen, pos: LONGINT;
N, n: INTEGER;
ch: CHAR;
Dict: ARRAY 32, 32 OF CHAR;
BEGIN pos := Files.Pos(W); Files.WriteInt(W, 0); (*place holder*)
N := 1; p := T.trailer.next;
WHILE p # T.trailer DO
rlen := p.len; q := p.next;
WHILE (q # T.trailer) & (q.fnt = p.fnt) & (q.col = p.col) & (q.voff = p.voff) DO
rlen := rlen + q.len; q := q.next
END;
(*Dict[N] := p.fnt.name;*)
COPY(p.fnt.name, Dict[N]); (* voc adaptation by noch *)
n := 1;
WHILE Dict[n] # p.fnt.name DO INC(n) END;
(*Files.WriteByte(W, n);*)
Files.WriteByte(W, SHORT(SHORT(n))); (* voc adaptation by noch *)
IF n = N THEN Files.WriteString(W, p.fnt.name); INC(N) END;
(*Files.WriteByte(W, p.col);*)
Files.WriteByte(W, SHORT(SHORT(p.col))); (* voc adaptation by noch *)
(*Files.WriteByte(W, p.voff);*)
Files.WriteByte(W, SHORT(SHORT(p.voff))); (* voc adaptation by noch *)
Files.WriteInt(W, rlen);
p := q
END;
Files.WriteByte(W, 0); Files.WriteInt(W, T.len);
off := Files.Pos(W); p := T.trailer.next;
WHILE p # T.trailer DO
rlen := p.len; Files.Set(R, p.f, p.off);
WHILE rlen > 0 DO Files.Read(R, ch); Files.Write(W, ch); DEC(rlen) END ;
p := p.next
END ;
Files.Set(W, Files.Base(W), pos); Files.WriteInt(W, off); (*fixup*)
T.changed := FALSE;
IF T.notify # NIL THEN T.notify(T, unmark, 0, 0) END
END Store;
PROCEDURE Close*(T: Text; name: ARRAY OF CHAR);
VAR f: Files.File; w: Files.Rider;
BEGIN f := Files.New(name); Files.Set(w, f, 0);
Files.Write(w, TextTag); Store(w, T); Files.Register(f)
END Close;
(* -------------------- Editing ----------------------- *)
PROCEDURE OpenBuf* (B: Buffer);
BEGIN NEW(B.header); (*null piece*)
B.last := B.header; B.len := 0
END OpenBuf;
PROCEDURE FindPiece (T: Text; pos: LONGINT; VAR org: LONGINT; VAR pce: Piece);
VAR p: Piece; porg: LONGINT;
BEGIN p := T.pce; porg := T.org;
IF pos >= porg THEN
WHILE pos >= porg + p.len DO INC(porg, p.len); p := p.next END
ELSE p := p.prev; DEC(porg, p.len);
WHILE pos < porg DO p := p.prev; DEC(porg, p.len) END
END ;
T.pce := p; T.org := porg; (*update cache*)
pce := p; org := porg
END FindPiece;
PROCEDURE SplitPiece (p: Piece; off: LONGINT; VAR pr: Piece);
VAR q: Piece;
BEGIN
IF off > 0 THEN NEW(q);
q.fnt := p.fnt; q.col := p.col; q.voff := p.voff;
q.len := p.len - off;
q.f := p.f; q.off := p.off + off;
p.len := off;
q.next := p.next; p.next := q;
q.prev := p; q.next.prev := q;
pr := q
ELSE pr := p
END
END SplitPiece;
PROCEDURE Save* (T: Text; beg, end: LONGINT; B: Buffer);
VAR p, q, qb, qe: Piece; org: LONGINT;
BEGIN
IF end > T.len THEN end := T.len END;
FindPiece(T, beg, org, p);
NEW(qb); qb^ := p^;
qb.len := qb.len - (beg - org);
qb.off := qb.off + (beg - org);
qe := qb;
WHILE end > org + p.len DO
org := org + p.len; p := p.next;
NEW(q); q^ := p^; qe.next := q; q.prev := qe; qe := q
END;
qe.next := NIL; qe.len := qe.len - (org + p.len - end);
B.last.next := qb; qb.prev := B.last; B.last := qe;
B.len := B.len + (end - beg)
END Save;
PROCEDURE Copy* (SB, DB: Buffer);
VAR Q, q, p: Piece;
BEGIN p := SB.header; Q := DB.last;
WHILE p # SB.last DO p := p.next;
NEW(q); q^ := p^; Q.next := q; q.prev := Q; Q := q
END;
DB.last := Q; DB.len := DB.len + SB.len
END Copy;
PROCEDURE Insert* (T: Text; pos: LONGINT; B: Buffer);
VAR pl, pr, p, qb, qe: Piece; org, end: LONGINT;
BEGIN
FindPiece(T, pos, org, p); SplitPiece(p, pos - org, pr);
IF T.org >= org THEN T.org := org - p.prev.len; T.pce := p.prev END ;
pl := pr.prev; qb := B.header.next;
IF (qb # NIL) & (qb.f = pl.f) & (qb.off = pl.off + pl.len)
& (qb.fnt = pl.fnt) & (qb.col = pl.col) & (qb.voff = pl.voff) THEN
pl.len := pl.len + qb.len; qb := qb.next
END;
IF qb # NIL THEN qe := B.last;
qb.prev := pl; pl.next := qb; qe.next := pr; pr.prev := qe
END;
T.len := T.len + B.len; end := pos + B.len;
B.last := B.header; B.last.next := NIL; B.len := 0;
T.changed := TRUE;
(*T.notify(T, insert, pos, end)*)
IF T.notify # NIL THEN
T.notify(T, insert, pos, end)
END(* voc adaptation by noch *)
END Insert;
PROCEDURE Append* (T: Text; B: Buffer);
BEGIN Insert(T, T.len, B)
END Append;
PROCEDURE Delete* (T: Text; beg, end: LONGINT; B: Buffer);
VAR pb, pe, pbr, per: Piece; orgb, orge: LONGINT;
BEGIN
IF end > T.len THEN end := T.len END;
FindPiece(T, beg, orgb, pb); SplitPiece(pb, beg - orgb, pbr);
FindPiece(T, end, orge, pe);
SplitPiece(pe, end - orge, per);
IF T.org >= orgb THEN (*adjust cache*)
T.org := orgb - pb.prev.len; T.pce := pb.prev
END;
B.header.next := pbr; B.last := per.prev;
B.last.next := NIL; B.len := end - beg;
per.prev := pbr.prev; pbr.prev.next := per;
T.len := T.len - B.len;
T.changed := TRUE;
IF T.notify # NIL THEN (* noch *)
T.notify(T, delete, beg, end)
END
END Delete;
PROCEDURE ChangeLooks* (T: Text; beg, end: LONGINT; sel: SET; fnt: Fonts.Font; col, voff: INTEGER);
VAR pb, pe, p: Piece; org: LONGINT;
BEGIN
IF end > T.len THEN end := T.len END;
FindPiece(T, beg, org, p); SplitPiece(p, beg - org, pb);
FindPiece(T, end, org, p); SplitPiece(p, end - org, pe);
p := pb;
REPEAT
IF 0 IN sel THEN p.fnt := fnt END;
IF 1 IN sel THEN p.col := col END;
IF 2 IN sel THEN p.voff := voff END;
p := p.next
UNTIL p = pe;
T.changed := TRUE;
IF T.notify # NIL THEN (* noch *)
T.notify(T, replace, beg, end)
END
END ChangeLooks;
PROCEDURE Attributes*(T: Text; pos: LONGINT; VAR fnt: Fonts.Font; VAR col, voff: INTEGER);
VAR p: Piece; org: LONGINT;
BEGIN FindPiece(T, pos, org, p); fnt := p.fnt; col := p.col; voff := p.voff
END Attributes;
(* ------------------ Access: Readers ------------------------- *)
PROCEDURE OpenReader* (VAR R: Reader; T: Text; pos: LONGINT);
VAR p: Piece; org: LONGINT;
BEGIN FindPiece(T, pos, org, p);
R.ref := p; R.org := org; R.off := pos - org;
Files.Set(R.rider, p.f, p.off + R.off); R.eot := FALSE
END OpenReader;
PROCEDURE Read* (VAR R: Reader; VAR ch: CHAR);
BEGIN Files.Read(R.rider, ch);
R.fnt := R.ref.fnt; R.col := R.ref.col; R.voff := R.ref.voff;
INC(R.off);
IF R.off = R.ref.len THEN
IF R.ref.f = TrailerFile THEN R.eot := TRUE END;
R.org := R.org + R.off; R.off := 0;
R.ref := R.ref.next; R.org := R.org + R.off; R.off := 0;
Files.Set(R.rider, R.ref.f, R.ref.off)
END
END Read;
PROCEDURE Pos* (VAR R: Reader): LONGINT;
BEGIN RETURN R.org + R.off
END Pos;
(* ------------------ Access: Scanners (NW) ------------------------- *)
PROCEDURE OpenScanner* (VAR S: Scanner; T: Text; pos: LONGINT);
BEGIN OpenReader(S, T, pos); S.line := 0; S.nextCh := " "
END OpenScanner;
(*floating point formats:
x = 1.m * 2^(e-127) bit 0: sign, bits 1- 8: e, bits 9-31: m
x = 1.m * 2^(e-1023) bit 0: sign, bits 1-11: e, bits 12-63: m *)
PROCEDURE Ten(n: INTEGER): REAL;
VAR t, p: REAL;
BEGIN t := 1.0; p := 10.0; (*compute 10^n *)
WHILE n > 0 DO
IF ODD(n) THEN t := p * t END ;
p := p*p; n := n DIV 2
END ;
RETURN t
END Ten;
PROCEDURE Scan* (VAR S: Scanner);
CONST maxExp = 38; maxM = 16777216; (*2^24*)
VAR ch, term: CHAR;
neg, negE, hex: BOOLEAN;
i, j, h, d, e, n, s: INTEGER;
k: LONGINT;
x: REAL;
BEGIN ch := S.nextCh; i := 0;
WHILE (ch = " ") OR (ch = TAB) OR (ch = CR) DO
IF ch = CR THEN INC(S.line) END ;
Read(S, ch)
END ;
IF ("A" <= ch) & (ch <= "Z") OR ("a" <= ch) & (ch <= "z") THEN (*name*)
REPEAT S.s[i] := ch; INC(i); Read(S, ch)
UNTIL ((ch < "0") & (ch # ".") OR ("9" < ch) & (ch < "A") OR ("Z" < ch) & (ch < "a") OR ("z" < ch)) OR (i = 31);
S.s[i] := 0X; S.len := i; S.class := Name
ELSIF ch = 22X THEN (*string*)
Read(S, ch);
WHILE (ch # 22X) & (ch >= " ") & (i # 31) DO S.s[i] := ch; INC(i); Read(S, ch) END;
S.s[i] := 0X; S.len := i+1; Read(S, ch); S.class := String
ELSE hex := FALSE;
IF ch = "-" THEN neg := TRUE; Read(S, ch) ELSE neg := FALSE END ;
IF ("0" <= ch) & (ch <= "9") THEN (*number*)
n := ORD(ch) - 30H; h := n; Read(S, ch);
WHILE ("0" <= ch) & (ch <= "9") OR ("A" <= ch) & (ch <= "F") DO
IF ch <= "9" THEN d := ORD(ch) - 30H ELSE d := ORD(ch) - 37H; hex := TRUE END ;
n := 10*n + d; h := 10H*h + d; Read(S, ch)
END ;
IF ch = "H" THEN (*hex integer*) Read(S, ch); S.i := h; S.class := Int (*neg?*)
ELSIF ch = "." THEN (*real number*)
Read(S, ch); x := 0.0; e := 0; j := 0;
WHILE ("0" <= ch) & (ch <= "9") DO (*fraction*)
h := 10*n + (ORD(ch) - 30H);
IF h < maxM THEN n := h; INC(j) END ;
Read(S, ch)
END ;
IF ch = "E" THEN (*scale factor*)
s := 0; Read(S, ch);
IF ch = "-" THEN negE := TRUE; Read(S, ch)
ELSE negE := FALSE;
IF ch = "+" THEN Read(S, ch) END
END ;
WHILE ("0" <= ch) & (ch <= "9") DO
s := s*10 + ORD(ch) - 30H; Read(S, ch)
END ;
IF negE THEN DEC(e, s) ELSE INC(e, s) END ;
END ;
(*x := FLT(n);*)
x := n; (* voc adaptation by noch *)
DEC(e, j);
IF e < 0 THEN
IF e >= -maxExp THEN x := x / Ten(-e) ELSE x := 0.0 END
ELSIF e > 0 THEN
IF e <= maxExp THEN x := Ten(e) * x ELSE x := 0.0 END
END ;
IF neg THEN S.x := -x ELSE S.x := x END ;
IF hex THEN S.class := 0 ELSE S.class := Real END
ELSE (*decimal integer*)
IF neg THEN S.i := -n ELSE S.i := n END;
IF hex THEN S.class := Inval ELSE S.class := Int END
END
ELSE (*spectal character*) S.class := Char;
IF neg THEN S.c := "-" ELSE S.c := ch; Read(S, ch) END
END
END ;
S.nextCh := ch
END Scan;
(* --------------- Access: Writers (NW) ------------------ *)
PROCEDURE OpenWriter* (VAR W: Writer);
BEGIN NEW(W.buf);
OpenBuf(W.buf); W.fnt := Fonts.Default; W.col := 15; W.voff := 0;
Files.Set(W.rider, Files.New(""), 0)
END OpenWriter;
PROCEDURE SetFont* (VAR W: Writer; fnt: Fonts.Font);
BEGIN W.fnt := fnt
END SetFont;
PROCEDURE SetColor* (VAR W: Writer; col: INTEGER);
BEGIN W.col := col
END SetColor;
PROCEDURE SetOffset* (VAR W: Writer; voff: INTEGER);
BEGIN W.voff := voff
END SetOffset;
PROCEDURE Write* (VAR W: Writer; ch: CHAR);
VAR p: Piece;
BEGIN
IF (W.buf.last.fnt # W.fnt) OR (W.buf.last.col # W.col) OR (W.buf.last.voff # W.voff) THEN
NEW(p); p.f := Files.Base(W.rider); p.off := Files.Pos(W.rider); p.len := 0;
p.fnt := W.fnt; p.col := W.col; p.voff:= W.voff;
p.next := NIL; W.buf.last.next := p;
p.prev := W.buf.last; W.buf.last := p
END;
Files.Write(W.rider, ch);
INC(W.buf.last.len); INC(W.buf.len)
END Write;
PROCEDURE WriteLn* (VAR W: Writer);
BEGIN Write(W, CR)
END WriteLn;
PROCEDURE WriteString* (VAR W: Writer; s: ARRAY OF CHAR);
VAR i: INTEGER;
BEGIN i := 0;
WHILE s[i] >= " " DO Write(W, s[i]); INC(i) END
END WriteString;
PROCEDURE WriteInt* (VAR W: Writer; x, n: LONGINT);
VAR i: INTEGER; x0: LONGINT;
a: ARRAY 10 OF CHAR;
BEGIN
(*IF ROR(x, 31) = 1 THEN WriteString(W, " -2147483648")
ELSE*) i := 0; (* voc adaptation by noch *)
IF x < 0 THEN DEC(n); x0 := -x ELSE x0 := x END;
REPEAT
a[i] := CHR(x0 MOD 10 + 30H); x0 := x0 DIV 10; INC(i)
UNTIL x0 = 0;
WHILE n > i DO Write(W, " "); DEC(n) END;
IF x < 0 THEN Write(W, "-") END;
REPEAT DEC(i); Write(W, a[i]) UNTIL i = 0
(*END*)
END WriteInt;
PROCEDURE WriteHex* (VAR W: Writer; x: LONGINT);
VAR i: INTEGER; y: LONGINT;
a: ARRAY 10 OF CHAR;
BEGIN i := 0; Write(W, " ");
REPEAT y := x MOD 10H;
IF y < 10 THEN a[i] := CHR(y + 30H) ELSE a[i] := CHR(y + 37H) END;
x := x DIV 10H; INC(i)
UNTIL i = 8;
REPEAT DEC(i); Write(W, a[i]) UNTIL i = 0
END WriteHex;
(* commented out because it's not necessary to compile OR compiler; -- noch
PROCEDURE WriteReal* (VAR W: Writer; x: REAL; n: INTEGER);
VAR e, i, m: INTEGER; x0: REAL; neg: BOOLEAN;
d: ARRAY 16 OF CHAR;
BEGIN
IF x = 0.0 THEN
WriteString(W, " 0.0"); i := 5;
WHILE i < n DO Write(W, " "); INC(i) END
ELSE
IF x < 0.0 THEN x := -x; neg := TRUE ELSE neg := FALSE END ;
x0 := x; UNPK(x0, e);
IF e = 255 THEN WriteString(W, " NaN")
ELSE
REPEAT Write(W, " "); DEC(n) UNTIL n <= 14;
IF neg THEN Write(W, "-") ELSE Write(W, " ") END ;
e := e * 77 DIV 256 - 6;
IF e >= 0 THEN x := x / Ten(e) ELSE x := x * Ten(-e) END ;
IF x >= 10.0E6 THEN x := 0.1*x; INC(e) END ;
m := FLOOR(x + 0.5); i := 0;
IF x >= 10.0E6 THEN x := 0.1*x; INC(e) END ;
REPEAT d[i] := CHR(m MOD 10 + 30H); m := m DIV 10; INC(i) UNTIL m = 0;
DEC(i); Write(W, d[i]); Write(W, ".");
IF i < n-6 THEN n := 0 ELSE n := 13-n END ;
WHILE i > n DO DEC(i); Write(W, d[i]) END ;
Write(W, "E"); INC(e, 6);
IF e < 0 THEN Write(W, "-"); e := -e ELSE Write(W, "+") END ;
Write(W, CHR(e DIV 10 + 30H)); Write(W, CHR(e MOD 10 + 30H))
END
END
END WriteReal;
*)
PROCEDURE WriteRealFix* (VAR W: Writer; x: REAL; n, k: INTEGER);
VAR i, m: INTEGER; neg: BOOLEAN;
d: ARRAY 12 OF CHAR;
BEGIN
IF x = 0.0 THEN WriteString(W, " 0")
ELSE
IF x < 0.0 THEN x := -x; neg := TRUE ELSE neg := FALSE END ;
IF k > 7 THEN k := 7 END ;
x := Ten(k) * x; m := FLOOR(x + 0.5);
i := 0;
REPEAT d[i] := CHR(m MOD 10 + 30H); m := m DIV 10; INC(i) UNTIL m = 0;
REPEAT Write(W, " "); DEC(n) UNTIL n <= i+3;
IF neg THEN Write(W, "-"); DEC(n) ELSE Write(W, " ") END ;
WHILE i > k DO DEC(i); Write(W, d[i]) END ;
Write(W, ".");
WHILE k > i DO DEC(k); Write(W, "0") END ;
WHILE i > 0 DO DEC(i); Write(W, d[i]) END
END
END WriteRealFix;
PROCEDURE WritePair(VAR W: Writer; ch: CHAR; x: LONGINT);
BEGIN Write(W, ch);
Write(W, CHR(x DIV 10 + 30H)); Write(W, CHR(x MOD 10 + 30H))
END WritePair;
PROCEDURE WriteClock* (VAR W: Writer; d: LONGINT);
BEGIN
WritePair(W, " ", d DIV 20000H MOD 20H); (*day*)
WritePair(W, ".", d DIV 400000H MOD 10H); (*month*)
WritePair(W, ".", d DIV 4000000H MOD 40H); (*year*)
WritePair(W, " ", d DIV 1000H MOD 20H); (*hour*)
WritePair(W, ":", d DIV 40H MOD 40H); (*min*)
WritePair(W, ":", d MOD 40H) (*sec*)
END WriteClock;
BEGIN TrailerFile := Files.New("")
END CompatTexts.

146
src/voc07R/Fonts.Mod Normal file
View file

@ -0,0 +1,146 @@
MODULE Fonts; (*JG 18.11.90; PDR 8.6.12; NW 25.3.2013*)
IMPORT SYSTEM, Files := CompatFiles;
TYPE INTEGER = LONGINT; (* voc adaptation by noch *)
BYTE = CHAR;
CONST FontFileId = 0DBH;
TYPE Font* = POINTER TO FontDesc;
FontDesc* = RECORD
name*: ARRAY 32 OF CHAR;
height*, minX*, maxX*, minY*, maxY*: INTEGER;
next*: Font;
T: ARRAY 128 OF INTEGER;
raster: ARRAY 2360 OF BYTE
END ;
LargeFontDesc = RECORD (FontDesc) ext: ARRAY 2560 OF BYTE END ;
LargeFont = POINTER TO LargeFontDesc;
(* raster sizes: Syntax8 1367, Syntax10 1628, Syntax12 1688, Syntax14 1843, Syntax14b 1983,
Syntax16 2271, Syntax20 3034, Syntac24 4274, Syntax24b 4302 *)
VAR Default*, root*: Font;
PROCEDURE GetPat*(fnt: Font; ch: CHAR; VAR dx, x, y, w, h, patadr: INTEGER);
VAR pa: INTEGER; dxb, xb, yb, wb, hb: BYTE;
BEGIN pa := fnt.T[ORD(ch) MOD 80H]; patadr := pa;
SYSTEM.GET(pa-3, dxb); SYSTEM.GET(pa-2, xb); SYSTEM.GET(pa-1, yb); SYSTEM.GET(pa, wb); SYSTEM.GET(pa+1, hb);
(*dx := dxb;*)
dx := ORD(dxb); (* voc adaptation by noch *)
(*x := xb;*)
x := ORD(xb); (* voc adaptation by noch *)
(*y := yb;*)
y := ORD(yb); (* voc adaptation by noch *)
(*w := wb;*)
w := ORD(wb); (* voc adaptation by noch *)
(*h := hb;*)
h := ORD(hb); (* voc adaptation by noch *)
(*IF yb < 128 THEN y := yb ELSE y := yb - 256 END*)
IF ORD(yb) < 128 THEN y := ORD(yb) ELSE y := ORD(yb) - 256 END (* voc adaptation by noch *)
END GetPat;
PROCEDURE This*(name: ARRAY OF CHAR): Font;
TYPE RunRec = RECORD beg, end: BYTE END ;
BoxRec = RECORD dx, x, y, w, h: BYTE END ;
VAR F: Font; LF: LargeFont;
f: Files.File; R: Files.Rider;
NofRuns, NofBoxes: BYTE;
NofBytes: INTEGER;
height, minX, maxX, minY, maxY: BYTE;
i, j, k, m, n: INTEGER;
a, a0: INTEGER;
b, beg, end: BYTE;
run: ARRAY 16 OF RunRec;
box: ARRAY 512 OF BoxRec;
PROCEDURE RdInt16(VAR R: Files.Rider; VAR b0: BYTE);
VAR b1: BYTE;
BEGIN Files.ReadByte(R, b0); Files.ReadByte(R, b1)
END RdInt16;
BEGIN F := root;
WHILE (F # NIL) & (name # F.name) DO F := F.next END;
IF F = NIL THEN
f := Files.Old(name);
IF f # NIL THEN
Files.Set(R, f, 0); Files.ReadByte(R, b);
(*IF b = FontFileId THEN*)
IF ORD(b) = FontFileId THEN (* voc adaptation by noch *)
Files.ReadByte(R, b); (*abstraction*)
Files.ReadByte(R, b); (*family*)
Files.ReadByte(R, b); (*variant*)
NEW(F);
(*F.name := name;*)
COPY(name, F.name); (* voc adaptation by noch *)
RdInt16(R, height); RdInt16(R, minX); RdInt16(R, maxX); RdInt16(R, minY); RdInt16(R, maxY); RdInt16(R, NofRuns);
(*NofBoxes := 0;*) (* voc adaptation by noch *)
NofBoxes := 0X;
k := 0;
(*WHILE k # NofRuns DO*)
WHILE k # ORD(NofRuns) DO (* voc adaptation by noch *)
RdInt16(R, beg);
run[k].beg := beg; RdInt16(R, end);
run[k].end := end;
(*NofBoxes := NofBoxes + end - beg;*)
NofBoxes := CHR(ORD(NofBoxes) + ORD(end) - ORD(beg)); (* voc adaptation by noch *)
INC(k)
END;
NofBytes := 5; j := 0;
(*WHILE j # NofBoxes DO*)
WHILE j # ORD(NofBoxes) DO (* voc adaptation by noch *)
RdInt16(R, box[j].dx); RdInt16(R, box[j].x); RdInt16(R, box[j].y);
RdInt16(R, box[j].w); RdInt16(R, box[j].h);
(*NofBytes := NofBytes + 5 + (box[j].w + 7) DIV 8 * box[j].h;*)
NofBytes := (NofBytes + 5 + (ORD(box[j].w) + 7) DIV 8 * ORD(box[j].h)); (* voc adaptation by noch *)
INC(j)
END;
IF NofBytes < 2300 THEN NEW(F) ELSE NEW(LF); F := LF END ;
(*F.name := name;*)
COPY(name, F.name); (* voc adaptation by noch *)
(*F.height := height; F.minX := minX; F.maxX := maxX; F.maxY := maxY;*)
F.height := ORD(height); F.minX := ORD(minX); F.maxX := ORD(maxX); F.maxY := ORD(maxY); (* voc adaptation by noch *)
(*IF minY >= 80H THEN F.minY := minY - 100H ELSE F.minY := minY END ;*)
IF ORD(minY) >= 80H THEN F.minY := ORD(minY) - 100H ELSE F.minY := ORD(minY) END ; (* voc adaptation by noch *)
a0 := SYSTEM.ADR(F.raster);
SYSTEM.PUT(a0, 0X); SYSTEM.PUT(a0+1, 0X); SYSTEM.PUT(a0+2, 0X); SYSTEM.PUT(a0+3, 0X); SYSTEM.PUT(a0+4, 0X);
(*null pattern for characters not in a run*)
INC(a0, 2); a := a0+3; j := 0; k := 0; m := 0;
(*WHILE k < NofRuns DO*)
WHILE k < ORD(NofRuns) DO
(*WHILE (m < run[k].beg) & (m < 128) DO F.T[m] := a0; INC(m) END;*)
WHILE (m < ORD(run[k].beg)) & (m < 128) DO F.T[m] := a0; INC(m) END; (* voc adaptation by noch *)
(*WHILE (m < run[k].end) & (m < 128) DO*) (* voc adaptation by noch *)
WHILE (m < ORD(run[k].end)) & (m < 128) DO
F.T[m] := a+3;
SYSTEM.PUT(a, box[j].dx); SYSTEM.PUT(a+1, box[j].x); SYSTEM.PUT(a+2, box[j].y);
SYSTEM.PUT(a+3, box[j].w); SYSTEM.PUT(a+4, box[j].h); INC(a, 5);
(*n := (box[j].w + 7) DIV 8 * box[j].h;*)
n := (ORD(box[j].w) + 7) DIV 8 * ORD(box[j].h); (* voc adaptation by noch *)
WHILE n # 0 DO DEC(n); Files.ReadByte(R, b); SYSTEM.PUT(a, b); INC(a) END ;
INC(j); INC(m)
END;
INC(k)
END;
WHILE m < 128 DO F.T[m] := a0; INC(m) END ;
F.next := root; root := F
ELSE (*bad file id*) F := Default
END
ELSE (*font file not available*) F := Default
END
END;
RETURN F
END This;
PROCEDURE Free*; (*remove all but first two from font list*)
VAR f: Font;
BEGIN f := root.next;
IF f # NIL THEN f := f.next END ;
f.next := NIL
END Free;
BEGIN root := NIL; Default := This("Oberon10.Scn.Fnt")
END Fonts.

View file

@ -1,6 +1,6 @@
MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
IMPORT Files, ORS, S := SYSTEM;
TYPE BYTE = S.BYTE;
MODULE ORB; (*NW 25.6.2014 in Oberon-07*)
IMPORT Files := CompatFiles (* voc adaptation by noch *)
, ORS;
(*Definition of data types Object and Type, which together form the data structure
called "symbol table". Contains procedures for creation of Objects, and for search:
NewObj, this, thisimport, thisfield (and OpenScope, CloseScope).
@ -8,6 +8,9 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
Import and Export. This module contains the list of standard identifiers, with which
the symbol table (universe), and that of the pseudo-module SYSTEM are initialized. *)
TYPE INTEGER = LONGINT; (* voc adaptation by noch *)
BYTE = CHAR;
CONST versionkey* = 1; maxTypTab = 64;
(* class values*) Head* = 0;
Const* = 1; Var* = 2; Par* = 3; Fld* = 4; Typ* = 5;
@ -146,11 +149,9 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
PROCEDURE Read(VAR R: Files.Rider; VAR x: INTEGER);
VAR b: BYTE;
BEGIN
(*Files.ReadByte(R, b);*)
Files.ReadBytes(R, b, 1);
BEGIN Files.ReadByte(R, b);
(*IF b < 80H THEN x := b ELSE x := b - 100H END*)
IF S.VAL(SHORTINT, b) < 128 THEN x := S.VAL(SHORTINT, b) ELSE x := S.VAL(SHORTINT, b) - 100H END
IF b < 80X THEN x := ORD(b) ELSE x := ORD(b) - 100H END (* voc adaptation by noch *)
END Read;
PROCEDURE InType(VAR R: Files.Rider; thismod: Object; VAR T: Type);
@ -170,8 +171,7 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
InType(R, thismod, t.base);
IF t.base.form = NoTyp THEN t.base := NIL; obj := NIL ELSE obj := t.base.dsc END ;
Files.ReadNum(R, t.len); (*TD adr/exno*)
(*Files.ReadNum(R, t.nofpar);*) (*ext level*)
Files.ReadInt(R, t.nofpar); (*ext level*)
Files.ReadNum(R, t.nofpar); (*ext level*)
Files.ReadNum(R, t.size);
Read(R, class);
WHILE class # 0 DO (*fields*)
@ -191,15 +191,14 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
END ;
Files.ReadString(R, modname);
IF modname[0] # 0X THEN (*re-import*)
(*Files.ReadInt(R, key); Files.ReadString(R, name);*)
Files.ReadNum(R, key); Files.ReadString(R, name);
Files.ReadInt(R, key); Files.ReadString(R, name);
mod := ThisModule(modname, modname, FALSE, key);
obj := mod.dsc; (*search type*)
WHILE (obj # NIL) & (obj.name # name) DO obj := obj.next END ;
IF obj # NIL THEN T := obj.type (*type object found in object list of mod*)
ELSE (*insert new type object in object list of mod*)
NEW(obj); obj.name := name; obj.class := Typ; obj.next := mod.dsc; mod.dsc := obj; obj.type := t;
t.mno := mod.lev; T := t
t.mno := mod.lev; t.typobj := obj; T := t
END ;
typtab[ref] := T
END
@ -218,10 +217,7 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
thismod.lev := 0; thismod.dsc := system; thismod.rdo := TRUE
ELSE MakeFileName(fname, modid1, ".smb"); F := Files.Old(fname);
IF F # NIL THEN
Files.Set(R, F, 0);
(*Files.ReadInt(R, key); Files.ReadInt(R, key);*)
Files.ReadNum(R, key); Files.ReadNum(R, key);
Files.ReadString(R, modname);
Files.Set(R, F, 0); Files.ReadInt(R, key); Files.ReadInt(R, key); Files.ReadString(R, modname);
thismod := ThisModule(modid, modid1, TRUE, key); thismod.rdo := TRUE;
Read(R, class); (*version key*)
IF class # versionkey THEN ORS.Mark("wrong version") END ;
@ -234,12 +230,7 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
WHILE k # 0 DO typtab[k].base := t; Read(R, k) END
ELSE
IF class = Const THEN
IF obj.type.form = Real THEN
(*Files.ReadInt(R, obj.val) *)
Files.ReadNum(R, obj.val)
ELSE
Files.ReadNum(R, obj.val)
END
IF obj.type.form = Real THEN Files.ReadInt(R, obj.val) ELSE Files.ReadNum(R, obj.val) END
ELSIF class = Var THEN Files.ReadNum(R, obj.val); obj.rdo := TRUE
END
END ;
@ -254,8 +245,8 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
PROCEDURE Write(VAR R: Files.Rider; x: INTEGER);
BEGIN
(*Files.WriteByte(R, x)*) (* -128 <= x < 128 *)
Files.WriteByte(R, SHORT(x)) (* -128 <= x < 128 *)
(*Files.WriteByte(R, x)*)
Files.WriteByte(R, SHORT(SHORT(x))) (* voc adaptation by noch *)
END Write;
PROCEDURE OutType(VAR R: Files.Rider; t: Type);
@ -288,11 +279,7 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
ELSE obj := t.typobj;
IF obj # NIL THEN Write(R, Ref); t.ref := Ref; INC(Ref) ELSE (*anonymous*) Write(R, 0) END ;
Write(R, t.form);
IF t.form = Pointer THEN
IF t.base.ref > 0 THEN Write(R, -t.base.ref)
ELSIF (t.base.typobj = NIL) OR ~t.base.typobj.expo THEN (*base not exported*) Write(R, -1)
ELSE OutType(R, t.base)
END
IF t.form = Pointer THEN OutType(R, t.base)
ELSIF t.form = Array THEN OutType(R, t.base); Files.WriteNum(R, t.len); Files.WriteNum(R, t.size)
ELSIF t.form = Record THEN
IF t.base # NIL THEN OutType(R, t.base) ELSE OutType(R, noType) END ;
@ -302,20 +289,17 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
WHILE fld # NIL DO (*fields*)
IF fld.expo THEN
Write(R, Fld); Files.WriteString(R, fld.name); OutType(R, fld.type); Files.WriteNum(R, fld.val)
ELSE FindHiddenPointers(R, fld.type, fld.val)
ELSE FindHiddenPointers(R, fld.type, fld.val) (*offset*)
END ;
fld := fld.next
END ;
Write(R, 0)
Write(R, 0)
ELSIF t.form = Proc THEN OutType(R, t.base); OutPar(R, t.dsc, t.nofpar); Write(R, 0)
END ;
IF (t.mno > 0) & (obj # NIL) THEN (*re-export, output name*)
mod := topScope.next;
WHILE (mod # NIL) & (mod.lev # t.mno) DO mod := mod.next END ;
IF mod # NIL THEN Files.WriteString(R, mod.name);
(*Files.WriteInt(R, mod.val); *)
Files.WriteNum(R, mod.val);
Files.WriteString(R, obj.name)
IF mod # NIL THEN Files.WriteString(R, mod.name); Files.WriteInt(R, mod.val); Files.WriteString(R, obj.name)
ELSE ORS.Mark("re-export not found"); Write(R, 0)
END
ELSE Write(R, 0)
@ -349,9 +333,7 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
Write(R, 0)
ELSIF obj.class = Const THEN
IF obj.type.form = Proc THEN Files.WriteNum(R, obj.exno)
ELSIF obj.type.form = Real THEN
(*Files.WriteInt(R, obj.val)*)
Files.WriteNum(R, obj.val)
ELSIF obj.type.form = Real THEN Files.WriteInt(R, obj.val)
ELSE Files.WriteNum(R, obj.val)
END
ELSIF obj.class = Var THEN
@ -365,26 +347,13 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
END ;
REPEAT Write(R, 0) UNTIL Files.Length(F) MOD 4 = 0;
FOR Ref := Record+1 TO maxTypTab-1 DO typtab[Ref] := NIL END ;
Files.Set(R, F, 0); sum := 0; (* compute key (checksum) *)
WHILE ~R.eof DO
(*Files.ReadInt(R, x); *)
Files.ReadNum (R, x);
sum := sum + x
END ;
Files.Set(R, F, 0); sum := 0; Files.ReadInt(R, x); (* compute key (checksum) *)
WHILE ~R.eof DO sum := sum + x; Files.ReadInt(R, x) END ;
F1 := Files.Old(filename); (*sum is new key*)
IF F1 # NIL THEN
Files.Set(R1, F1, 4);
(*Files.ReadInt(R1, oldkey) *)
Files.ReadNum(R1, oldkey)
ELSE
oldkey := sum+1
END ;
IF F1 # NIL THEN Files.Set(R1, F1, 4); Files.ReadInt(R1, oldkey) ELSE oldkey := sum+1 END ;
IF sum # oldkey THEN
IF newSF THEN
key := sum; Files.Set(R, F, 4);
(*Files.WriteInt(R, sum); *)
Files.WriteNum(R, sum);
Files.Register(F) (*insert checksum*)
IF newSF OR (F1 = NIL) THEN
key := sum; newSF := TRUE; Files.Set(R, F, 4); Files.WriteInt(R, sum); Files.Register(F) (*insert checksum*)
ELSE ORS.Mark("new symbol file inhibited")
END
ELSE newSF := FALSE; key := sum
@ -406,8 +375,11 @@ MODULE ORB; (*NW 7.10.2013 in Oberon-07*)
BEGIN
NEW(obj);
(*obj.name := name; *)
COPY(name, obj.name);
obj.class := cl; obj.type := type; obj.val := n; obj.dsc := NIL;
COPY(name, obj.name); (* voc adaptation by noch *)
obj.class := cl;
obj.type := type;
obj.val := n;
obj.dsc := NIL;
IF cl = Typ THEN type.typobj := obj END ;
obj.next := system; system := obj
END enter;
@ -425,7 +397,7 @@ BEGIN
(*initialize universe with data types and in-line procedures;
LONGINT is synonym to INTEGER, LONGREAL to REAL.
LED, ADC, SBC; LDPSR, LDREG, REG, COND, MSK are not in language definition*)
LED, ADC, SBC; LDPSR, LDREG, REG, COND are not in language definition*)
system := NIL; (*n = procno*10 + nofpar*)
enter("UML", SFunc, intType, 132); (*functions*)
enter("SBC", SFunc, intType, 122);

View file

@ -1,206 +0,0 @@
MODULE ORC; (*Connection to RISC; NW 11.11.2013*)
IMPORT SYSTEM, Files, Texts, Oberon, V24;
CONST portno = 1; (*RS-232*)
BlkLen = 255; pno = 1;
REQ = 20X; REC = 21X; SND = 22X; CLS = 23X; ACK = 10X;
Tout = 1000;
VAR res: LONGINT;
W: Texts.Writer;
PROCEDURE Flush*;
VAR ch: CHAR;
BEGIN
WHILE V24.Available(portno) > 0 DO V24.Receive(portno, ch, res); Texts.Write(W, ch) END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END Flush;
PROCEDURE Open*;
VAR ch: CHAR;
BEGIN V24.Start(pno, 19200, 8, V24.ParNo, V24.Stop1, res);
WHILE V24.Available(pno) > 0 DO V24.Receive(pno, ch, res) END ;
IF res > 0 THEN Texts.WriteString(W, "open V24, error ="); Texts.WriteInt(W, res, 4)
ELSE Texts.WriteString(W, "connection open")
END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END Open;
PROCEDURE TestReq*;
VAR ch: CHAR;
BEGIN V24.Send(pno, REQ, res); Rec(ch); Texts.WriteInt(W, ORD(ch), 4);
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END TestReq;
PROCEDURE SendInt(x: LONGINT);
VAR i: INTEGER;
BEGIN i := 4;
WHILE i > 0 DO
DEC(i); V24.Send(portno, CHR(x), res); x := x DIV 100H
END
END SendInt;
PROCEDURE Load*; (*linked boot file F.bin*)
VAR i, m, n, w: LONGINT;
F: Files.File; R: Files.Rider;
S: Texts.Scanner;
BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
IF S.class = Texts.Name THEN (*input file name*)
Texts.WriteString(W, S.s); F := Files.Old(S.s);
IF F # NIL THEN
Files.Set(R, F, 0); Files.ReadLInt(R, n); Files.ReadLInt(R, m); n := n DIV 4;
Texts.WriteInt(W, n, 6); Texts.WriteString(W, " loading "); Texts.Append(Oberon.Log, W.buf);
i := 0; SendInt(n*4); SendInt(m);
WHILE i < n DO
IF i + 1024 < n THEN m := i + 1024 ELSE m := n END ;
WHILE i < m DO Files.ReadLInt(R, w); SendInt(w); INC(i) END ;
Texts.Write(W, "."); Texts.Append(Oberon.Log, W.buf)
END ;
SendInt(0); Texts.WriteString(W, "done")
ELSE Texts.WriteString(W, " not found")
END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END
END Load;
(* ------------ send and receive files ------------ *)
PROCEDURE Rec(VAR ch: CHAR); (*receive with timeout*)
VAR time: LONGINT;
BEGIN time := Oberon.Time() + 3000;
LOOP
IF V24.Available(pno) > 0 THEN V24.Receive(pno, ch, res); EXIT END ;
IF Oberon.Time() >= time THEN ch := 0X; EXIT END
END
END Rec;
PROCEDURE SendName(VAR s: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0; ch := s[0];
WHILE ch > 0X DO V24.Send(pno, ch, res); INC(i); ch := s[i] END ;
V24.Send(pno, 0X, res)
END SendName;
PROCEDURE Send*;
VAR ch, code: CHAR;
n, n0, L: LONGINT;
F: Files.File; R: Files.Rider;
S: Texts.Scanner;
BEGIN V24.Send(pno, REQ, res); Rec(code);
IF code = ACK THEN
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
WHILE S.class = Texts.Name DO
Texts.WriteString(W, S.s); F := Files.Old(S.s);
IF F # NIL THEN
V24.Send(pno, REC, res); SendName(S.s); Rec(code);
IF code = ACK THEN
Texts.WriteString(W, " sending ");
L := Files.Length(F); Files.Set(R, F, 0);
REPEAT (*send paket*)
IF L > BlkLen THEN n := BlkLen ELSE n := L END ;
n0 := n; V24.Send(pno, CHR(n), res); DEC(L, n);
WHILE n > 0 DO Files.Read(R, ch); V24.Send(pno, ch, res); DEC(n) END ;
Rec(code);
IF code = ACK THEN Texts.Write(W, ".") ELSE Texts.Write(W, "*"); n := 0 END ;
Texts.Append(Oberon.Log, W.buf)
UNTIL n0 < BlkLen;
Rec(code)
ELSE Texts.WriteString(W, " no response"); Texts.WriteInt(W, ORD(code), 4)
END
ELSE Texts.WriteString(W, " not found")
END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); Texts.Scan(S)
END
ELSE Texts.WriteString(W, " connection not open");
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END
END Send;
PROCEDURE Receive*;
VAR ch, code: CHAR;
n, L, LL: LONGINT;
F: Files.File; R: Files.Rider;
orgname: ARRAY 32 OF CHAR;
S: Texts.Scanner;
BEGIN V24.Send(pno, REQ, res); Rec(code);
IF code = ACK THEN
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
WHILE S.class = Texts.Name DO
Texts.WriteString(W, S.s); COPY(S.s, orgname);
F := Files.New(S.s); Files.Set(R, F, 0); LL := 0;
V24.Send(pno, SND, res); SendName(S.s); Rec(code);
IF code = ACK THEN
Texts.WriteString(W, " receiving ");
REPEAT Rec(ch); L := ORD(ch); n := L;
WHILE n > 0 DO V24.Receive(pno, ch, res); Files.Write(R, ch); DEC(n) END ;
V24.Send(pno, ACK, res); LL := LL + L; Texts.Write(W, "."); Texts.Append(Oberon.Log, W.buf)
UNTIL L < BlkLen;
Files.Register(F); Texts.WriteInt(W, LL, 6)
ELSE Texts.WriteString(W, " no response"); Texts.WriteInt(W, ORD(code), 4)
END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); Texts.Scan(S)
END
ELSE Texts.WriteString(W, " connection not open");
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END
END Receive;
PROCEDURE Close*;
BEGIN V24.Send(pno, CLS, res);
Texts.WriteString(W, "Server closed"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END Close;
(* ------------ Oberon-0 commands ------------ *)
PROCEDURE RecByte(VAR ch: CHAR);
VAR T: LONGINT; ch0: CHAR;
BEGIN T := Oberon.Time() + Tout;
REPEAT UNTIL (V24.Available(portno) > 0) OR (Oberon.Time() >= T);
IF V24.Available(portno) > 0 THEN V24.Receive(portno, ch, res) ELSE ch := 0X END ;
END RecByte;
PROCEDURE RecInt(VAR x: LONGINT);
VAR i, k, T: LONGINT; ch: CHAR;
BEGIN i := 4; k := 0;
REPEAT
DEC(i); V24.Receive(portno, ch, res);
k := SYSTEM.ROT(ORD(ch)+k, -8)
UNTIL i = 0;
x := k
END RecInt;
PROCEDURE SR*; (*send, then receive sequence of items*)
VAR S: Texts.Scanner; i, k: LONGINT; ch, xch: CHAR;
BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
WHILE (S.class # Texts.Char) & (S.c # "~") DO
IF S.class = Texts.Int THEN Texts.WriteInt(W, S.i, 6); SendInt(S.i)
ELSIF S.class = Texts.Real THEN
Texts.WriteReal(W, S.x, 12); SendInt(SYSTEM.VAL(LONGINT, S.x))
ELSIF S.class IN {Texts.Name, Texts.String} THEN
Texts.Write(W, " "); Texts.WriteString(W, S.s); i := 0;
REPEAT ch := S.s[i]; V24.Send(portno, ch, res); INC(i) UNTIL ch = 0X
ELSIF S.class = Texts.Char THEN Texts.Write(W, S.c)
ELSE Texts.WriteString(W, "bad value")
END ;
Texts.Scan(S)
END ;
Texts.Write(W, "|"); (*Texts.Append(Oberon.Log, W.buf);*)
(*receive input*)
REPEAT RecByte(xch);
IF xch = 0X THEN Texts.WriteString(W, " timeout"); Flush
ELSIF xch = 1X THEN RecInt(k); Texts.WriteInt(W, k, 6)
ELSIF xch = 2X THEN RecInt(k); Texts.WriteHex(W, k)
ELSIF xch = 3X THEN RecInt(k); Texts.WriteReal(W, SYSTEM.VAL(REAL, k), 15)
ELSIF xch = 4X THEN Texts.Write(W, " "); V24.Receive(portno, ch, res);
WHILE ch > 0X DO Texts.Write(W, ch); V24.Receive(portno, ch, res) END
ELSIF xch = 5X THEN V24.Receive(portno, ch, res); Texts.Write(W, ch)
ELSIF xch = 6X THEN Texts.WriteLn(W)
ELSIF xch = 7X THEN Texts.Write(W, "~"); xch := 0X
ELSIF xch = 8X THEN RecByte(ch); Texts.WriteInt(W, ORD(ch), 4); Texts.Append(Oberon.Log, W.buf)
ELSE xch := 0X
END
UNTIL xch = 0X;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END SR;
BEGIN Texts.OpenWriter(W);
END ORC.

View file

@ -1,16 +1,20 @@
MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
IMPORT SYSTEM, Files, ORS, ORB;
MODULE ORG; (* NW 24.6.2014 code generator in Oberon-07 for RISC*)
IMPORT SYSTEM, Files := CompatFiles, ORS, ORB;
(*Code generator for Oberon compiler for RISC processor.
Procedural interface to Parser OSAP; result in array "code".
Procedure Close writes code-files*)
(* voc adaptation by noch *)
TYPE INTEGER = LONGINT;
BYTE = CHAR;
CONST WordSize* = 4;
StkOrg0 = -64; VarOrg0 = 0; (*for RISC-0 only*)
MT = 12; SB = 13; SP = 14; LNK = 15; (*dedicated registers*)
maxCode = 8000; maxStrx = 2400; maxTD = 120; C24 = 1000000H;
Reg = 10; RegI = 11; Cond = 12; (*internal item modes*)
(*frequently used opcodes*) U = 2000H;
(*frequently used opcodes*) U = 2000H; V = 1000H;
Mov = 0; Lsl = 1; Asr = 2; Ror= 3; And = 4; Ann = 5; Ior = 6; Xor = 7;
Add = 8; Sub = 9; Cmp = 9; Mul = 10; Div = 11;
Fad = 12; Fsb = 13; Fml = 14; Fdv = 15;
@ -28,7 +32,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
(* Item forms and meaning of fields:
mode r a b
--------------------------------
Const - value (proc adr) (immediate value)
Const - value (proc adr) (immediate value)
Var base off - (direct adr)
Par - off0 off1 (indirect adr)
Reg regno
@ -40,8 +44,9 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
entry: LONGINT; (*main entry point*)
RH: LONGINT; (*available registers R[0] ... R[H-1]*)
curSB: LONGINT; (*current static base in SB*)
frame: LONGINT; (*frame offset changed in SaveRegs and RestoreRegs*)
fixorgP, fixorgD, fixorgT: LONGINT; (*origins of lists of locations to be fixed up by loader*)
check, inhibitCalls: BOOLEAN; (*emit run-time checks*)
check: BOOLEAN; (*emit run-time checks*)
version: INTEGER; (* 0 = RISC-0, 1 = RISC-5 *)
relmap: ARRAY 6 OF INTEGER; (*condition codes for relations*)
@ -49,6 +54,15 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
data: ARRAY maxTD OF LONGINT; (*type descriptors*)
str: ARRAY maxStrx OF CHAR;
(* voc adaptation by noch *)
PROCEDURE LSL (x, n : INTEGER): INTEGER;
BEGIN
RETURN ASH(x, n);
END LSL;
(*instruction assemblers according to formats*)
PROCEDURE Put0(op, a, b, c: LONGINT);
@ -58,7 +72,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE Put1(op, a, b, im: LONGINT);
BEGIN (*emit format-1 instruction, -10000H <= im < 10000H*)
IF im < 0 THEN INC(op, 1000H) END ; (*set v-bit*)
IF im < 0 THEN INC(op, V) END ;
code[pc] := (((a+40H) * 10H + b) * 10H + op) * 10000H + (im MOD 10000H); INC(pc)
END Put1;
@ -83,36 +97,21 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE incR;
BEGIN
IF RH < MT THEN INC(RH) ELSE ORS.Mark("register stack overflow") END
IF RH < MT-1 THEN INC(RH) ELSE ORS.Mark("register stack overflow") END
END incR;
PROCEDURE CheckRegs*;
BEGIN
IF RH # 0 THEN ORS.Mark("Reg Stack"); RH := 0 END ;
IF pc >= maxCode - 40 THEN ORS.Mark("Program too long"); END
IF pc >= maxCode - 40 THEN ORS.Mark("Program too long") END
END CheckRegs;
PROCEDURE SaveRegs(r: LONGINT); (* R[0 .. r-1] to be saved; R[r .. RH-1] to be moved down*)
VAR rs, rd: LONGINT; (*r > 0*)
BEGIN rs := r; rd := 0;
REPEAT DEC(rs); Put1(Sub, SP, SP, 4); Put2(Str, rs, SP, 0) UNTIL rs = 0;
rs := r; rd := 0;
WHILE rs < RH DO Put0(Mov, rd, 0, rs); INC(rs); INC(rd) END ;
RH := rd
END SaveRegs;
PROCEDURE RestoreRegs(r: LONGINT; VAR x: Item); (*R[0 .. r-1] to be restored*)
VAR rd: LONGINT; (*r > 0*)
BEGIN Put0(Mov, r, 0, 0); rd := 0;
REPEAT Put2(Ldr, rd, SP, 0); Put1(Add, SP, SP, 4); INC(rd) UNTIL rd = r
END RestoreRegs;
PROCEDURE SetCC(VAR x: Item; n: LONGINT);
BEGIN x.mode := Cond; x.a := 0; x.b := 0; x.r := n
END SetCC;
PROCEDURE Trap(cond, num: LONGINT);
BEGIN Put3(BLR, cond, ORS.Pos()*100H + num*10H + MT)
BEGIN num := ORS.Pos()*100H + num*10H + MT; Put3(BLR, cond, num)
END Trap;
(*handling of forward reference, fixups of branch addresses and constant tables*)
@ -174,13 +173,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
BEGIN
IF x.type.size = 1 THEN op := Ldr+1 ELSE op := Ldr END ;
IF x.mode # Reg THEN
IF x.mode = ORB.Var THEN
IF x.r > 0 THEN (*local*) Put2(op, RH, SP, x.a)
ELSE GetSB(x.r); Put2(op, RH, SB, x.a)
END ;
x.r := RH; incR
ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a); Put2(op, RH, RH, x.b); x.r := RH; incR
ELSIF x.mode = ORB.Const THEN
IF x.mode = ORB.Const THEN
IF x.type.form = ORB.Proc THEN
IF x.r > 0 THEN ORS.Mark("not allowed")
ELSIF x.r = 0 THEN Put3(BL, 7, 0); Put1a(Sub, RH, LNK, pc*4 - x.a)
@ -191,6 +184,12 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
IF x.a MOD 10000H # 0 THEN Put1(Ior, RH, RH, x.a MOD 10000H) END
END ;
x.r := RH; incR
ELSIF x.mode = ORB.Var THEN
IF x.r > 0 THEN (*local*) Put2(op, RH, SP, x.a + frame)
ELSE GetSB(x.r); Put2(op, RH, SB, x.a)
END ;
x.r := RH; incR
ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a + frame); Put2(op, RH, RH, x.b); x.r := RH; incR
ELSIF x.mode = RegI THEN Put2(op, x.r, x.r, x.a)
ELSIF x.mode = Cond THEN
Put3(BC, negated(x.r), 2);
@ -204,16 +203,16 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE loadAdr(VAR x: Item);
BEGIN
IF x.mode = ORB.Var THEN
IF x.r > 0 THEN (*local*) Put1a(Add, RH, SP, x.a)
IF x.r > 0 THEN (*local*) Put1a(Add, RH, SP, x.a + frame)
ELSE GetSB(x.r); Put1a(Add, RH, SB, x.a)
END ;
x.r := RH; incR
ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a);
ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a + frame);
IF x.b # 0 THEN Put1a(Add, RH, RH, x.b) END ;
x.r := RH; incR
ELSIF x.mode = RegI THEN
IF x.a # 0 THEN Put1a(Add, x.r, x.r, x.a) END
ELSE ORS.Mark("address error")
ELSE ORS.Mark("address error")
END ;
x.mode := Reg
END loadAdr;
@ -295,15 +294,15 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
IF check THEN (*check array bounds*)
IF lim >= 0 THEN Put1a(Cmp, RH, y.r, lim)
ELSE (*open array*)
IF x.mode IN {ORB.Var, ORB.Par} THEN Put2(Ldr, RH, SP, x.a+4); Put0(Cmp, RH, y.r, RH)
IF x.mode IN {ORB.Var, ORB.Par} THEN Put2(Ldr, RH, SP, x.a+4+frame); Put0(Cmp, RH, y.r, RH)
ELSE ORS.Mark("error in Index")
END
END ;
Trap(10, 1)
Trap(10, 1) (*BCC*)
END ;
IF s = 4 THEN Put1(Lsl, y.r, y.r, 2) ELSIF s > 1 THEN Put1(Mul, y.r, y.r, s) END ;
IF s = 4 THEN Put1(Lsl, y.r, y.r, 2) ELSIF s > 1 THEN Put1a(Mul, y.r, y.r, s) END ;
IF x.mode = ORB.Var THEN
IF x.r > 0 THEN Put0(Add, y.r, SP, y.r)
IF x.r > 0 THEN Put0(Add, y.r, SP, y.r); INC(x.a, frame)
ELSE GetSB(x.r);
IF x.r = 0 THEN Put0(Add, y.r, SB, y.r)
ELSE Put1a(Add, RH, SB, x.a); Put0(Add, y.r, RH, y.r); x.a := 0
@ -311,7 +310,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
END ;
x.r := y.r; x.mode := RegI
ELSIF x.mode = ORB.Par THEN
Put2(Ldr, RH, SP, x.a);
Put2(Ldr, RH, SP, x.a + frame);
Put0(Add, y.r, RH, y.r); x.mode := RegI; x.r := y.r; x.a := x.b
ELSIF x.mode = RegI THEN Put0(Add, x.r, x.r, y.r); DEC(RH)
END
@ -321,10 +320,10 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE DeRef*(VAR x: Item);
BEGIN
IF x.mode = ORB.Var THEN
IF x.r > 0 THEN (*local*) Put2(Ldr, RH, SP, x.a) ELSE GetSB(x.r); Put2(Ldr, RH, SB, x.a) END ;
IF x.r > 0 THEN (*local*) Put2(Ldr, RH, SP, x.a + frame) ELSE GetSB(x.r); Put2(Ldr, RH, SB, x.a) END ;
NilCheck; x.r := RH; incR
ELSIF x.mode = ORB.Par THEN
Put2(Ldr, RH, SP, x.a); Put2(Ldr, RH, RH, x.b); NilCheck; x.r := RH; incR
Put2(Ldr, RH, SP, x.a + frame); Put2(Ldr, RH, RH, x.b); NilCheck; x.r := RH; incR
ELSIF x.mode = RegI THEN Put2(Ldr, x.r, x.r, x.a); NilCheck
ELSIF x.mode # Reg THEN ORS.Mark("bad mode in DeRef")
END ;
@ -358,7 +357,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
IF s <= 24 THEN s := 32 ELSIF s <= 56 THEN s := 64 ELSIF s <= 120 THEN s := 128
ELSE s := (s+263) DIV 256 * 256
END ;
data[dcw] := s; INC(dcw);
T.len := dc; data[dcw] := s; INC(dcw);
k := T.nofpar; (*extension level!*)
IF k > 3 THEN ORS.Mark("ext level too large")
ELSE Q(T, dcw);
@ -369,13 +368,17 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
END BuildTD;
PROCEDURE TypeTest*(VAR x: Item; T: ORB.Type; varpar, isguard: BOOLEAN);
VAR pc0: LONGINT;
BEGIN (*fetch tag into RH*)
IF varpar THEN Put2(Ldr, RH, SP, x.a+4)
ELSE load(x); NilCheck; Put2(Ldr, RH, x.r, -8)
IF varpar THEN Put2(Ldr, RH, SP, x.a+4+frame)
ELSE load(x);
pc0 := pc; Put3(BC, EQ, 0); (*NIL belongs to every pointer type*)
Put2(Ldr, RH, x.r, -8)
END ;
Put2(Ldr, RH, RH, T.nofpar*4); incR;
loadTypTagAdr(T); (*tag of T*)
Put0(Cmp, RH, RH-1, RH-2); DEC(RH, 2);
Put0(Cmp, RH-1, RH-1, RH-2); DEC(RH, 2);
IF ~varpar THEN fix(pc0, pc - pc0 - 1) END ;
IF isguard THEN
IF check THEN Trap(NE, 2) END
ELSE SetCC(x, EQ);
@ -514,32 +517,20 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE Singleton*(VAR x: Item); (* x := {x} *)
BEGIN
IF x.mode = ORB.Const THEN
(*x.a := LSL(1, x.a)*) (* o7 -> o2 *)
x.a := ASH(1, x.a)
ELSE
load(x); Put1(Mov, RH, 0, 1); Put0(Lsl, x.r, RH, x.r)
x.a := LSL(1, x.a)
ELSE load(x); Put1(Mov, RH, 0, 1); Put0(Lsl, x.r, RH, x.r)
END
END Singleton;
PROCEDURE Set*(VAR x, y: Item); (* x := {x .. y} *)
BEGIN
IF (x.mode = ORB.Const) & ( y.mode = ORB.Const) THEN
IF x.a <= y.a THEN
(*x.a := LSL(2, y.a) - LSL(1, x.a)*) (* o7 -> o2 *)
x.a := ASH(2, y.a) - ASH(1, x.a)
ELSE
x.a := 0
END
IF x.a <= y.a THEN x.a := LSL(2, y.a) - LSL(1, x.a) ELSE x.a := 0 END
ELSE
IF (x.mode = ORB.Const) & (x.a < 10H) THEN
(*x.a := LSL(-1, x.a)*) (* o7 -> o2 *)
x.a := ASH(-1, x.a)
IF (x.mode = ORB.Const) & (x.a < 16) THEN x.a := LSL(-1, x.a)
ELSE load(x); Put1(Mov, RH, 0, -1); Put0(Lsl, x.r, RH, x.r)
END ;
IF (y.mode = ORB.Const) & (y.a < 10H) THEN
(*Put1(Mov, RH, 0, LSL(-2, y.a)); *) (* o7 -> o2 *)
Put1(Mov, RH, 0, ASH(-2, y.a));
y.mode := Reg; y.r := RH; INC(RH)
IF (y.mode = ORB.Const) & (y.a < 16) THEN Put1(Mov, RH, 0, LSL(-2, y.a)); y.mode := Reg; y.r := RH; incR
ELSE load(y); Put1(Mov, RH, 0, -2); Put0(Lsl, y.r, RH, y.r)
END ;
IF x.mode = ORB.Const THEN
@ -641,36 +632,36 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
BEGIN load(y);
IF x.type.size = 1 THEN op := Str+1 ELSE op := Str END ;
IF x.mode = ORB.Var THEN
IF x.r > 0 THEN (*local*) Put2(op, y.r, SP, x.a)
IF x.r > 0 THEN (*local*) Put2(op, y.r, SP, x.a + frame)
ELSE GetSB(x.r); Put2(op, y.r, SB, x.a)
END
ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a); Put2(op, y.r, RH, x.b);
ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a + frame); Put2(op, y.r, RH, x.b);
ELSIF x.mode = RegI THEN Put2(op, y.r, x.r, x.a); DEC(RH);
ELSE ORS.Mark("bad mode in Store")
END ;
DEC(RH)
END Store;
PROCEDURE StoreStruct*(VAR x, y: Item); (* x := y *)
PROCEDURE StoreStruct*(VAR x, y: Item); (* x := y, frame = 0 *)
VAR s, pc0: LONGINT;
BEGIN loadAdr(x); loadAdr(y);
IF (x.type.form = ORB.Array) & (x.type.len > 0) THEN
IF y.type.len >= 0 THEN
IF x.type.len >= y.type.len THEN Put1(Mov, RH, 0, (y.type.size+3) DIV 4)
IF x.type.len >= y.type.len THEN Put1a(Mov, RH, 0, (y.type.size+3) DIV 4)
ELSE ORS.Mark("source array too long")
END
ELSE (*y is open array*)
Put2(Ldr, RH, SP, y.a+4); s := y.type.base.size; (*element size*)
pc0 := pc; Put3(BC, EQ, 0);
IF s = 1 THEN Put1(Add, RH, RH, 3); Put1(Asr, RH, RH, 2)
ELSIF s # 4 THEN Put1(Mul, RH, RH, s DIV 4)
ELSIF s # 4 THEN Put1a(Mul, RH, RH, s DIV 4)
END ;
IF check THEN
Put1(Mov, RH+1, 0, (x.type.size+3) DIV 4); Put0(Cmp, RH+1, RH, RH+1); Trap(GT, 3)
Put1a(Mov, RH+1, 0, (x.type.size+3) DIV 4); Put0(Cmp, RH+1, RH, RH+1); Trap(GT, 3)
END ;
fix(pc0, pc + 5 - pc0)
END
ELSIF x.type.form = ORB.Record THEN Put1(Mov, RH, 0, x.type.size DIV 4)
ELSIF x.type.form = ORB.Record THEN Put1a(Mov, RH, 0, x.type.size DIV 4)
ELSE ORS.Mark("inadmissible assignment")
END ;
Put2(Ldr, RH+1, y.r, 0); Put1(Add, y.r, y.r, 4);
@ -698,10 +689,10 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
VAR xmd: INTEGER;
BEGIN xmd := x.mode; loadAdr(x);
IF (ftype.form = ORB.Array) & (ftype.len < 0) THEN (*open array*)
IF x.type.len >= 0 THEN Put1(Mov, RH, 0, x.type.len) ELSE Put2(Ldr, RH, SP, x.a+4) END ;
IF x.type.len >= 0 THEN Put1a(Mov, RH, 0, x.type.len) ELSE Put2(Ldr, RH, SP, x.a+4+frame) END ;
incR
ELSIF ftype.form = ORB.Record THEN
IF xmd = ORB.Par THEN Put2(Ldr, RH, SP, x.a+4); incR ELSE loadTypTagAdr(x.type) END
IF xmd = ORB.Par THEN Put2(Ldr, RH, SP, x.a+4+frame); incR ELSE loadTypTagAdr(x.type) END
END
END VarParam;
@ -711,7 +702,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE OpenArrayParam*(VAR x: Item);
BEGIN loadAdr(x);
IF x.type.len >= 0 THEN Put1a(Mov, RH, 0, x.type.len) ELSE Put2(Ldr, RH, SP, x.a+4) END ;
IF x.type.len >= 0 THEN Put1a(Mov, RH, 0, x.type.len) ELSE Put2(Ldr, RH, SP, x.a+4+frame) END ;
incR
END OpenArrayParam;
@ -772,38 +763,47 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
BEGIN FixLink(x.a)
END Fixup;
PROCEDURE SaveRegs(r: LONGINT); (* R[0 .. r-1]*)
VAR r0: LONGINT;
BEGIN (*r > 0*) r0 := 0;
Put1(Sub, SP, SP, r*4); INC(frame, 4*r);
REPEAT Put2(Str, r0, SP, (r-r0-1)*4); INC(r0) UNTIL r0 = r
END SaveRegs;
PROCEDURE RestoreRegs(r: LONGINT); (*R[0 .. r-1]*)
VAR r0: LONGINT;
BEGIN (*r > 0*) r0 := r;
REPEAT DEC(r0); Put2(Ldr, r0, SP, (r-r0-1)*4) UNTIL r0 = 0;
Put1(Add, SP, SP, r*4); DEC(frame, 4*r)
END RestoreRegs;
PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
BEGIN
IF x.type.form = ORB.Proc THEN
IF x.mode # ORB.Const THEN
load(x); code[pc-1] := code[pc-1] + 0B000000H; x.r := 11; DEC(RH); inhibitCalls := TRUE;
IF check THEN Trap(EQ, 5) END
END
ELSE ORS.Mark("not a procedure")
END ;
r := RH
BEGIN (*x.type.form = ORB.Proc*)
IF x.mode > ORB.Par THEN load(x) END ;
r := RH;
IF RH > 0 THEN SaveRegs(RH); RH := 0 END
END PrepCall;
PROCEDURE Call*(VAR x: Item; r: LONGINT);
BEGIN
IF inhibitCalls & (x.r # 11) THEN ORS.Mark("inadmissible call") ELSE inhibitCalls := FALSE END ;
IF r > 0 THEN SaveRegs(r) END ;
IF x.type.form = ORB.Proc THEN
IF x.mode = ORB.Const THEN
IF x.r >= 0 THEN Put3(BL, 7, (x.a DIV 4)-pc-1)
ELSE (*imported*)
IF pc - fixorgP < 1000H THEN
Put3(BL, 7, ((-x.r) * 100H + x.a) * 1000H + pc-fixorgP); fixorgP := pc-1
ELSE ORS.Mark("fixup impossible")
END
BEGIN (*x.type.form = ORB.Proc*)
IF x.mode = ORB.Const THEN
IF x.r >= 0 THEN Put3(BL, 7, (x.a DIV 4)-pc-1)
ELSE (*imported*)
IF pc - fixorgP < 1000H THEN
Put3(BL, 7, ((-x.r) * 100H + x.a) * 1000H + pc-fixorgP); fixorgP := pc-1
ELSE ORS.Mark("fixup impossible")
END
ELSE Put3(BLR, 7, x.r)
END
ELSE ORS.Mark("not a procedure")
END ;
IF x.type.base.form = ORB.NoTyp THEN RH := 0
ELSE
IF r > 0 THEN RestoreRegs(r, x) END ;
IF x.mode <= ORB.Par THEN load(x); DEC(RH)
ELSE Put2(Ldr, RH, SP, 0); Put1(Add, SP, SP, 4); DEC(r); DEC(frame, 4)
END ;
IF check THEN Trap(EQ, 5) END ;
Put3(BLR, 7, RH)
END ;
IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
ELSE (*function*)
IF r > 0 THEN Put0(Mov, r, 0, 0); RestoreRegs(r) END ;
x.mode := Reg; x.r := r; RH := r+1
END ;
invalSB
@ -811,14 +811,14 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE Enter*(parblksize, locblksize: LONGINT; int: BOOLEAN);
VAR a, r: LONGINT;
BEGIN invalSB;
BEGIN invalSB; frame := 0;
IF ~int THEN (*procedure prolog*)
a := 4; r := 0;
Put1(Sub, SP, SP, locblksize); Put2(Str, LNK, SP, 0);
WHILE a < parblksize DO Put2(Str, r, SP, a); INC(r); INC(a, 4) END
ELSE (*interrupt procedure*)
Put1(Sub, SP, SP, 8); Put2(Str, 0, SP, 0); Put2(Str, 1, SP, 4)
(*R0 and R1 saved, but NOT LNK*)
Put1(Sub, SP, SP, 12); Put2(Str, 0, SP, 0); Put2(Str, 1, SP, 4); Put2(Str, SB, SP, 8)
(*R0, R1, SB saved os stack*)
END
END Enter;
@ -827,8 +827,8 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
IF form # ORB.NoTyp THEN load(x) END ;
IF ~int THEN (*procedure epilog*)
Put2(Ldr, LNK, SP, 0); Put1(Add, SP, SP, size); Put3(BR, 7, LNK)
ELSE (*interrupt*)
Put2(Ldr, 1, SP, 4); Put2(Ldr, 0, SP, 0); Put1(Add, SP, SP, 8); Put3(BR, 7, 10H)
ELSE (*interrupt return, restore SB, R1, R0*)
Put2(Ldr, SB, SP, 8); Put2(Ldr, 1, SP, 4); Put2(Ldr, 0, SP, 0); Put1(Add, SP, SP, 12); Put3(BR, 7, 10H)
END ;
RH := 0
END Return;
@ -837,35 +837,26 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE Increment*(upordown: LONGINT; VAR x, y: Item);
VAR op, zr, v: LONGINT;
BEGIN
BEGIN (*frame = 0*)
IF upordown = 0 THEN op := Add ELSE op := Sub END ;
IF x.type = ORB.byteType THEN v := 1 ELSE v := 0 END ;
IF y.type.form = ORB.NoTyp THEN y.mode := ORB.Const; y.a := 1 END ;
IF (x.mode = ORB.Var) & (x.r > 0) THEN
zr := RH; Put2(Ldr+v, zr, SP, x.a); incR;
IF y.mode = ORB.Const THEN Put1(op, zr, zr, y.a) ELSE load(y); Put0(op, zr, zr, y.r); DEC(RH) END ;
IF y.mode = ORB.Const THEN Put1a(op, zr, zr, y.a) ELSE load(y); Put0(op, zr, zr, y.r); DEC(RH) END ;
Put2(Str+v, zr, SP, x.a); DEC(RH)
ELSE loadAdr(x); zr := RH; Put2(Ldr+v, RH, x.r, 0); incR;
IF y.mode = ORB.Const THEN Put1(op, zr, zr, y.a) ELSE load(y); Put0(op, zr, zr, y.r); DEC(RH) END ;
IF y.mode = ORB.Const THEN Put1a(op, zr, zr, y.a) ELSE load(y); Put0(op, zr, zr, y.r); DEC(RH) END ;
Put2(Str+v, zr, x.r, 0); DEC(RH, 2)
END
END Increment;
PROCEDURE Include*(inorex: LONGINT; VAR x, y: Item);
VAR zr: LONGINT;
VAR op, zr: LONGINT;
BEGIN loadAdr(x); zr := RH; Put2(Ldr, RH, x.r, 0); incR;
IF inorex = 0 THEN (*include*)
IF y.mode = ORB.Const THEN
(*Put1(Ior, zr, zr, LSL(1, y.a))*) (* o7 -> o2 *)
Put1(Ior, zr, zr, ASH(1, y.a))
ELSE load(y); Put1(Mov, RH, 0, 1); Put0(Lsl, y.r, RH, y.r); Put0(Ior, zr, zr, y.r); DEC(RH)
END
ELSE (*exclude*)
IF y.mode = ORB.Const THEN
(*Put1(And, zr, zr, -LSL(1, y.a)-1)*) (* o7 -> o2 *)
Put1(And, zr, zr, - ASH(1, y.a)-1)
ELSE load(y); Put1(Mov, RH, 0, 1); Put0(Lsl, y.r, RH, y.r); Put1(Xor, y.r, y.r, -1); Put0(And, zr, zr, y.r); DEC(RH)
END
IF inorex = 0 THEN op := Ior ELSE op := Ann END ;
IF y.mode = ORB.Const THEN Put1a(op, zr, zr, LSL(1, y.a))
ELSE load(y); Put1(Mov, RH, 0, 1); Put0(Lsl, y.r, RH, y.r); Put0(op, zr, zr, y.r); DEC(RH)
END ;
Put2(Str, zr, x.r, 0); DEC(RH, 2)
END Include;
@ -950,7 +941,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
END Odd;
PROCEDURE Floor*(VAR x: Item);
BEGIN load(x); Put1(Mov+U, RH, 0, 4B00H); Put0(Fad+1000H, x.r, x.r, RH)
BEGIN load(x); Put1(Mov+U, RH, 0, 4B00H); Put0(Fad+V, x.r, x.r, RH)
END Floor;
PROCEDURE Float*(VAR x: Item);
@ -965,7 +956,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE Len*(VAR x: Item);
BEGIN
IF x.type.len >= 0 THEN x.mode := ORB.Const; x.a := x.type.len
ELSE (*open array*) Put2(Ldr, RH, SP, x.a + 4); x.mode := Reg; x.r := RH; incR
ELSE (*open array*) Put2(Ldr, RH, SP, x.a + 4 + frame); x.mode := Reg; x.r := RH; incR
END
END Len;
@ -1005,7 +996,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE H*(VAR x: Item);
BEGIN (*x.mode = Const*)
Put0(Mov + U + (x.a MOD 2 * 1000H), RH, 0, 0); x.mode := Reg; x.r := RH; incR
Put0(Mov + U + x.a MOD 2 * V, RH, 0, 0); x.mode := Reg; x.r := RH; incR
END H;
PROCEDURE Adr*(VAR x: Item);
@ -1022,8 +1013,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
END Condition;
PROCEDURE Open*(v: INTEGER);
BEGIN pc := 0; tdx := 0; strx := 0; RH := 0; fixorgP := 0; fixorgD := 0; fixorgT := 0;
check := v # 0; version := v; inhibitCalls := FALSE;
BEGIN pc := 0; tdx := 0; strx := 0; RH := 0; fixorgP := 0; fixorgD := 0; fixorgT := 0; check := v # 0; version := v;
IF v = 0 THEN pc := 8 END
END Open;
@ -1033,7 +1023,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE Header*;
BEGIN entry := pc*4;
IF version = 0 THEN code[0] := 0E7000000H-1 + pc; Put1(Mov, SB, 0, 16); Put1(Mov, SP, 0, StkOrg0) (*RISC-0*)
IF version = 0 THEN code[0] := 0E7000000H-1 + pc; Put1a(Mov, SB, 0, VarOrg0); Put1a(Mov, SP, 0, StkOrg0) (*RISC-0*)
ELSE Put1(Sub, SP, SP, 4); Put2(Str, LNK, SP, 0); invalSB
END
END Header;
@ -1054,9 +1044,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
PROCEDURE FindPtrs(VAR R: Files.Rider; typ: ORB.Type; adr: LONGINT);
VAR fld: ORB.Object; i, s: LONGINT;
BEGIN
IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN
(*Files.WriteInt(R, adr)*) (* o7 -> o2 *)
Files.WriteNum(R, adr)
IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN Files.WriteInt(R, adr)
ELSIF typ.form = ORB.Record THEN
fld := typ.dsc;
WHILE fld # NIL DO FindPtrs(R, fld.type, fld.val + adr); fld := fld.next END
@ -1089,70 +1077,43 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
size := varsize + strx + comsize + (pc + nofimps + nofent + nofptrs + 1)*4; (*varsize includes type descriptors*)
ORB.MakeFileName(name, modid, ".rsc"); (*write code file*)
F := Files.New(name); Files.Set(R, F, 0); Files.WriteString(R, modid);
(*Files.WriteInt(R, key); *) (* o7 -> o2 *)
Files.WriteNum(R, key);
(*Files.WriteByte(R, version);*)
Files.WriteByte(R, SHORT(version));
(*Files.WriteInt(R, size);*)
Files.WriteNum(R, size);
F := Files.New(name); Files.Set(R, F, 0); Files.WriteString(R, modid); Files.WriteInt(R, key);
(*Files.WriteByte(R, version);*) (* who writes like that? -- noch *)
Files.WriteByte(R, SHORT(SHORT(version))); (* voc adaptation by noch *)
Files.WriteInt(R, size);
obj := ORB.topScope.next;
WHILE (obj # NIL) & (obj.class = ORB.Mod) DO (*imports*)
IF obj.dsc # ORB.system THEN
Files.WriteString(R, obj(ORB.Module).orgname);
(*Files.WriteInt(R, obj.val) *)
Files.WriteNum(R, obj.val)
END ;
IF obj.dsc # ORB.system THEN Files.WriteString(R, obj(ORB.Module).orgname); Files.WriteInt(R, obj.val) END ;
obj := obj.next
END ;
Files.Write(R, 0X);
(*Files.WriteInt(R, tdx*4);*)
Files.WriteNum(R, tdx*4);
Files.WriteInt(R, tdx*4);
i := 0;
WHILE i < tdx DO
(*Files.WriteInt(R, data[i]); *)
Files.WriteNum(R, data[i]);
INC(i)
END ; (*type descriptors*)
(*Files.WriteInt(R, varsize - tdx*4);*) (*data*)
Files.WriteNum(R, varsize - tdx*4); (*data*)
(*Files.WriteInt(R, strx);*)
Files.WriteNum(R, strx);
WHILE i < tdx DO Files.WriteInt(R, data[i]); INC(i) END ; (*type descriptors*)
Files.WriteInt(R, varsize - tdx*4); (*data*)
Files.WriteInt(R, strx);
FOR i := 0 TO strx-1 DO Files.Write(R, str[i]) END ; (*strings*)
(*Files.WriteInt(R, pc);*) (*code len*)
Files.WriteNum(R, pc); (*code len*)
FOR i := 0 TO pc-1 DO
(*Files.WriteInt(R, code[i]) *)
Files.WriteNum(R, code[i])
END ; (*program*)
Files.WriteInt(R, pc); (*code len*)
FOR i := 0 TO pc-1 DO Files.WriteInt(R, code[i]) END ; (*program*)
obj := ORB.topScope.next;
WHILE obj # NIL DO (*commands*)
IF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) &
(obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN
Files.WriteString(R, obj.name);
(*Files.WriteInt(R, obj.val)*)
Files.WriteNum(R, obj.val)
Files.WriteString(R, obj.name); Files.WriteInt(R, obj.val)
END ;
obj := obj.next
END ;
Files.Write(R, 0X);
(*Files.WriteInt(R, nofent);*)
Files.WriteNum(R, nofent);
(*Files.WriteInt(R, entry);*)
Files.WriteNum(R, entry);
Files.WriteInt(R, nofent); Files.WriteInt(R, entry);
obj := ORB.topScope.next;
WHILE obj # NIL DO (*entries*)
IF obj.exno # 0 THEN
IF (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) OR (obj.class = ORB.Var) THEN
(*Files.WriteInt(R, obj.val)*)
Files.WriteNum(R, obj.val)
Files.WriteInt(R, obj.val)
ELSIF obj.class = ORB.Typ THEN
IF obj.type.form = ORB.Record THEN
(*Files.WriteInt(R, obj.type.len MOD 10000H)*)
Files.WriteNum(R, obj.type.len MOD 10000H)
IF obj.type.form = ORB.Record THEN Files.WriteInt(R, obj.type.len MOD 10000H)
ELSIF (obj.type.form = ORB.Pointer) & ((obj.type.base.typobj = NIL) OR (obj.type.base.typobj.exno = 0)) THEN
(*Files.WriteInt(R, obj.type.base.len MOD 10000H)*)
Files.WriteNum(R, obj.type.base.len MOD 10000H)
Files.WriteInt(R, obj.type.base.len MOD 10000H)
END
END
END ;
@ -1164,14 +1125,7 @@ MODULE ORG; (* NW 10.10.2013 code generator in Oberon-07 for RISC*)
obj := obj.next
END ;
Files.WriteInt(R, -1);
(*Files.WriteInt(R, fixorgP);*)
Files.WriteNum(R, fixorgP);
(*Files.WriteInt(R, fixorgD);*)
Files.WriteNum(R, fixorgD);
(*Files.WriteInt(R, fixorgT);*)
Files.WriteNum(R, fixorgT);
(*Files.WriteInt(R, entry);*)
Files.WriteNum(R, entry);
Files.WriteInt(R, fixorgP); Files.WriteInt(R, fixorgD); Files.WriteInt(R, fixorgT); Files.WriteInt(R, entry);
Files.Write(R, "O"); Files.Register(F)
END Close;

View file

@ -1,11 +1,13 @@
MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07*)
IMPORT Args, Out := Console, Texts, (*Oberon,*) ORS, ORB, ORG;
(*Author: Niklaus Wirth, 2011.
MODULE ORP; (*N. Wirth 1.7.97 / 7.6.2014 Oberon compiler for RISC in Oberon-07*)
IMPORT Texts := CompatTexts, Oberon, ORS, ORB, ORG;
(*Author: Niklaus Wirth, 2014.
Parser of Oberon-RISC compiler. Uses Scanner ORS to obtain symbols (tokens),
ORB for definition of data structures and for handling import and export, and
ORG to produce binary code. ORP performs type checking and data allocation.
Parser is target-independent, except for part of the handling of allocations.*)
TYPE INTEGER = LONGINT; (* voc adaptation by noch *)
TYPE PtrBase = POINTER TO PtrBaseDesc;
PtrBaseDesc = RECORD (*list of names of pointer base types*)
name: ORS.Ident; type: ORB.Type; next: PtrBase
@ -21,7 +23,7 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
modid: ORS.Ident;
pbsList: PtrBase; (*list of names of pointer base types*)
dummy: ORB.Object;
(*W: Texts.Writer;*)
W: Texts.Writer;
PROCEDURE Check(s: INTEGER; msg: ARRAY OF CHAR);
BEGIN
@ -166,8 +168,10 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
IF (t0.base = t1.base) & (t0.nofpar = t1.nofpar) THEN
p0 := t0.dsc; p1 := t1.dsc;
WHILE p0 # NIL DO
(*IF (p0.class = p1.class) & CompTypes(p0.type, p1.type, TRUE) & (ORD(p0.rdo) = ORD(p1.rdo)) THEN*)
IF (p0.class = p1.class) & CompTypes(p0.type, p1.type, TRUE) & (p0.rdo = p1.rdo) THEN
IF (p0.class = p1.class) & CompTypes(p0.type, p1.type, TRUE) &
(*(ORD(p0.rdo) = ORD(p1.rdo))*)
(p0.rdo = p1.rdo) (* voc adaptation by noch *)
THEN
IF p0.type.form >= ORB.Array THEN com := CompTypes(p0.type, p1.type, (p0.class = ORB.Par)) END ;
p0 := p0.next; p1 := p1.next
ELSE p0 := NIL; com := FALSE
@ -207,7 +211,7 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
ELSIF (x.type.form = ORB.Array) & (par.type.form = ORB.Array) &
(x.type.base.form = par.type.base.form) & (par.type.len < 0) THEN
ORG.OpenArrayParam(x);
ELSIF (x.type.form = ORB.String) & (par.class = ORB.Par) & (par.type.form = ORB.Array) &
ELSIF (x.type.form = ORB.String) & varpar & par.rdo & (par.type.form = ORB.Array) &
(par.type.base.form = ORB.Char) & (par.type.len < 0) THEN ORG.StringParam(x)
ELSIF (par.type.form = ORB.Array) & (par.type.base.form = ORB.Int) & (par.type.size = x.type.size) THEN
ORG.VarParam(x, par.type)
@ -314,11 +318,11 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
IF obj.class = ORB.SFunc THEN StandFunc(x, obj.val, obj.type)
ELSE ORG.MakeItem(x, obj, level); selector(x);
IF sym = ORS.lparen THEN
ORS.Get(sym); ORG.PrepCall(x, rx); ParamList(x);
ORS.Get(sym);
IF (x.type.form = ORB.Proc) & (x.type.base.form # ORB.NoTyp) THEN
ORG.Call(x, rx); x.type := x.type.base
ELSE ORS.Mark("not a function")
END ;
ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx); x.type := x.type.base
ELSE ORS.Mark("not a function"); ParamList(x)
END
END
END
ELSIF sym = ORS.int THEN ORG.MakeConstItem(x, ORB.intType, ORS.ival); ORS.Get(sym)
@ -472,6 +476,12 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
END
END TypeCase;
PROCEDURE SkipCase;
BEGIN
WHILE sym # ORS.colon DO ORS.Get(sym) END ;
ORS.Get(sym); StatSequence
END SkipCase;
BEGIN (* StatSequence *)
REPEAT (*sync*) obj := NIL;
IF ~((sym = ORS.ident) OR (sym >= ORS.if) & (sym <= ORS.for) OR (sym >= ORS.semicolon)) THEN
@ -496,9 +506,10 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
END
ELSIF sym = ORS.eql THEN ORS.Mark("should be :="); ORS.Get(sym); expression(y)
ELSIF sym = ORS.lparen THEN (*procedure call*)
ORS.Get(sym); ORG.PrepCall(x, rx); ParamList(x);
IF (x.type.form = ORB.Proc) & (x.type.base.form = ORB.NoTyp) THEN ORG.Call(x, rx)
ELSE ORS.Mark("not a procedure")
ORS.Get(sym);
IF (x.type.form = ORB.Proc) & (x.type.base.form = ORB.NoTyp) THEN
ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx)
ELSE ORS.Mark("not a procedure"); ParamList(x)
END
ELSIF x.type.form = ORB.Proc THEN (*procedure call without parameters*)
IF x.type.nofpar > 0 THEN ORS.Mark("missing parameters") END ;
@ -554,14 +565,16 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
ORS.Get(sym);
IF sym = ORS.ident THEN
qualident(obj); orgtype := obj.type;
IF ~((orgtype.form = ORB.Pointer) OR (orgtype.form = ORB.Record) & (obj.class = ORB.Par)) THEN
ORS.Mark("bad case var")
END ;
Check(ORS.of, "OF expected"); TypeCase(obj, x); L0 := 0;
WHILE sym = ORS.bar DO
ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); obj.type := orgtype; TypeCase(obj, x)
END ;
ORG.Fixup(x); ORG.FixLink(L0); obj.type := orgtype
IF (orgtype.form = ORB.Pointer) OR (orgtype.form = ORB.Record) & (obj.class = ORB.Par) THEN
Check(ORS.of, "OF expected"); TypeCase(obj, x); L0 := 0;
WHILE sym = ORS.bar DO
ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); obj.type := orgtype; TypeCase(obj, x)
END ;
ORG.Fixup(x); ORG.FixLink(L0); obj.type := orgtype
ELSE ORS.Mark("numeric case not implemented");
Check(ORS.of, "OF expected"); SkipCase;
WHILE sym = ORS.bar DO SkipCase END
END
ELSE ORS.Mark("ident expected")
END ;
Check(ORS.end, "no END")
@ -605,7 +618,7 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
ELSIF sym = ORS.comma THEN ORS.Get(sym); ArrayType(typ.base)
ELSE ORS.Mark("missing OF"); typ.base := ORB.intType
END ;
IF len >= 0 THEN typ.size := len * typ.base.size ELSE typ.size := 2*ORG.WordSize (*array desc*) END ;
IF len >= 0 THEN typ.size := (len * typ.base.size + 3) DIV 4 * 4 ELSE typ.size := 2*ORG.WordSize (*array desc*) END ;
typ.form := ORB.Array; typ.len := len; type := typ
END ArrayType;
@ -613,10 +626,10 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
VAR obj, obj0, new, bot, base: ORB.Object;
typ, tp: ORB.Type;
offset, off, n: LONGINT;
BEGIN NEW(typ); typ.form := ORB.NoTyp; typ.base := NIL; typ.mno := level; typ.nofpar := 0;
offset := 0; bot := NIL;
BEGIN NEW(typ); typ.form := ORB.NoTyp; typ.base := NIL; typ.mno := -level; typ.nofpar := 0; offset := 0; bot := NIL;
IF sym = ORS.lparen THEN
ORS.Get(sym); (*record extension*)
IF level # 0 THEN ORS.Mark("extension of local types not implemented") END ;
IF sym = ORS.ident THEN
qualident(base);
IF base.class = ORB.Typ THEN
@ -651,7 +664,7 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
bot := obj;
IF sym = ORS.semicolon THEN ORS.Get(sym) ELSIF sym # ORS.end THEN ORS.Mark(" ; or END") END
END ;
typ.form := ORB.Record; typ.dsc := bot; typ.size := offset; type := typ
typ.form := ORB.Record; typ.dsc := bot; typ.size := (offset + 3) DIV 4 * 4; type := typ
END RecordType;
PROCEDURE FPSection(VAR adr: LONGINT; VAR nofpar: INTEGER);
@ -715,6 +728,11 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
END
END FormalType0;
PROCEDURE CheckRecLevel(lev: INTEGER);
BEGIN
IF lev # 0 THEN ORS.Mark("ptr base must be global") END
END CheckRecLevel;
PROCEDURE Type0(VAR type: ORB.Type);
VAR dmy: LONGINT; obj: ORB.Object; ptbase: PtrBase;
BEGIN type := ORB.intType; (*sync*)
@ -736,13 +754,16 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
IF sym = ORS.ident THEN
obj := ORB.thisObj(); ORS.Get(sym);
IF obj # NIL THEN
IF (obj.class = ORB.Typ) & (obj.type.form IN {ORB.Record, ORB.NoTyp}) THEN type.base := obj.type
IF (obj.class = ORB.Typ) & (obj.type.form IN {ORB.Record, ORB.NoTyp}) THEN
CheckRecLevel(obj.lev); type.base := obj.type
ELSE ORS.Mark("no valid base type")
END
END ;
NEW(ptbase); ORS.CopyId(ptbase.name); ptbase.type := type; ptbase.next := pbsList; pbsList := ptbase
ELSE CheckRecLevel(level); (*enter into list of forward references to be fixed in Declarations*)
NEW(ptbase); ORS.CopyId(ptbase.name); ptbase.type := type; ptbase.next := pbsList; pbsList := ptbase
END
ELSE Type(type.base);
IF type.base.form # ORB.Record THEN ORS.Mark("must point to record") END
IF type.base.form # ORB.Record THEN ORS.Mark("must point to record") END ;
CheckRecLevel(level)
END
ELSIF sym = ORS.procedure THEN
ORS.Get(sym); ORB.OpenScope;
@ -768,11 +789,7 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
expression(x);
IF (x.type.form = ORB.String) & (x.b = 2) THEN ORG.StrToChar(x) END ;
ORB.NewObj(obj, id, ORB.Const); obj.expo := expo;
IF x.mode = ORB.Const THEN
obj.val := x.a;
(*obj.lev := x.b;*)
obj.lev := SHORT(x.b);
obj.type := x.type
IF x.mode = ORB.Const THEN obj.val := x.a; obj.lev := x.b; obj.type := x.type
ELSE ORS.Mark("expression not constant"); obj.type := ORB.intType
END;
Check(ORS.semicolon, "; missing")
@ -789,12 +806,9 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
IF tp.form = ORB.Record THEN
ptbase := pbsList; (*check whether this is base of a pointer type; search and fixup*)
WHILE ptbase # NIL DO
IF obj.name = ptbase.name THEN
IF ptbase.type.base = ORB.intType THEN ptbase.type.base := obj.type ELSE ORS.Mark("recursive record?") END
END ;
IF obj.name = ptbase.name THEN ptbase.type.base := obj.type END ;
ptbase := ptbase.next
END ;
tp.len := dc;
IF level = 0 THEN ORG.BuildTD(tp, dc) END (*type descriptor; len used as its address*)
END ;
Check(ORS.semicolon, "; missing")
@ -835,7 +849,6 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
IF sym = ORS.times THEN ORS.Get(sym); int := TRUE END ;
IF sym = ORS.ident THEN
ORS.CopyId(procid); ORS.Get(sym);
(*Texts.WriteLn(W); Texts.WriteString(W, procid); Texts.WriteInt(W, ORG.Here(), 7);*)
ORB.NewObj(proc, ORS.id, ORB.Const); parblksize := 4;
NEW(type); type.form := ORB.Proc; type.size := ORG.WordSize; proc.type := type;
CheckExport(proc.expo);
@ -875,25 +888,15 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
VAR key: LONGINT;
obj: ORB.Object;
impid, impid1: ORS.Ident;
BEGIN
(*Texts.WriteString(W, " compiling "); *)
Out.String(" compiling ");
ORS.Get(sym);
BEGIN Texts.WriteString(W, " compiling "); ORS.Get(sym);
IF sym = ORS.module THEN
ORS.Get(sym);
IF sym = ORS.times THEN
version := 0;
(*Texts.Write(W, "*"); *)
Out.Char("*");
ORS.Get(sym)
ELSE
version := 1
END ;
IF sym = ORS.times THEN version := 0; Texts.Write(W, "*"); ORS.Get(sym) ELSE version := 1 END ;
ORB.Init; ORB.OpenScope;
IF sym = ORS.ident THEN
ORS.CopyId(modid); ORS.Get(sym);
(*Texts.WriteString(W, modid); Texts.Append(Oberon.Log, W.buf)*)
Out.String(modid); Out.Ln
Texts.WriteString(W, modid); Texts.Append(Oberon.Log, W.buf);
Oberon.DumpLog; (* voc adaptation; -- noch *)
ELSE ORS.Mark("identifier expected")
END ;
Check(ORS.semicolon, "no ;"); level := 0; dc := 0; exno := 1; key := 0;
@ -927,30 +930,22 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
ELSE ORS.Mark("identifier missing")
END ;
IF sym # ORS.period THEN ORS.Mark("period missing") END ;
IF ORS.errcnt = 0 THEN
IF (ORS.errcnt = 0) & (version # 0) THEN
ORB.Export(modid, newSF, key);
IF newSF THEN
(*Texts.WriteLn(W); Texts.WriteString(W, "new symbol file ") *)
Out.Ln; Out.String("new symbol file ")
END
IF newSF THEN Texts.WriteString(W, " new symbol file") END
END ;
IF ORS.errcnt = 0 THEN
ORG.Close(modid, key, exno);
(*Texts.WriteLn(W); Texts.WriteString(W, "compilation done ");*)
Out.Ln; Out.String("compilation done ");
(*Texts.WriteInt(W, ORG.pc, 6); Texts.WriteInt(W, dc, 6)*)
Out.Int(ORG.pc, 6); Out.Int(dc, 6)
ELSE
(*Texts.WriteLn(W); Texts.WriteString(W, "compilation FAILED")*)
Out.Ln; Out.String("compilation FAILED")
ORG.Close(modid, key, exno);
Texts.WriteInt(W, ORG.pc, 6); Texts.WriteInt(W, dc, 6); Texts.WriteHex(W, key)
ELSE Texts.WriteLn(W); Texts.WriteString(W, "compilation FAILED")
END ;
(*Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);*)
Out.Ln;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
Oberon.DumpLog; (* voc adaptation; -- noch *)
ORB.CloseScope; pbsList := NIL
ELSE ORS.Mark("must start with MODULE")
END
END Module;
(*
PROCEDURE Option(VAR S: Texts.Scanner);
BEGIN newSF := FALSE;
IF S.nextCh = "/" THEN
@ -958,24 +953,12 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
IF (S.class = Texts.Name) & (S.s[0] = "s") THEN newSF := TRUE END
END
END Option;
*)
PROCEDURE Option(VAR s: ARRAY OF CHAR);
BEGIN
newSF := FALSE;
IF s[0] = "-" THEN
IF s[1] = "s" THEN newSF := TRUE END
END
END Option;
PROCEDURE Compile*;
VAR beg, end, time: LONGINT;
(*T: Texts.Text;
S: Texts.Scanner;*)
s, name : ARRAY 32 OF CHAR;
T : Texts.Text;
BEGIN
(*Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S);
T: Texts.Text;
S: Texts.Scanner;
BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
IF S.class = Texts.Char THEN
IF S.c = "@" THEN
Option(S); Oberon.GetSelection(T, beg, end, time);
@ -995,35 +978,20 @@ MODULE ORP; (*N. Wirth 1.7.97 / 5.11.2013 Oberon compiler for RISC in Oberon-07
NEW(T); Texts.Open(T, S.s);
IF T.len > 0 THEN Option(S); ORS.Init(T, 0); Module
ELSE Texts.WriteString(W, S.s); Texts.WriteString(W, " not found");
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
Oberon.DumpLog; (* voc adaptation; -- noch *)
END ;
IF (T.len # 0) & (ORS.errcnt = 0) THEN Texts.Scan(S) ELSE S.class := 0 END
END
END ;
Oberon.Collect(0)
*)
IF Args.argc <= 1 THEN HALT(1) END;
Args.Get (1, s);
Option(s);
IF s[0] = "-" THEN
IF Args.argc < 3 THEN Out.String ("module name expected"); Out.Ln; HALT(1) END;
Args.Get(2, name);
ELSE
COPY(s, name);
END;
NEW(T);
Texts.Open(T, name);
IF T.len > 0 THEN
ORS.Init(T, 0); Module
ELSE
Out.String ("module not found"); Out.Ln
END;
END Compile;
BEGIN (*Texts.OpenWriter(W); Texts.WriteString(W, "OR Compiler 5.11.2013");*)
Out.String("OR Compiler 5.11.2013"); Out.Ln;
(*Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);*)
BEGIN Texts.OpenWriter(W); Texts.WriteString(W, "OR Compiler 7.6.2014");
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
Oberon.DumpLog; (* voc adaptation; -- noch *)
NEW(dummy); dummy.class := ORB.Var; dummy.type := ORB.intType;
expression := expression0; Type := Type0; FormalType := FormalType0;
Compile;
Compile (* voc adaptation; -- noch *)
END ORP.

View file

@ -1,5 +1,7 @@
MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
IMPORT SYSTEM, Texts, Console, S := SYSTEM;
MODULE ORS; (* NW 19.9.93 / 1.4.2014 Scanner in Oberon-07*)
IMPORT SYSTEM, Texts := CompatTexts, Oberon;
TYPE INTEGER = LONGINT; (* voc adaptation by noch *)
(* Oberon Scanner does lexical analysis. Input is Oberon-Text, output is
sequence of symbols, i.e identifiers, numbers, strings, and special symbols.
@ -10,7 +12,7 @@ MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
If Get delivers ident, then the identifier (a string) is in variable id, if int or char
in ival, if real in rval, and if string in str (and slen) *)
CONST IdLen* = 32; WS = 4; (*Word size*)
CONST IdLen* = 32;
NKW = 34; (*nof keywords*)
maxExp = 38; stringBufSize = 256;
@ -29,7 +31,6 @@ MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
else* = 55; elsif* = 56; until* = 57; return* = 58;
array* = 60; record* = 61; pointer* = 62; const* = 63; type* = 64;
var* = 65; procedure* = 66; begin* = 67; import* = 68; module* = 69;
eof = 70;
TYPE Ident* = ARRAY IdLen OF CHAR;
@ -60,8 +61,9 @@ MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
VAR p: LONGINT;
BEGIN p := Pos();
IF (p > errpos) & (errcnt < 25) THEN
Console.Ln; Console.String(" pos "); Console.Int(p, 1); Console.Char(" ");
Console.String(msg)
Texts.WriteLn(W); Texts.WriteString(W, " pos "); Texts.WriteInt(W, p, 1); Texts.Write(W, " ");
Texts.WriteString(W, msg); Texts.Append(Oberon.Log, W.buf);
Oberon.DumpLog;
END ;
INC(errcnt); errpos := p + 4
END Mark;
@ -124,7 +126,7 @@ MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
END Ten;
PROCEDURE Number(VAR sym: INTEGER);
CONST max = 2147483647 (*2^31*); maxM = 16777216; (*2^24*)
CONST max = 2147483647 (*2^31 - 1*);
VAR i, k, e, n, s, h: LONGINT; x: REAL;
d: ARRAY 16 OF INTEGER;
negE: BOOLEAN;
@ -149,25 +151,24 @@ MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
IF ch = "." THEN (*double dot*) ch := 7FX; (*decimal integer*)
REPEAT
IF d[i] < 10 THEN
h := k*10 + d[i];
IF h < max THEN k := h ELSE Mark("too large") END
IF k <= (max-d[i]) DIV 10 THEN k := k *10 + d[i] ELSE Mark("too large"); k := 0 END
ELSE Mark("bad integer")
END ;
INC(i)
UNTIL i = n;
sym := int; ival := k
ELSE (*real number*) x := 0.0; e := 0;
REPEAT (*integer part*) h := k*10 + d[i];
IF h < maxM THEN k := h ELSE Mark("too many digits") END ;
INC(i)
UNTIL i = n;
WHILE (ch >= "0") & (ch <= "9") DO (*fraction*)
h := k*10 + ORD(ch) - 30H;
IF h < maxM THEN k := h ELSE Mark("too many digits*") END ;
DEC(e); Texts.Read(R, ch)
REPEAT (*integer part*)
(*x := x * 10.0 + FLT(d[i]); *)
x := x * 10.0 + (d[i]); (* voc adaptation by noch *)
INC(i)
UNTIL i = n;
WHILE (ch >= "0") & (ch <= "9") DO (*fraction*)
(*x := x * 10.0 + FLT(ORD(ch) - 30H);*)
x := x * 10.0 + (ORD(ch) - 30H); (* voc adaptation by noch *)
DEC(e);
Texts.Read(R, ch)
END ;
(*x := FLT(k);*)
x := S.VAL(REAL, k);
IF (ch = "E") OR (ch = "D") THEN (*scale factor*)
Texts.Read(R, ch); s := 0;
IF ch = "-" THEN negE := TRUE; Texts.Read(R, ch)
@ -275,8 +276,9 @@ MODULE ORS; (* NW 19.9.93 / 10.10.2013 Scanner in Oberon-07*)
PROCEDURE EnterKW(sym: INTEGER; name: ARRAY OF CHAR);
BEGIN
(*keyTab[k].id := name; *)
COPY(name, keyTab[k].id);
keyTab[k].sym := sym; INC(k)
COPY(name, keyTab[k].id); (* voc adaptation by noch *)
keyTab[k].sym := sym;
INC(k)
END EnterKW;
BEGIN Texts.OpenWriter(W); k := 0; KWX[0] := 0; KWX[1] := 0;

103
src/voc07R/Oberon.Mod Normal file
View file

@ -0,0 +1,103 @@
MODULE Oberon;
IMPORT Args, Strings, Texts := CompatTexts, (*Files := CompatFiles,*) Out := Console;
VAR Log*: Texts.Text;
Par*: RECORD
text*: Texts.Text;
pos* : LONGINT;
END;
arguments : ARRAY 2048 OF CHAR;
PROCEDURE GetSelection* (VAR text: Texts.Text; VAR beg, end, time: LONGINT);
(*VAR M: SelectionMsg;*)
BEGIN
(*M.time := -1; Viewers.Broadcast(M); time := M.time;
IF time >= 0 THEN text := M.text; beg := M.beg; end := M.end END*)
END GetSelection;
PROCEDURE Collect*( count : LONGINT);
BEGIN
END Collect;
PROCEDURE ArgsToString(VAR opts : ARRAY OF CHAR);
VAR i : INTEGER;
opt : ARRAY 256 OF CHAR;
BEGIN
i := 1;
opt := ""; COPY ("", opts);
WHILE i < Args.argc DO
Args.Get(i, opt);
Strings.Append(opt, opts);(* Strings.Append (" ", opts);*)
INC(i)
END;
END ArgsToString;
PROCEDURE StringToText(VAR arguments : ARRAY OF CHAR; VAR T : Texts.Text);
VAR
W : Texts.Writer;
BEGIN
Texts.OpenWriter(W);
Texts.WriteString(W, arguments);
Texts.Append (T, W.buf);
END StringToText;
(*
PROCEDURE WriteTextToFile(VAR T : Texts.Text; filename : ARRAY OF CHAR);
VAR f : Files.File; r : Files.Rider;
BEGIN
f := Files.New(filename);
Files.Set(r, f, 0);
Texts.Store(r, T);
Files.Register(f);
END WriteTextToFile;
*)
PROCEDURE TextToString(VAR T : Texts.Text; VAR string : ARRAY OF CHAR);
VAR R : Texts.Reader;
ch : CHAR;
i : LONGINT;
BEGIN
COPY("", string);
Texts.OpenReader(R, T, 0);
i := 0;
WHILE Texts.Pos(R) < T.len DO
Texts.Read(R, ch);
string[i] := ch;
INC(i);
END;
(*string[i] := 0X;*)
END TextToString;
PROCEDURE DumpLog*;
VAR s : POINTER TO ARRAY OF CHAR;
BEGIN
NEW(s, Log.len + 1);
COPY("", s^);
TextToString(Log, s^);
Out.String(s^); Out.Ln;
NEW(Log);
Texts.Open(Log, "");
END DumpLog;
BEGIN
NEW(Log);
Texts.Open(Log, "");
NEW(Par.text);
Texts.Open(Par.text, "");
Par.pos := 0;
COPY("", arguments);
ArgsToString(arguments);
StringToText(arguments, Par.text);
(*WriteTextToFile(Par.text, "params.txt");*)
(*WriteTextToFile(Log, "log.txt");*)
(*DumpLog;*)
END Oberon.

View file

@ -7,7 +7,9 @@ all:
#$(VOC0) -s ORS.Mod
#$(VOC0) -s ORB.Mod
#$(VOC0) -s ORG.Mod
$(VOC0) -s ORS.Mod ORB.Mod ORG.Mod ORP.Mod -M
$(VOC0) -s CompatFiles.Mod \
Fonts.Mod CompatTexts.Mod Oberon.Mod \
ORS.Mod ORB.Mod ORG.Mod ORP.Mod -M
test:
./ORP -s test.Mod

BIN
voc

Binary file not shown.