1 // CommandLineParser.cpp
2
3 #include "StdAfx.h"
4
5 #include "CommandLineParser.h"
6
7 namespace NCommandLineParser {
8
SplitCommandLine(const UString & src,UString & dest1,UString & dest2)9 void SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
10 {
11 dest1.Empty();
12 dest2.Empty();
13 bool quoteMode = false;
14 int i;
15 for (i = 0; i < src.Length(); i++)
16 {
17 wchar_t c = src[i];
18 if (c == L'\"')
19 quoteMode = !quoteMode;
20 else if (c == L' ' && !quoteMode)
21 {
22 i++;
23 break;
24 }
25 else
26 dest1 += c;
27 }
28 dest2 = src.Mid(i);
29 }
30
SplitCommandLine(const UString & s,UStringVector & parts)31 void SplitCommandLine(const UString &s, UStringVector &parts)
32 {
33 UString sTemp = s;
34 sTemp.Trim();
35 parts.Clear();
36 while (true)
37 {
38 UString s1, s2;
39 SplitCommandLine(sTemp, s1, s2);
40 // s1.Trim();
41 // s2.Trim();
42 if (!s1.IsEmpty())
43 parts.Add(s1);
44 if (s2.IsEmpty())
45 return;
46 sTemp = s2;
47 }
48 }
49
50
51 static const wchar_t kSwitchID1 = '-';
52 // static const wchar_t kSwitchID2 = '/';
53
54 static const wchar_t kSwitchMinus = '-';
55 static const wchar_t *kStopSwitchParsing = L"--";
56
IsItSwitchChar(wchar_t c)57 static bool IsItSwitchChar(wchar_t c)
58 {
59 return (c == kSwitchID1 /*|| c == kSwitchID2 */);
60 }
61
CParser(int numSwitches)62 CParser::CParser(int numSwitches):
63 _numSwitches(numSwitches)
64 {
65 _switches = new CSwitchResult[_numSwitches];
66 }
67
~CParser()68 CParser::~CParser()
69 {
70 delete []_switches;
71 }
72
ParseStrings(const CSwitchForm * switchForms,const UStringVector & commandStrings)73 void CParser::ParseStrings(const CSwitchForm *switchForms,
74 const UStringVector &commandStrings)
75 {
76 int numCommandStrings = commandStrings.Size();
77 bool stopSwitch = false;
78 for (int i = 0; i < numCommandStrings; i++)
79 {
80 const UString &s = commandStrings[i];
81 if (stopSwitch)
82 NonSwitchStrings.Add(s);
83 else
84 if (s == kStopSwitchParsing)
85 stopSwitch = true;
86 else
87 if (!ParseString(s, switchForms))
88 NonSwitchStrings.Add(s);
89 }
90 }
91
92 // if string contains switch then function updates switch structures
93 // out: (string is a switch)
ParseString(const UString & s,const CSwitchForm * switchForms)94 bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
95 {
96 int len = s.Length();
97 if (len == 0)
98 return false;
99 int pos = 0;
100 if (!IsItSwitchChar(s[pos]))
101 return false;
102 while(pos < len)
103 {
104 if (IsItSwitchChar(s[pos]))
105 pos++;
106 const int kNoLen = -1;
107 int matchedSwitchIndex = 0; // GCC Warning
108 int maxLen = kNoLen;
109 for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)
110 {
111 int switchLen = MyStringLen(switchForms[switchIndex].IDString);
112 if (switchLen <= maxLen || pos + switchLen > len)
113 continue;
114
115 UString temp = s + pos;
116 temp = temp.Left(switchLen);
117 if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)
118 // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)
119 {
120 matchedSwitchIndex = switchIndex;
121 maxLen = switchLen;
122 }
123 }
124 if (maxLen == kNoLen)
125 throw "maxLen == kNoLen";
126 CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];
127 const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];
128 if ((!switchForm.Multi) && matchedSwitch.ThereIs)
129 throw "switch must be single";
130 matchedSwitch.ThereIs = true;
131 pos += maxLen;
132 int tailSize = len - pos;
133 NSwitchType::EEnum type = switchForm.Type;
134 switch(type)
135 {
136 case NSwitchType::kPostMinus:
137 {
138 if (tailSize == 0)
139 matchedSwitch.WithMinus = false;
140 else
141 {
142 matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);
143 if (matchedSwitch.WithMinus)
144 pos++;
145 }
146 break;
147 }
148 case NSwitchType::kPostChar:
149 {
150 if (tailSize < switchForm.MinLen)
151 throw "switch is not full";
152 UString set = switchForm.PostCharSet;
153 const int kEmptyCharValue = -1;
154 if (tailSize == 0)
155 matchedSwitch.PostCharIndex = kEmptyCharValue;
156 else
157 {
158 int index = set.Find(s[pos]);
159 if (index < 0)
160 matchedSwitch.PostCharIndex = kEmptyCharValue;
161 else
162 {
163 matchedSwitch.PostCharIndex = index;
164 pos++;
165 }
166 }
167 break;
168 }
169 case NSwitchType::kLimitedPostString:
170 case NSwitchType::kUnLimitedPostString:
171 {
172 int minLen = switchForm.MinLen;
173 if (tailSize < minLen)
174 throw "switch is not full";
175 if (type == NSwitchType::kUnLimitedPostString)
176 {
177 matchedSwitch.PostStrings.Add(s.Mid(pos));
178 return true;
179 }
180 int maxLen = switchForm.MaxLen;
181 UString stringSwitch = s.Mid(pos, minLen);
182 pos += minLen;
183 for(int i = minLen; i < maxLen && pos < len; i++, pos++)
184 {
185 wchar_t c = s[pos];
186 if (IsItSwitchChar(c))
187 break;
188 stringSwitch += c;
189 }
190 matchedSwitch.PostStrings.Add(stringSwitch);
191 break;
192 }
193 case NSwitchType::kSimple:
194 break;
195 }
196 }
197 return true;
198 }
199
operator [](size_t index) const200 const CSwitchResult& CParser::operator[](size_t index) const
201 {
202 return _switches[index];
203 }
204
205 /////////////////////////////////
206 // Command parsing procedures
207
ParseCommand(int numCommandForms,const CCommandForm * commandForms,const UString & commandString,UString & postString)208 int ParseCommand(int numCommandForms, const CCommandForm *commandForms,
209 const UString &commandString, UString &postString)
210 {
211 for(int i = 0; i < numCommandForms; i++)
212 {
213 const UString id = commandForms[i].IDString;
214 if (commandForms[i].PostStringMode)
215 {
216 if(commandString.Find(id) == 0)
217 {
218 postString = commandString.Mid(id.Length());
219 return i;
220 }
221 }
222 else
223 if (commandString == id)
224 {
225 postString.Empty();
226 return i;
227 }
228 }
229 return -1;
230 }
231
ParseSubCharsCommand(int numForms,const CCommandSubCharsSet * forms,const UString & commandString,CIntVector & indices)232 bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms,
233 const UString &commandString, CIntVector &indices)
234 {
235 indices.Clear();
236 int numUsedChars = 0;
237 for(int i = 0; i < numForms; i++)
238 {
239 const CCommandSubCharsSet &set = forms[i];
240 int currentIndex = -1;
241 int len = MyStringLen(set.Chars);
242 for(int j = 0; j < len; j++)
243 {
244 wchar_t c = set.Chars[j];
245 int newIndex = commandString.Find(c);
246 if (newIndex >= 0)
247 {
248 if (currentIndex >= 0)
249 return false;
250 if (commandString.Find(c, newIndex + 1) >= 0)
251 return false;
252 currentIndex = j;
253 numUsedChars++;
254 }
255 }
256 if(currentIndex == -1 && !set.EmptyAllowed)
257 return false;
258 indices.Add(currentIndex);
259 }
260 return (numUsedChars == commandString.Length());
261 }
262
263 }
264