ArgsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, June 6, 1986 1:33:29 pm PDT
DIRECTORY Args, Commander, CommandTool, Convert, IO, Rope;
ArgsImpl: CEDAR PROGRAM
IMPORTS Commander, CommandTool, Convert, IO, Rope
EXPORTS Args
~ {
Arg: TYPE ~ Args.Arg;
NArgs: PUBLIC PROC [cmd: Commander.Handle] RETURNS [INTEGER] ~ {
RETURN[CommandTool.Parse[cmd].argc-1];
};
GetRope: PUBLIC PROC [cmd: Commander.Handle, nArg: INTEGER ← 0] RETURNS [Rope.ROPE] ~ {
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd];
RETURN [IF argv.argc < nArg+2 OR nArg < 0 THEN NIL ELSE argv[nArg+1]];
};
ArgRope: PUBLIC PROC [cmd: Commander.Handle, nArg: INTEGER ← 0] RETURNS [a: Arg] ~ {
a.rope ← GetRope[cmd, nArg];
a.ok ← a.rope # NIL;
};
ArgReal: PUBLIC PROC [cmd: Commander.Handle, nArg: INTEGER ← 0] RETURNS [a: Arg] ~ {
r: Rope.ROPE ← GetRope[cmd, nArg];
a.ok ← r # NIL;
IF a.ok THEN a.real ← Convert.RealFromRope[r ! Convert.Error => {a.ok ← FALSE; CONTINUE}];
};
ArgInt: PUBLIC PROC [cmd: Commander.Handle, nArg: INTEGER ← 0] RETURNS [a: Arg] ~ {
r: Rope.ROPE ← GetRope[cmd, nArg];
a.ok ← r # NIL;
IF a.ok THEN a.int ← Convert.IntFromRope[r ! Convert.Error => {a.ok ← FALSE; CONTINUE}];
};
ArgIntDef: PUBLIC PROC [cmd: Commander.Handle, nArg: INTEGER ← 0, defVal: INT] RETURNS [a: Arg] ~ {
r: Rope.ROPE ← GetRope[cmd, nArg];
a.ok ← TRUE;
a.int ← IF r = NIL
THEN defVal
ELSE Convert.IntFromRope[r ! Convert.Error => {a.ok ← FALSE; CONTINUE}];
};
ArgIntRange: PUBLIC PROC [cmd: Commander.Handle, n, min, max: INT] RETURNS [arg: Arg] ~ {
arg ← ArgInt[cmd, n];
IF NOT arg.ok THEN RETURN;
IF arg.ok THEN arg.ok ← arg.int >= min AND arg.int <= max;
};
ArgsGet: PUBLIC PROC [cmd: Commander.Handle, fmt: Rope.ROPE] RETURNS [BOOL, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg] ~ {
retOK: BOOLTRUE;
maxNRet: INTEGER ~ 12;
maxNArgs: INTEGER ~ 100;
retArgs: ARRAY[0..maxNRet) OF Arg;
usedArgs: PACKED ARRAY [0..maxNArgs) OF BOOLALL[FALSE];
nArgs: INTEGERMIN[maxNArgs, NArgs[cmd]];
fmtLength: INTEGER ← Rope.Length[fmt];
argIndex: INTEGER ← 0;
fmtIndex: INTEGER ← 0;
retIndex: INTEGER ← 0;
SetRets: enter at '% or ']; return at next '%, '[, '-, or end of format string.
SetRets: PROC ~ {
optional: BOOL ← Rope.Fetch[fmt, fmtIndex] = '[;
fmtIndex ← fmtIndex+1;
WHILE fmtIndex < fmtLength AND retIndex < maxNRet DO
c: CHAR ← Rope.Fetch[fmt, fmtIndex];
SELECT c FROM
'%, '[, '-, IO.SP => RETURN;
'b => retArgs[retIndex] ← [ok: TRUE, bool: TRUE];
'i, 's, 'r => {
WHILE argIndex < nArgs AND usedArgs[argIndex] DO
argIndex ← argIndex+1;
ENDLOOP;
IF argIndex >= nArgs THEN {
IF NOT optional THEN retOK ← FALSE;
fmtIndex ← Rope.SkipTo[fmt, fmtIndex, "-"];
RETURN
};
retArgs[retIndex] ← SELECT c FROM
'i => ArgInt[cmd, argIndex],
's => ArgRope[cmd, argIndex],
'r => ArgReal[cmd, argIndex],
ENDCASE => [];
IF NOT retArgs[retIndex].ok THEN retOK ← FALSE;
usedArgs[argIndex] ← TRUE;
argIndex ← argIndex+1;
};
ENDCASE => {
retOK ← FALSE;
fmtIndex ← Rope.SkipTo[fmt, fmtIndex, "%[-"];
RETURN
};
fmtIndex ← fmtIndex+1;
retIndex ← retIndex+1;
ENDLOOP;
};
SkipTokens: enter at '% or ']; return at next '%, '[, '-, or end of format string.
SkipTokens: PROC ~ {
fmtIndex ← fmtIndex+1;
WHILE fmtIndex < fmtLength DO
SELECT Rope.Fetch[fmt, fmtIndex] FROM
'i, 's, 'r, 'b => retIndex ← retIndex+1;
'%, '[, '- => RETURN;
ENDCASE => {retOK ← FALSE; RETURN};
fmtIndex ← fmtIndex+1;
ENDLOOP;
};
WHILE fmtIndex < fmtLength DO      -- first, set hyphenated arguments:
SELECT Rope.Fetch[fmt, fmtIndex] FROM
'%, '[ => SkipTokens[];
'- => {
key: Rope.ROPE;
n: INTEGER ← Rope.SkipTo[fmt, fmtIndex, "[%"];
IF n = fmtLength THEN {retOK ← FALSE; EXIT};
key ← Rope.Substr[fmt, fmtIndex, n-fmtIndex];
fmtIndex ← n;
argIndex ← 1;
WHILE argIndex <= nArgs DO
IF GetRope[cmd, argIndex-1].Equal[key] THEN {
usedArgs[argIndex-1] ← TRUE;
SetRets[];
EXIT;
};
argIndex ← argIndex+1;
REPEAT
FINISHED => fmtIndex ← Rope.SkipTo[fmt, fmtIndex, "-%["];
ENDLOOP;
};
ENDCASE => {fmtIndex ← Rope.SkipTo[fmt, fmtIndex, "-%["]; retOK ← FALSE};
ENDLOOP;
argIndex ← retIndex ← fmtIndex ← 0;     -- now set non-hyphenated arguments:
WHILE fmtIndex < fmtLength DO
SELECT Rope.Fetch[fmt, fmtIndex] FROM
'- => {fmtIndex ← Rope.SkipTo[fmt, fmtIndex, "%"]; SkipTokens[]};
'%, '[ => SetRets[];
ENDCASE => {retOK ← FALSE; fmtIndex ← fmtIndex+1};
ENDLOOP;
FOR n: INTEGER IN[0..nArgs) DO IF NOT usedArgs[n] THEN retOK ← FALSE; ENDLOOP;
RETURN[retOK, retArgs[0], retArgs[1], retArgs[2], retArgs[3], retArgs[4], retArgs[5], retArgs[6], retArgs[7], retArgs[8], retArgs[9], retArgs[10], retArgs[11]];
};
TestArgs: Commander.CommandProc ~ {
PrintArg: PROC [arg: Arg] ~ {
cmd.out.PutF["ok: %g\tbool: %g\tint: %g\treal: %g\trope: %g\n", IO.bool[arg.ok], IO.bool[arg.bool], IO.int[arg.int], IO.real[arg.real], IO.rope[arg.rope]];
};
ok: BOOL;
args: ARRAY[0..6) OF Arg;
[ok, args[0], args[1], args[2], args[3], args[4], args[5]] ← ArgsGet[cmd, "-i%ii-b%b%r%s"];
[ok, args[0], args[1], args[2], args[3], args[4], args[5]] ← ArgsGet[cmd, "-i%ii-b%b"];
cmd.out.PutF["ok is %g\n", IO.bool[ok]];
FOR n: INTEGER IN[0..6) DO PrintArg[args[n]]; ENDLOOP;
};
Commander.Register["///Commands/TestArgs", TestArgs, "\nTestArgs [argument list]."];
}.