mirror of
https://github.com/vishapoberon/compiler.git
synced 2026-10-10 02:47:23 +00:00
adding ulm unix file and terminal streams.
This commit is contained in:
parent
fcf59d5d93
commit
9701249ad2
12 changed files with 1163 additions and 11 deletions
235
src/library/ulm/ulmUnixFiles.Mod
Normal file
235
src/library/ulm/ulmUnixFiles.Mod
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
(* Platform-backed port of Ulm's UnixFiles stream module. *)
|
||||
MODULE ulmUnixFiles;
|
||||
|
||||
IMPORT Events := ulmEvents, Priorities := ulmPriorities,
|
||||
RelatedEvents := ulmRelatedEvents, Services := ulmServices,
|
||||
Streams := ulmStreams, Sys := ulmSys, SysErrors := ulmSysErrors,
|
||||
SysIO := ulmSysIO, SysStat := ulmSysStat, SysTypes := ulmSysTypes,
|
||||
Platform, SYSTEM;
|
||||
|
||||
CONST
|
||||
illegalMode* = 0;
|
||||
invalidFd* = 1;
|
||||
errorcodes* = 2;
|
||||
|
||||
read* = 0;
|
||||
write* = 1;
|
||||
rdwr* = 2;
|
||||
create* = 4;
|
||||
condcreate* = 8;
|
||||
|
||||
TYPE
|
||||
ErrorCode* = SHORTINT;
|
||||
ErrorEvent* = POINTER TO ErrorEventRec;
|
||||
ErrorEventRec* = RECORD (Events.EventRec)
|
||||
errorcode*: ErrorCode
|
||||
END;
|
||||
|
||||
Mode* = SHORTINT;
|
||||
Stream* = POINTER TO StreamRec;
|
||||
StreamRec* = RECORD (Streams.StreamRec)
|
||||
file*: SysTypes.File;
|
||||
interrupted*: BOOLEAN;
|
||||
retry*: BOOLEAN
|
||||
END;
|
||||
|
||||
VAR
|
||||
error*: Events.EventType;
|
||||
errormsg*: ARRAY errorcodes OF Events.Message;
|
||||
interface: Streams.Interface;
|
||||
type: Services.Type;
|
||||
|
||||
PROCEDURE Error(errors: RelatedEvents.Object; errorcode: ErrorCode);
|
||||
VAR event: ErrorEvent;
|
||||
BEGIN
|
||||
NEW(event);
|
||||
event.type := error;
|
||||
event.message := errormsg[errorcode];
|
||||
event.errorcode := errorcode;
|
||||
RelatedEvents.Raise(errors, event)
|
||||
END Error;
|
||||
|
||||
PROCEDURE ReadBuf(s: Streams.Stream; address: SysTypes.Address;
|
||||
count: SysTypes.Count): SysTypes.Count;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
RETURN SysIO.Read(s.file, address, count, s, s.retry, s.interrupted)
|
||||
END
|
||||
END ReadBuf;
|
||||
|
||||
PROCEDURE WriteBuf(s: Streams.Stream; address: SysTypes.Address;
|
||||
count: SysTypes.Count): SysTypes.Count;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
RETURN SysIO.Write(s.file, address, count, s, s.retry, s.interrupted)
|
||||
END
|
||||
END WriteBuf;
|
||||
|
||||
PROCEDURE ReadByte(s: Streams.Stream; VAR byte: Streams.Byte): BOOLEAN;
|
||||
VAR count: SysTypes.Count;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
count := SysIO.Read(s.file, SYSTEM.ADR(byte), 1, s,
|
||||
s.retry, s.interrupted);
|
||||
RETURN count = 1
|
||||
END
|
||||
END ReadByte;
|
||||
|
||||
PROCEDURE WriteByte(s: Streams.Stream; byte: Streams.Byte): BOOLEAN;
|
||||
VAR count: SysTypes.Count;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
count := SysIO.Write(s.file, SYSTEM.ADR(byte), 1, s,
|
||||
s.retry, s.interrupted);
|
||||
RETURN count = 1
|
||||
END
|
||||
END WriteByte;
|
||||
|
||||
PROCEDURE Seek(s: Streams.Stream; offset: SysTypes.Count;
|
||||
whence: Streams.Whence): BOOLEAN;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
RETURN SysIO.Seek(s.file, offset, whence, s)
|
||||
END
|
||||
END Seek;
|
||||
|
||||
PROCEDURE Tell(s: Streams.Stream; VAR offset: SysTypes.Count): BOOLEAN;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
RETURN SysIO.Tell(s.file, offset, s)
|
||||
END
|
||||
END Tell;
|
||||
|
||||
PROCEDURE Close(s: Streams.Stream): BOOLEAN;
|
||||
BEGIN
|
||||
WITH s: Stream DO
|
||||
RETURN SysIO.Close(s.file, s, FALSE, s.interrupted)
|
||||
END
|
||||
END Close;
|
||||
|
||||
PROCEDURE OpenFd*(VAR s: Streams.Stream; fd: SysTypes.File;
|
||||
mode: Mode; bufmode: Streams.BufMode;
|
||||
errors: RelatedEvents.Object): BOOLEAN;
|
||||
VAR caps: Streams.CapabilitySet; newfile: Stream; stat: SysStat.StatRec;
|
||||
BEGIN
|
||||
IF ~SysStat.Fstat(fd, stat, errors) THEN
|
||||
Error(errors, invalidFd);
|
||||
RETURN FALSE
|
||||
END;
|
||||
|
||||
caps := {Streams.addrio, Streams.close};
|
||||
CASE mode OF
|
||||
| read: INCL(caps, Streams.read)
|
||||
| write: INCL(caps, Streams.write)
|
||||
| rdwr: caps := caps + {Streams.read, Streams.write}
|
||||
ELSE
|
||||
Error(errors, illegalMode);
|
||||
RETURN FALSE
|
||||
END;
|
||||
|
||||
IF SysIO.Seekable(fd) THEN
|
||||
caps := caps + {Streams.seek, Streams.tell, Streams.holes}
|
||||
END;
|
||||
|
||||
NEW(newfile);
|
||||
Services.Init(newfile, type);
|
||||
Streams.Init(newfile, interface, caps, bufmode);
|
||||
newfile.file := fd;
|
||||
newfile.interrupted := FALSE;
|
||||
newfile.retry := TRUE;
|
||||
RelatedEvents.QueueEvents(newfile);
|
||||
s := newfile;
|
||||
RETURN TRUE
|
||||
END OpenFd;
|
||||
|
||||
PROCEDURE Open*(VAR s: Streams.Stream; filename: ARRAY OF CHAR;
|
||||
mode: Mode; bufmode: Streams.BufMode;
|
||||
errors: RelatedEvents.Object): BOOLEAN;
|
||||
CONST accessMask = 4;
|
||||
VAR accessMode, openMode: Mode; access, creation: INTEGER;
|
||||
fd: SysTypes.File; interrupted: BOOLEAN; hostError: Platform.ErrorCode;
|
||||
BEGIN
|
||||
accessMode := mode MOD accessMask;
|
||||
openMode := mode - accessMode;
|
||||
|
||||
CASE accessMode OF
|
||||
| read: access := Platform.ReadOnly
|
||||
| write: access := Platform.WriteOnly
|
||||
| rdwr: access := Platform.ReadWrite
|
||||
ELSE
|
||||
Error(errors, illegalMode);
|
||||
RETURN FALSE
|
||||
END;
|
||||
|
||||
CASE openMode OF
|
||||
| 0: creation := Platform.OpenExisting
|
||||
| create: creation := Platform.CreateAlways
|
||||
| condcreate: creation := Platform.OpenAlways
|
||||
ELSE
|
||||
Error(errors, illegalMode);
|
||||
RETURN FALSE
|
||||
END;
|
||||
|
||||
filename[LEN(filename)-1] := 0X;
|
||||
REPEAT
|
||||
hostError := Platform.OpenFile(filename, access, creation, fd)
|
||||
UNTIL (hostError = 0) OR ~Platform.Interrupted(hostError);
|
||||
IF hostError # 0 THEN
|
||||
SysErrors.Raise(errors, hostError, Sys.open, filename);
|
||||
RETURN FALSE
|
||||
END;
|
||||
|
||||
IF OpenFd(s, fd, accessMode, bufmode, errors) THEN
|
||||
RETURN TRUE
|
||||
END;
|
||||
IF ~SysIO.Close(fd, errors, FALSE, interrupted) THEN END;
|
||||
RETURN FALSE
|
||||
END Open;
|
||||
|
||||
PROCEDURE InitInterface;
|
||||
BEGIN
|
||||
NEW(interface);
|
||||
interface.addrread := ReadBuf;
|
||||
interface.addrwrite := WriteBuf;
|
||||
interface.read := ReadByte;
|
||||
interface.write := WriteByte;
|
||||
interface.seek := Seek;
|
||||
interface.tell := Tell;
|
||||
interface.close := Close
|
||||
END InitInterface;
|
||||
|
||||
PROCEDURE InitStandardStreams;
|
||||
PROCEDURE Connect(VAR stream: Streams.Stream; fd: SysTypes.File; mode: Mode);
|
||||
VAR bufmode: Streams.BufMode;
|
||||
BEGIN
|
||||
IF fd = SysIO.StdErr() THEN
|
||||
bufmode := Streams.nobuf
|
||||
ELSIF SysIO.Isatty(fd) THEN
|
||||
bufmode := Streams.linebuf
|
||||
ELSIF fd = SysIO.StdOut() THEN
|
||||
(* ULM process termination is not wired into VOC program shutdown. *)
|
||||
bufmode := Streams.nobuf
|
||||
ELSE
|
||||
bufmode := Streams.onebuf
|
||||
END;
|
||||
IF ~OpenFd(stream, fd, mode, bufmode, NIL) THEN END
|
||||
END Connect;
|
||||
BEGIN
|
||||
Connect(Streams.stdin, SysIO.StdIn(), rdwr);
|
||||
Connect(Streams.stdout, SysIO.StdOut(), rdwr);
|
||||
Connect(Streams.stderr, SysIO.StdErr(), write);
|
||||
IF (Streams.GetBufMode(Streams.stdin) = Streams.linebuf) &
|
||||
(Streams.GetBufMode(Streams.stdout) = Streams.linebuf) THEN
|
||||
Streams.Tie(Streams.stdin, Streams.stdout)
|
||||
END
|
||||
END InitStandardStreams;
|
||||
|
||||
BEGIN
|
||||
errormsg[illegalMode] := "illegal opening mode";
|
||||
errormsg[invalidFd] := "invalid file descriptor";
|
||||
Events.Define(error);
|
||||
Events.SetPriority(error, Priorities.liberrors);
|
||||
InitInterface;
|
||||
Services.CreateType(type, "UnixFiles.Stream", "Streams.Stream");
|
||||
InitStandardStreams
|
||||
END ulmUnixFiles.
|
||||
Loading…
Add table
Add a link
Reference in a new issue