IMPLEMENTATION MODULE CmdArgs ;
FROM ASCII IMPORT cr, nul ;
FROM StrLib IMPORT StrLen ;
CONST
esc = '\' ;
space = ' ' ;
squote = "'" ;
dquote = '"' ;
tab = ' ' ;
PROCEDURE GetArg (CmdLine: ARRAY OF CHAR ;
n: CARDINAL; VAR Argi: ARRAY OF CHAR) : BOOLEAN ;
VAR
Index,
i : CARDINAL ;
Another: BOOLEAN ;
BEGIN
Index := 0 ;
i := 0 ;
REPEAT
Another := GetNextArg(CmdLine, Index, Argi) ;
INC(i) ;
UNTIL (i>n) OR (NOT Another) ;
RETURN( i>n )
END GetArg ;
PROCEDURE GetNextArg (CmdLine: ARRAY OF CHAR; VAR CmdIndex: CARDINAL;
VAR Arg: ARRAY OF CHAR) : BOOLEAN ;
VAR
ArgIndex: CARDINAL ;
HighA,
HighC: CARDINAL ;
BEGIN
HighA := HIGH(Arg) ;
HighC := StrLen(CmdLine) ;
ArgIndex := 0 ;
WHILE (CmdIndex<HighC) AND Space(CmdLine[CmdIndex]) DO
INC(CmdIndex)
END ;
IF CmdIndex<HighC
THEN
IF SingleQuote(CmdLine[CmdIndex])
THEN
INC(CmdIndex) ;
CopyUntil(CmdLine, CmdIndex, HighC, Arg, ArgIndex, HighA, squote) ;
INC(CmdIndex)
ELSIF DoubleQuote(CmdLine[CmdIndex])
THEN
INC(CmdIndex) ;
CopyUntil(CmdLine, CmdIndex, HighC, Arg, ArgIndex, HighA, dquote) ;
INC(CmdIndex)
ELSE
CopyUntilSpace(CmdLine, CmdIndex, HighC, Arg, ArgIndex, HighA)
END
END ;
WHILE (CmdIndex<HighC) AND Space(CmdLine[CmdIndex]) DO
INC(CmdIndex)
END ;
IF ArgIndex<HighA
THEN
Arg[ArgIndex] := nul
END ;
RETURN( (CmdIndex<HighC) )
END GetNextArg ;
PROCEDURE CopyUntilSpace (From: ARRAY OF CHAR;
VAR FromIndex: CARDINAL; FromHigh: CARDINAL;
VAR To: ARRAY OF CHAR;
VAR ToIndex: CARDINAL; ToHigh: CARDINAL) ;
BEGIN
WHILE (FromIndex<FromHigh) AND (ToIndex<ToHigh) AND
(NOT Space(From[FromIndex])) DO
CopyChar(From, FromIndex, FromHigh, To, ToIndex, ToHigh)
END
END CopyUntilSpace ;
PROCEDURE CopyUntil (From: ARRAY OF CHAR;
VAR FromIndex: CARDINAL; FromHigh: CARDINAL;
VAR To: ARRAY OF CHAR;
VAR ToIndex: CARDINAL; ToHigh: CARDINAL;
UntilChar: CHAR) ;
BEGIN
WHILE (FromIndex<FromHigh) AND (ToIndex<ToHigh) AND
(From[FromIndex]#UntilChar) DO
CopyChar(From, FromIndex, FromHigh, To, ToIndex, ToHigh)
END
END CopyUntil ;
PROCEDURE CopyChar (From: ARRAY OF CHAR;
VAR FromIndex: CARDINAL; FromHigh: CARDINAL;
VAR To: ARRAY OF CHAR;
VAR ToIndex: CARDINAL; ToHigh: CARDINAL) ;
BEGIN
IF (FromIndex<FromHigh) AND (ToIndex<ToHigh)
THEN
IF Escape(From[FromIndex])
THEN
INC(FromIndex)
END ;
IF FromIndex<FromHigh
THEN
To[ToIndex] := From[FromIndex] ;
INC(ToIndex) ;
INC(FromIndex)
END
END
END CopyChar ;
PROCEDURE Narg (CmdLine: ARRAY OF CHAR) : CARDINAL ;
VAR
a : ARRAY [0..1000] OF CHAR ;
ArgNo: CARDINAL ;
BEGIN
ArgNo := 0 ;
WHILE GetArg(CmdLine, ArgNo, a) DO
INC( ArgNo )
END ;
RETURN( ArgNo )
END Narg ;
PROCEDURE Escape (ch: CHAR) : BOOLEAN ;
BEGIN
RETURN( ch=esc )
END Escape ;
PROCEDURE Space (ch: CHAR) : BOOLEAN ;
BEGIN
RETURN( (ch=space) OR (ch=tab) )
END Space ;
PROCEDURE DoubleQuote (ch: CHAR) : BOOLEAN ;
BEGIN
RETURN( ch=dquote )
END DoubleQuote ;
PROCEDURE SingleQuote (ch: CHAR) : BOOLEAN ;
BEGIN
RETURN( ch=squote )
END SingleQuote ;
END CmdArgs.