Rus: Простой но довольно мощный парсер строки, который позволяет разбирать как POSIX так и Windows стили аргументов
Eng: Simple but powerful command line parser which recognizes any kind of POSIX and Windows arguments
code:
{$Mode ObjFPC}
{$H+}
UNIT CmdLine;
INTERFACE
TYPE
CLOption = RECORD
Name: String;
Value: String;
END;
CLOptions = ARRAY OF CLOption;
FUNCTION CLCompose(cmdLine: String = ''): String; STDCALL;
FUNCTION CLParse(cmdLine: String): CLOptions; STDCALL;
IMPLEMENTATION
USES SysUtils;
FUNCTION CLCompose(cmdLine: String = ''): String; STDCALL;
FUNCTION _AddQuotes(str: String): String;
BEGIN
IF Pos(' ', str) > 0
THEN
RESULT := Format('"%s"', [str])
ELSE
RESULT := str
END;
VAR
i: LongWord;
BEGIN
RESULT := '';
IF Length(cmdLine) = 0
THEN
FOR i := 1 TO ParamCount() DO
IF Length(RESULT) = 0
THEN
RESULT := _AddQuotes(ParamStr(i))
ELSE
RESULT := Format('%s %s', [RESULT, _AddQuotes(ParamStr(i))])
ELSE
RESULT := cmdLine
END;
FUNCTION CLParse(cmdLine: String): CLOptions; STDCALL;
CONST
_SpaceChars = [#$20, #$09, #$0D, #$0A];
_EqChars = [':', '='];
_QChars = ['''', '"'];
PROCEDURE _SkipSpace(VAR str: String; VAR i: LongWord);
BEGIN
WHILE cmdLine[i] IN _SpaceChars
DO Inc(i)
END;
FUNCTION _GetString(VAR str: String; VAR i: LongWord): String;
VAR
chPos: LongWord;
BEGIN
chPos := i+1;
WHILE (str[chPos] <> str[i]) AND (chPos <= Length(str))
DO Inc(chPos);
RESULT := Copy(str, i+1, chPos - i - 1 );
IF str[i] <> str[chPos]
THEN RAISE Exception.Create(Format( 'String {%c}[[ %s ]]{%c} must be have quote on the end', [str[i], RESULT, str[chPos]] ));
i := chPos + 1
END;
FUNCTION _GetValue(VAR str: String; VAR i: LongWord): String;
VAR
chPos: LongWord;
BEGIN
chPos := i;
WHILE (NOT (str[chpos] IN _SpaceChars)) AND (chPos <= Length(str))
DO Inc(chPos);
RESULT := Copy(str, i, chPos - i + 1);
i := chPos
END;
FUNCTION _GetOptionName(VAR str: String; VAR i: LongWord): String;
VAR
chBeg, chEnd: LongWord;
BEGIN
IF str[i+1] = '-'
THEN chBeg := i+2
ELSE chBeg := i+1;
chEnd := chBeg;
WHILE (NOT (str[chEnd] IN (_EqChars + _SpaceChars))) AND (chEnd <= Length(str))
DO Inc(chEnd);
RESULT := Copy(str, chBeg, chEnd - chBeg);
i := chEnd
END;
FUNCTION _GetOptionValue(VAR str: String; VAR i: LongWord): String;
VAR
chPos: LongWord;
BEGIN
chPos := i;
IF str[i] IN _EqChars
THEN BEGIN
chPos := i + 1;
IF str[i + 1] IN _QChars
THEN
RESULT := _GetString(str, chPos)
ELSE
RESULT := _GetValue(str, chPos)
END;
i := chPos
END;
VAR
i : LongWord;
pPos: LongWord;
BEGIN
pPos := 0;
i := 1;
SetLength(RESULT, 0);
WHILE i < Length(cmdLine) DO BEGIN
_SkipSpace( cmdLine, i );
CASE cmdLine[i] OF
'''', '"' :
BEGIN
Inc(pPos);
SetLength(RESULT, Length(RESULT) + 1);
WITH RESULT[ Length(RESULT) - 1 ] DO BEGIN
Name := Format('%d', [pPos]);
Value := _GetString(cmdLine, i);
END;
END;
'-', '/' :
BEGIN
SetLength(RESULT, Length(RESULT) + 1);
WITH RESULT[ Length(RESULT) - 1 ] DO BEGIN
Name := _GetOptionName(cmdLine, i);
Value := _GetOptionValue(cmdLine, i);
END;
END;
ELSE
BEGIN
Inc(pPos);
SetLength(RESULT, Length(RESULT) + 1);
WITH RESULT[ Length(RESULT) - 1 ] DO BEGIN
Name := Format('%d', [pPos]);
Value := _GetValue(cmdLine, i);
END;
END;
END
END
END;
END.