1 { Version 040709. Copyright � Alexey A.Chernobaev, 1996-2004 }
2
3 unit ParseCmd;
4 {
5 Command line parsing.
6 ������ ��������� ������.
7
8 Example:
9 ������ �������������:
10
11 CmdParser:=TCommandLineParser.Create([], False);
12 try
13 CmdParser.Parse(Windows.GetCommandLine, 1);
14
15 for I:=0 to CmdParser.ParamCount - 1 do
16 if CmdParser.ParamStr(I) = ...
17
18 for I:=0 to CmdParser.SimpleParamCount - 1 do
19 if CmdParser.SimpleParamStr(I) = ...
20
21 for I:=0 to CmdParser.OptionCount - 1 do
22 if CmdParser.OptionStr(I) = ...
23
24 if CmdParser.HasOption('from') then ...
25 finally
26 CmdParser.Free;
27 end;
28 }
29
30 interface
31
32 {$I VCheck.inc}
33
34 uses
35 SysUtils, StrLst, VectStr;
36
37 type
38 TCommandLineParser = class
39 protected
40 FOptionPrefix: TCharSet;
41 FParamList, FSimpleList, FOptionValues: TStrLst;
42 FOptionKeys: TStrLstObj;
43 public
44 constructor Create(OptionPrefix: TCharSet{$IFDEF V_DEFAULTS} = []{$ENDIF};
45 CaseSensitive: Boolean{$IFDEF V_DEFAULTS} = False{$ENDIF});
46 { OptionPrefix: �������� ����� ��������� ������; ���� [], �� �����������
47 �������� �� ��������� ['/', '-']; ���� CaseSensitive = True, �� �����,
48 ����������� � ������ ��������, ��������� ����������, ����� ��� ���������
49 �������������� }
50 { OptionPrefix: command line option prefixes; if [] then default values
51 ['/', '-'] are used; if CaseSensitive = True then options in different
52 case are interpreted as different, otherwise as equivalent. }
53 destructor Destroy; override;
54 procedure Parse(const CommandLine: String; FromIndex: Integer;
55 QuotesDoubling: Boolean{$IFDEF V_DEFAULTS} = False{$ENDIF});
56 { ��������� ������ ������ CommandLine; ��� ���� ����� ���������������
57 ������ FromIndex ����������; ���� QuotesDoubling = True, �� �����
58 ��������� ������ ����������� ������� '"', ������� ������ ���� ������� }
59 { parses the string CommandLine ignoring first FromIndex parameters; if
60 QuotesDoubling = True then the character '"' is allowed among the
61 elements of the string }
ParamCountnull62 function ParamCount: Integer;
63 { ����� ���������� ���������� }
64 { total number of parameters }
ParamStrnull65 function ParamStr(I: Integer): String;
66 { I-�� �������� (I = 0..ParamCount - 1); ���� I >= ParamCount, ��
67 ������������ ������ ������ }
68 { Ith parameter (I = 0..ParamCount - 1); if I >= ParamCount then returns
69 empty string }
SimpleParamCountnull70 function SimpleParamCount: Integer;
71 { ���������� ������� ���������� (�.�. �� ������������ � OptionPrefix) }
72 { number of simple parameters (i.e. ones not beginning with OptionPrefix) }
SimpleParamStrnull73 function SimpleParamStr(I: Integer): String;
74 { I-�� ������� �������� (I = 0..SimpleParamCount - 1); ����
75 I >= SimpleParamCount, �� ������������ ������ ������ }
76 { Ith simple parameter (I = 0..SimpleParamCount - 1); if
77 I >= SimpleParamCount then returns empty string }
OptionCountnull78 function OptionCount: Integer;
79 { ���������� ����� (�.�. ����������, ������������ � OptionPrefix) }
80 { number of options (i.e. parameters beginning with OptionPrefix) }
OptionStrnull81 function OptionStr(I: Integer): String;
82 { I-�� ����� (I = 0..OptionCount - 1) �������; ���� I >= OptionCount,
83 �� ������������ ������ ������ }
84 { Ith option (I = 0..OptionCount - 1); if I >= OptionCount then empty string
85 will be returned }
HasOptionnull86 function HasOption(const OptionName: String): Boolean;
87 { ���������� True, ���� � ��������� ������ ������ ����� OptionName;
88 ��������, ����� Parse('/option') ����� HasOption('option') ���������
89 True (���� '/' ������ � AnOptionPrefix) }
90 { returns True if the command line contains an option OptionName; e.g. after
91 Parse('/option') call to HasOption('option') will return True (if '/' is
92 in AnOptionPrefix) }
RemoveOptionnull93 function RemoveOption(const OptionName: String): Boolean;
94 { ���������, ���� �� � ��������� ������ �������� �����, � ���� ��, ��
95 ������� � �� ����������� ������ ����� � ���������� True, ����� ����������
96 False }
97 { checks whether the command line contains the given option and if true then
98 removes it from the internal list of options and returns True else returns
99 False }
OptionValuenull100 function OptionValue(const OptionName: String; Remove: Boolean
101 {$IFDEF V_DEFAULTS} = False{$ENDIF}): String;
102 { ���������� �������� ����� OptionName; ��������, �����
103 Parse('/option:value') ����� OptionValue('option') ��������� 'value';
104 ���� HasOption(OptionName) = False, �� ������������ ������ ������;
105 ���� Remove = True, �� ����� ����� ������� �� ����������� ������ ����� }
106 { returns a value of option OptionName; e.g. a call to OptionValue('option')
107 after Parse('/option:value') will return 'value'; if
108 HasOption(OptionName) = False then an empty string will be returned; if
109 Remove = True then the option will be removed from the internal list of
110 options }
111 end;
112
113 implementation
114
115 {$IFDEF CHECK_OBJECTS_FREE}
116 uses ChckFree;
117 {$ENDIF}
118
119 constructor TCommandLineParser.Create(OptionPrefix: TCharSet; CaseSensitive: Boolean);
120 begin
121 inherited Create;
122 FParamList:=TStrLst.Create;
123 FSimpleList:=TStrLst.Create;
124 if CaseSensitive then
125 FOptionKeys:=TCaseSensStrLstObj.Create
126 else
127 FOptionKeys:=TStrLstObj.Create;
128 FOptionValues:=TStrLst.Create;
129 if OptionPrefix <> [] then
130 FOptionPrefix:=OptionPrefix
131 else
132 FOptionPrefix:=['/', '-'];
133 {$IFDEF CHECK_OBJECTS_FREE}
134 RegisterObjectCreate(Self);
135 {$ENDIF}
136 end;
137
138 destructor TCommandLineParser.Destroy;
139 begin
140 {$IFDEF CHECK_OBJECTS_FREE}
141 RegisterObjectFree(Self);
142 {$ENDIF}
143 FParamList.Free;
144 FSimpleList.Free;
145 FOptionKeys.Free;
146 FOptionValues.Free;
147 inherited Destroy;
148 end;
149
150 procedure TCommandLineParser.Parse(const CommandLine: String; FromIndex: Integer;
151 QuotesDoubling: Boolean);
152 var
153 ParamIndex: Integer;
154 S: String;
155
156 procedure ProcessParam;
157 var
158 I, J: Integer;
159 S1, S2: String;
160 begin
161 if S <> '' then begin
162 Inc(ParamIndex);
163 if ParamIndex > FromIndex then begin
164 I:=FParamList.Add(S);
165 if S[1] in FOptionPrefix then begin
166 J:=CharPos(':', S, 1);
167 if J > 0 then begin
168 S1:=Copy(S, 2, J - 2);
169 S2:=Copy(S, J + 1, Length(S));
170 J:=FOptionKeys.IndexOf(S1);
171 if J < 0 then begin
172 FOptionKeys.AddObject(S1, Pointer(I));
173 FOptionValues.Add(S2);
174 end
175 else begin
176 FOptionKeys.Objects[J]:=Pointer(I);
177 FOptionValues.Items[J]:=S2;
178 end;
179 end
180 else begin
181 FOptionKeys.AddObject(Copy(S, 2, Length(S)), Pointer(I));
182 FOptionValues.Add('');
183 end;
184 end
185 else
186 FSimpleList.Add(S);
187 end;
188 S:='';
189 end;
190 end;
191
192 var
193 I, L: Integer;
194 C: Char;
195 Quote: Boolean;
196 begin
197 FParamList.Clear;
198 FSimpleList.Clear;
199 FOptionKeys.Clear;
200 FOptionValues.Clear;
201 ParamIndex:=0;
202 S:='';
203 Quote:=False;
204 L:=Length(CommandLine);
205 I:=1;
206 while I <= L do begin
207 C:=CommandLine[I];
208 Case C of
209 '"':
210 begin
211 S:=S + C;
212 if Quote then begin
213 if QuotesDoubling and (I < L) and (CommandLine[I + 1] = '"') then begin
214 S:=S + '"';
215 Inc(I, 2);
216 Continue;
217 end;
218 ProcessParam;
219 end;
220 Quote:=not Quote;
221 end;
222 ' ':
223 if Quote then S:=S + C else ProcessParam;
224 Else
225 S:=S + C;
226 End;
227 Inc(I);
228 end;
229 ProcessParam;
230 FOptionKeys.SortWith(FOptionValues);
231 end;
232
ParamCountnull233 function TCommandLineParser.ParamCount: Integer;
234 begin
235 Result:=FParamList.Count;
236 end;
237
TCommandLineParser.ParamStrnull238 function TCommandLineParser.ParamStr(I: Integer): String;
239 begin
240 if (I >= 0) and (I < FParamList.Count) then
241 Result:=FParamList.Items[I]
242 else
243 Result:='';
244 end;
245
TCommandLineParser.SimpleParamCountnull246 function TCommandLineParser.SimpleParamCount: Integer;
247 begin
248 Result:=FSimpleList.Count;
249 end;
250
TCommandLineParser.SimpleParamStrnull251 function TCommandLineParser.SimpleParamStr(I: Integer): String;
252 begin
253 if (I >= 0) and (I < FSimpleList.Count) then
254 Result:=FSimpleList.Items[I]
255 else
256 Result:='';
257 end;
258
OptionCountnull259 function TCommandLineParser.OptionCount: Integer;
260 begin
261 Result:=FOptionKeys.Count;
262 end;
263
TCommandLineParser.OptionStrnull264 function TCommandLineParser.OptionStr(I: Integer): String;
265 begin
266 if (I >= 0) and (I < FOptionKeys.Count) then
267 Result:=FParamList.Items[Integer(FOptionKeys.Objects[I])]
268 else
269 Result:='';
270 end;
271
TCommandLineParser.HasOptionnull272 function TCommandLineParser.HasOption(const OptionName: String): Boolean;
273 begin
274 Result:=FOptionKeys.FindInSorted(OptionName) >= 0;
275 end;
276
TCommandLineParser.RemoveOptionnull277 function TCommandLineParser.RemoveOption(const OptionName: String): Boolean;
278 var
279 I: Integer;
280 begin
281 Result:=False;
282 I:=FOptionKeys.FindInSorted(OptionName);
283 if I >= 0 then begin
284 FOptionKeys.Delete(I);
285 FOptionValues.Delete(I);
286 Result:=True;
287 end;
288 end;
289
TCommandLineParser.OptionValuenull290 function TCommandLineParser.OptionValue(const OptionName: String;
291 Remove: Boolean): String;
292 var
293 I: Integer;
294 begin
295 I:=FOptionKeys.FindInSorted(OptionName);
296 if I >= 0 then begin
297 Result:=FOptionValues.Items[I];
298 FOptionKeys.Delete(I);
299 FOptionValues.Delete(I);
300 end
301 else
302 Result:='';
303 end;
304
305 end.
306