• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // CommandLineParser.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "CommandLineParser.h"
6 
IsString1PrefixedByString2_NoCase(const wchar_t * u,const char * a)7 static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a)
8 {
9   for (;;)
10   {
11     char c = *a;
12     if (c == 0)
13       return true;
14     if ((unsigned char)MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))
15       return false;
16     a++;
17     u++;
18   }
19 }
20 
21 namespace NCommandLineParser {
22 
SplitCommandLine(const UString & src,UString & dest1,UString & dest2)23 bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
24 {
25   dest1.Empty();
26   dest2.Empty();
27   bool quoteMode = false;
28   unsigned i;
29   for (i = 0; i < src.Len(); i++)
30   {
31     wchar_t c = src[i];
32     if ((c == L' ' || c == L'\t') && !quoteMode)
33     {
34       dest2 = src.Ptr(i + 1);
35       return i != 0;
36     }
37     if (c == L'\"')
38       quoteMode = !quoteMode;
39     else
40       dest1 += c;
41   }
42   return i != 0;
43 }
44 
SplitCommandLine(const UString & s,UStringVector & parts)45 void SplitCommandLine(const UString &s, UStringVector &parts)
46 {
47   UString sTemp = s;
48   sTemp.Trim();
49   parts.Clear();
50   for (;;)
51   {
52     UString s1, s2;
53     if (SplitCommandLine(sTemp, s1, s2))
54       parts.Add(s1);
55     if (s2.IsEmpty())
56       break;
57     sTemp = s2;
58   }
59 }
60 
61 
62 static const char *kStopSwitchParsing = "--";
63 
IsItSwitchChar(wchar_t c)64 static bool inline IsItSwitchChar(wchar_t c)
65 {
66   return (c == '-');
67 }
68 
CParser(unsigned numSwitches)69 CParser::CParser(unsigned numSwitches):
70   _numSwitches(numSwitches),
71   _switches(0)
72 {
73   _switches = new CSwitchResult[numSwitches];
74 }
75 
~CParser()76 CParser::~CParser()
77 {
78   delete []_switches;
79 }
80 
81 
82 // if (s) contains switch then function updates switch structures
83 // out: true, if (s) is a switch
ParseString(const UString & s,const CSwitchForm * switchForms)84 bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
85 {
86   if (s.IsEmpty() || !IsItSwitchChar(s[0]))
87     return false;
88 
89   unsigned pos = 1;
90   unsigned switchIndex = 0;
91   int maxLen = -1;
92 
93   for (unsigned i = 0; i < _numSwitches; i++)
94   {
95     const char *key = switchForms[i].Key;
96     unsigned switchLen = MyStringLen(key);
97     if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
98       continue;
99     if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key))
100     {
101       switchIndex = i;
102       maxLen = switchLen;
103     }
104   }
105 
106   if (maxLen < 0)
107   {
108     ErrorMessage = "Unknown switch:";
109     return false;
110   }
111 
112   pos += maxLen;
113 
114   CSwitchResult &sw = _switches[switchIndex];
115   const CSwitchForm &form = switchForms[switchIndex];
116 
117   if (!form.Multi && sw.ThereIs)
118   {
119     ErrorMessage = "Multiple instances for switch:";
120     return false;
121   }
122 
123   sw.ThereIs = true;
124 
125   int rem = s.Len() - pos;
126   if (rem < form.MinLen)
127   {
128     ErrorMessage = "Too short switch:";
129     return false;
130   }
131 
132   sw.WithMinus = false;
133   sw.PostCharIndex = -1;
134 
135   switch (form.Type)
136   {
137     case NSwitchType::kMinus:
138       if (rem == 1)
139       {
140         sw.WithMinus = (s[pos] == '-');
141         if (sw.WithMinus)
142           return true;
143         ErrorMessage = "Incorrect switch postfix:";
144         return false;
145       }
146       break;
147 
148     case NSwitchType::kChar:
149       if (rem == 1)
150       {
151         wchar_t c = s[pos];
152         if (c <= 0x7F)
153         {
154           sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
155           if (sw.PostCharIndex >= 0)
156             return true;
157         }
158         ErrorMessage = "Incorrect switch postfix:";
159         return false;
160       }
161       break;
162 
163     case NSwitchType::kString:
164       sw.PostStrings.Add((const wchar_t *)s + pos);
165       return true;
166   }
167 
168   if (pos != s.Len())
169   {
170     ErrorMessage = "Too long switch:";
171     return false;
172   }
173   return true;
174 }
175 
ParseStrings(const CSwitchForm * switchForms,const UStringVector & commandStrings)176 bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings)
177 {
178   ErrorLine.Empty();
179   bool stopSwitch = false;
180   FOR_VECTOR (i, commandStrings)
181   {
182     const UString &s = commandStrings[i];
183     if (!stopSwitch)
184     {
185       if (s.IsEqualTo(kStopSwitchParsing))
186       {
187         stopSwitch = true;
188         continue;
189       }
190       if (!s.IsEmpty() && IsItSwitchChar(s[0]))
191       {
192         if (ParseString(s, switchForms))
193           continue;
194         ErrorLine = s;
195         return false;
196       }
197     }
198     NonSwitchStrings.Add(s);
199   }
200   return true;
201 }
202 
203 }
204