compiler/src/library/ooc/oocProgramArgs.Mod
2026-09-18 04:19:37 +04:00

182 lines
4.2 KiB
Modula-2

(* oo2c 1.x command-line arguments represented as a read-only channel. *)
MODULE oocProgramArgs;
IMPORT
Host := oocProgramArgsHost, Channel0 := oocChannel,
CharClass := oocCharClass, Time := oocTime, Msg := oocMsg;
CONST
done* = Channel0.done;
outOfRange* = Channel0.outOfRange;
readAfterEnd* = Channel0.readAfterEnd;
channelClosed* = Channel0.channelClosed;
noWriteAccess* = Channel0.noWriteAccess;
noModTime* = Channel0.noModTime;
TYPE
Channel* = POINTER TO ChannelDesc;
ChannelDesc = RECORD
(Channel0.ChannelDesc)
END;
Reader = POINTER TO ReaderDesc;
ReaderDesc = RECORD
(Channel0.ReaderDesc)
argument, offset, position: LONGINT
END;
ErrorContext = POINTER TO ErrorContextDesc;
ErrorContextDesc* = RECORD
(Channel0.ErrorContextDesc)
END;
VAR
args-: Channel;
errorContext: ErrorContext;
PROCEDURE GetError(code: Msg.Code): Msg.Msg;
BEGIN
RETURN Msg.New(errorContext, code)
END GetError;
PROCEDURE (r: Reader) Pos* (): LONGINT;
BEGIN
RETURN r.position
END Pos;
PROCEDURE (r: Reader) Available* (): LONGINT;
VAR available: LONGINT;
BEGIN
IF ~r.base.open THEN RETURN -1 END;
available := r.base.Length()-r.position;
IF available > 0 THEN RETURN available ELSE RETURN 0 END
END Available;
PROCEDURE (r: Reader) SetPos* (newPos: LONGINT);
VAR argument, length, remaining: LONGINT;
BEGIN
IF r.res = done THEN
IF newPos < 0 THEN
r.res := GetError(outOfRange)
ELSIF ~r.base.open THEN
r.res := GetError(channelClosed)
ELSE
argument := 0;
remaining := newPos;
WHILE (argument < Host.Count()) & (remaining > Host.Length(argument)) DO
DEC(remaining, Host.Length(argument)+1);
INC(argument)
END;
IF argument = Host.Count() THEN
r.offset := 0
ELSE
length := Host.Length(argument);
IF remaining > length THEN remaining := length END;
r.offset := remaining
END;
r.argument := argument;
r.position := newPos
END
END
END SetPos;
PROCEDURE (r: Reader) ReadByte* (VAR x: Host.Byte);
VAR length: LONGINT;
BEGIN
r.bytesRead := 0;
IF r.res = done THEN
IF ~r.base.open THEN
r.res := GetError(channelClosed)
ELSIF r.argument >= Host.Count() THEN
r.res := GetError(readAfterEnd)
ELSE
length := Host.Length(r.argument);
IF r.offset = length THEN
x := CharClass.eol;
INC(r.argument);
r.offset := 0
ELSE
Host.Get(r.argument, r.offset, x);
IF Host.IsEol(x) THEN x := " " END;
INC(r.offset)
END;
INC(r.position);
r.bytesRead := 1
END
END
END ReadByte;
PROCEDURE (r: Reader) ReadBytes* (VAR x: ARRAY OF Host.Byte; start, n: LONGINT);
VAR count: LONGINT;
BEGIN
ASSERT((n >= 0) & (start >= 0) & (start+n <= LEN(x)));
count := 0;
WHILE (count < n) & (r.res = done) DO
r.ReadByte(x[start+count]);
IF r.res = done THEN INC(count) END
END;
r.bytesRead := count
END ReadBytes;
PROCEDURE (ch: Channel) Length* (): LONGINT;
VAR argument, length: LONGINT;
BEGIN
argument := 0;
length := 0;
WHILE argument < Host.Count() DO
INC(length, Host.Length(argument)+1);
INC(argument)
END;
RETURN length
END Length;
PROCEDURE (ch: Channel) ArgNumber* (): LONGINT;
BEGIN
IF Host.Count() > 0 THEN RETURN Host.Count()-1 ELSE RETURN 0 END
END ArgNumber;
PROCEDURE (ch: Channel) GetModTime* (VAR mtime: Time.TimeStamp);
BEGIN
ch.res := GetError(noModTime)
END GetModTime;
PROCEDURE (ch: Channel) NewReader* (): Channel0.Reader;
VAR r: Reader;
BEGIN
IF ch.open THEN
NEW(r);
r.base := ch;
r.res := done;
r.bytesRead := 0;
r.positionable := TRUE;
r.argument := 0;
r.offset := 0;
r.position := 0;
ch.res := done;
RETURN r
ELSE
ch.res := GetError(channelClosed);
RETURN NIL
END
END NewReader;
PROCEDURE (ch: Channel) Flush*;
BEGIN
IF ch.open THEN ch.res := done ELSE ch.res := GetError(channelClosed) END
END Flush;
PROCEDURE (ch: Channel) Close*;
BEGIN
ch.open := FALSE;
ch.res := done
END Close;
BEGIN
NEW(errorContext);
Msg.InitContext(errorContext, "OOC:Core:ProgramArgs");
NEW(args);
args.res := done;
args.readable := TRUE;
args.writable := FALSE;
args.open := TRUE
END oocProgramArgs.