ArgsImpl.mesa
Copyright Ó 1985, 1991 by Xerox Corporation. All rights reserved.
Bloomenthal, October 22, 1992 3:26 pm PDT
Michael Plass, November 22, 1991 5:19 pm PST
Public Procedures
NArgs:
PUBLIC PROC [cmd: Commander.Handle]
RETURNS [
INTEGER] ~ {
RETURN[CommanderOps.Parse[cmd].argc-1];
};
GetRope:
PUBLIC PROC [cmd: Commander.Handle, nArg:
INTEGER ¬ 0]
RETURNS [
ROPE] ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.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 ¬ 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 ¬ 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 ¬ GetRope[cmd, nArg];
a.ok ¬ TRUE;
a.int ¬
IF
r
=
NIL
THEN Convert.IntFromRope[r ! Convert.Error => {a.ok ¬ FALSE; CONTINUE}]
ELSE defVal;
};
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;
};
Error:
PUBLIC
ERROR [reason:
ROPE] =
CODE;
ArgsGetFromRope:
PUBLIC
PROC [input, format:
ROPE, caseSensitive:
BOOL ¬
FALSE]
RETURNS [Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg]
~ {
a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17: Arg;
cmd: Commander.Handle ¬ CommanderOps.CreateFromStreams[];
cmd.commandLine ¬ input;
[a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17] ¬
ArgsGet[cmd, format, caseSensitive];
RETURN[a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17];
};
ArgsGet:
PUBLIC
PROC [cmd: Commander.Handle, format:
ROPE, caseSensitive:
BOOL ¬
FALSE]
RETURNS [Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg,Arg]
~ {
maxNRet: INTEGER ~ 18;
maxNArgs: INTEGER ~ 100;
retArgs: ARRAY[0..maxNRet) OF Arg;
usedArgs: PACKED ARRAY [0..maxNArgs) OF BOOL ¬ ALL[FALSE];
nArgs: INTEGER ¬ MIN[maxNArgs, NArgs[cmd]];
formatLength: INTEGER ¬ Rope.Length[format];
argIndex: INTEGER ¬ 0;
formatIndex: INTEGER ¬ 0;
retIndex: INTEGER ¬ 0;
SetRets: enter at '% or ']; return at next '%, '[, '-, or end of format string.
SetRets:
PROC ~ {
optional: BOOL ¬ Rope.Fetch[format, formatIndex] = '[;
formatIndex ¬ formatIndex+1;
WHILE formatIndex < formatLength
AND retIndex < maxNRet
DO
c: CHAR ¬ Rope.Fetch[format, formatIndex];
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 ERROR Error["Missing non-optional argument"];
formatIndex ¬ Rope.SkipTo[format, formatIndex, "-"];
RETURN
};
retArgs[retIndex] ¬
SELECT c
FROM
'i => ArgInt[cmd, argIndex],
's => ArgRope[cmd, argIndex],
'r => ArgReal[cmd, argIndex],
ENDCASE => [];
usedArgs[argIndex] ¬ TRUE;
argIndex ¬ argIndex+1;
IF
NOT retArgs[retIndex].ok
THEN {
IF NOT optional THEN Error["Conversion error"];
formatIndex ¬ formatIndex+1;
LOOP;
};
};
ENDCASE => {
formatIndex ¬ Rope.SkipTo[format, formatIndex, "%[-"];
Error["Unrecognized delimiter or specifier"];
RETURN
};
formatIndex ¬ formatIndex+1;
retIndex ¬ retIndex+1;
ENDLOOP;
};
SkipTokens: enter at '% or ']; return at next '%, '[, '-, or end of format string.
SkipTokens:
PROC ~ {
formatIndex ¬ formatIndex+1;
WHILE formatIndex < formatLength
DO
SELECT Rope.Fetch[format, formatIndex]
FROM
'i, 's, 'r, 'b => retIndex ¬ retIndex+1;
'%, '[, '- => RETURN;
ENDCASE => Error["Unrecognized delimiter or specifier"];
formatIndex ¬ formatIndex+1;
ENDLOOP;
};
WHILE formatIndex < formatLength
DO
-- first, set hyphenated arguments:
SELECT Rope.Fetch[format, formatIndex]
FROM
'%, '[ => SkipTokens[];
'- => {
key: ROPE;
n: INTEGER ¬ Rope.SkipTo[format, formatIndex, "[%"];
IF n = formatLength THEN Error["No matching specifier"];
key ¬ Rope.Substr[format, formatIndex, n-formatIndex];
formatIndex ¬ n;
argIndex ¬ 1;
WHILE argIndex <= nArgs
DO
IF Rope.Equal[GetRope[cmd, argIndex-1], key, caseSensitive]
THEN {
usedArgs[argIndex-1] ¬ TRUE;
SetRets[];
EXIT;
};
argIndex ¬ argIndex+1;
REPEAT
FINISHED => formatIndex ¬ Rope.SkipTo[format, formatIndex, "-%["];
ENDLOOP;
};
ENDCASE => {
formatIndex ¬ Rope.SkipTo[format, formatIndex, "-%["];
Error["Unrecognized delimiter"];
};
ENDLOOP;
argIndex ¬ retIndex ¬ formatIndex ¬ 0; -- now set non-hyphenated arguments:
WHILE formatIndex < formatLength
DO
SELECT Rope.Fetch[format, formatIndex]
FROM
'- => {formatIndex ¬ Rope.SkipTo[format, formatIndex, "%"]; SkipTokens[]};
'%, '[ => SetRets[];
ENDCASE => {
formatIndex ¬ formatIndex+1;
Error["Unrecognized delimiter"];
};
ENDLOOP;
FOR n:
INTEGER
IN[0..nArgs)
DO
IF NOT usedArgs[n] THEN Error["Extraneous argument"];
ENDLOOP;
RETURN[
retArgs[0], retArgs[1], retArgs[2], retArgs[3], retArgs[4], retArgs[5],
retArgs[6], retArgs[7], retArgs[8], retArgs[9], retArgs[10], retArgs[11],
retArgs[12], retArgs[13], retArgs[14], retArgs[15], retArgs[16], retArgs[17]];
};