oocProgramArgs compatibility library. two examples.

This commit is contained in:
Norayr Chilingarian 2026-09-18 04:19:37 +04:00
parent 575ea5c236
commit 552eade09d
7 changed files with 310 additions and 1 deletions

View file

@ -356,6 +356,8 @@ cd %BUILDDIR%\%MODEL%
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocSysClock.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocTime.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocChannel.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocProgramArgsHost.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocProgramArgs.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocStrings2.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocRts.Mod || exit /b
%ROOTDIR%\%OBECOMP% -Ffs -O%MODEL% ../../../src/library/ooc/oocFilenames.Mod || exit /b

View file

@ -0,0 +1,182 @@
(* 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.

View file

@ -0,0 +1,45 @@
(* Raw command-line access used by oocProgramArgs. *)
MODULE oocProgramArgsHost;
IMPORT SYSTEM, Modules;
TYPE
Byte* = SYSTEM.BYTE;
PROCEDURE Count* (): LONGINT;
BEGIN
RETURN Modules.ArgCount
END Count;
PROCEDURE Address(index: LONGINT): SYSTEM.ADDRESS;
VAR address: SYSTEM.ADDRESS;
BEGIN
ASSERT((index >= 0) & (index < Modules.ArgCount));
SYSTEM.GET(Modules.ArgVector + index*SIZE(SYSTEM.ADDRESS), address);
RETURN address
END Address;
PROCEDURE Length* (index: LONGINT): LONGINT;
VAR address: SYSTEM.ADDRESS; ch: Byte; length: LONGINT;
BEGIN
address := Address(index);
length := 0;
SYSTEM.GET(address, ch);
WHILE SYSTEM.VAL(CHAR, ch) # 0X DO
INC(length);
SYSTEM.GET(address+length, ch)
END;
RETURN length
END Length;
PROCEDURE Get* (index, offset: LONGINT; VAR ch: Byte);
BEGIN
SYSTEM.GET(Address(index)+offset, ch)
END Get;
PROCEDURE IsEol* (ch: Byte): BOOLEAN;
BEGIN
RETURN SYSTEM.VAL(CHAR, ch) = 0AX
END IsEol;
END oocProgramArgsHost.

View file

@ -0,0 +1,43 @@
MODULE testArgs;
(**Demonstrates reading command-line arguments via TextRider.
Each argument is presented as a separate line in the ProgramArgs channel.
The first line is always argv[0] (the program name); the actual arguments
start from the second line. ConnectReader attaches a TextRider.Reader to
that channel so arguments can be read as strings, integers, or reals.
Usage:
bin/testArgs hello 42 3.14
*)
IMPORT
Out, ProgramArgs, TextRider;
PROCEDURE Run;
VAR
r: TextRider.Reader;
arg: ARRAY 1024 OF CHAR;
n, i: LONGINT;
BEGIN
n := ProgramArgs.args.ArgNumber();
Out.String("argument count: "); Out.Int(n, 0); Out.Ln;
r := TextRider.ConnectReader(ProgramArgs.args);
(* first line is the program name (argv[0]) — skip it *)
r.ReadLine(arg);
i := 0;
WHILE r.res = TextRider.done DO
r.ReadLine(arg);
IF r.res = TextRider.done THEN
Out.String("arg "); Out.Int(i, 0);
Out.String(": "); Out.String(arg); Out.Ln;
INC(i)
END
END
END Run;
BEGIN
Run
END testArgs.

View file

@ -0,0 +1,35 @@
MODULE testReader;
IMPORT oocFiles, oocTextRider, Out;
VAR f: oocFiles.File;
r: oocTextRider.Reader;
b: BOOLEAN;
ch: CHAR;
size: LONGINT;
res: oocFiles.Result;
BEGIN
b := oocFiles.Exists("test.Mod");
IF b THEN
f := oocFiles.Old("test.Mod", {oocFiles.read}, res);
IF res # oocFiles.done THEN
Out.String("cannot open file"); Out.Ln
ELSE
size := f.Length();
Out.String("file size: "); Out.Int(size, 0); Out.Ln;
r := oocTextRider.ConnectReader(f);
IF r = NIL THEN
Out.String("connecting reader failed"); Out.Ln
ELSE
WHILE (r.res = oocTextRider.done) & (r.Pos() < size) DO
r.ReadChar(ch);
IF r.res = oocTextRider.done THEN Out.Char(ch) END
END
END;
f.Close
END
ELSE
Out.String("file does not exist"); Out.Ln
END
END testReader.

View file

@ -280,6 +280,8 @@ ooc:
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocSysClock.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocTime.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocChannel.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocProgramArgsHost.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocProgramArgs.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocStrings2.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocRts.Mod
cd $(BUILDDIR)/$(MODEL); "$(ROOTDIR)/$(OBECOMP)" -Fs -O$(MODEL) ../../../src/library/ooc/oocFilenames.Mod

View file

@ -160,7 +160,7 @@ stage6:
$(VOCSTATIC) -sPF oocComplexMath.Mod oocLComplexMath.Mod
$(VOCSTATIC) -sPF oocLRealConv.Mod oocLRealStr.Mod
$(VOCSTATIC) -sPF oocRealConv.Mod oocRealStr.Mod
$(VOCSTATIC) -sPF oocMsg.Mod oocChannel.Mod
$(VOCSTATIC) -sPF oocMsg.Mod oocChannel.Mod oocProgramArgsHost.Mod oocProgramArgs.Mod
$(VOCSTATIC) -sPF oocStrings2.Mod oocRts.Mod oocFilenames.Mod
$(VOCSTATIC) -sPF oocTextRider.Mod oocBinaryRider.Mod oocJulianDay.Mod oocFilesHost.Mod oocFiles.Mod
$(VOCSTATIC) -sPF oocFilenames.Mod