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