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