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 (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 != 0)
139 {
140 sw.WithMinus = (s[pos] == '-');
141 if (sw.WithMinus)
142 pos++;
143 }
144 break;
145
146 case NSwitchType::kChar:
147 if (rem != 0)
148 {
149 wchar_t c = s[pos];
150 if (c <= 0x7F)
151 {
152 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
153 if (sw.PostCharIndex >= 0)
154 pos++;
155 }
156 }
157 break;
158
159 case NSwitchType::kString:
160 sw.PostStrings.Add((const wchar_t *)s + pos);
161 return true;
162 }
163 if (pos != s.Len())
164 {
165 ErrorMessage = "Too long switch:";
166 return false;
167 }
168 return true;
169 }
170
ParseStrings(const CSwitchForm * switchForms,const UStringVector & commandStrings)171 bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings)
172 {
173 ErrorLine.Empty();
174 bool stopSwitch = false;
175 FOR_VECTOR (i, commandStrings)
176 {
177 const UString &s = commandStrings[i];
178 if (!stopSwitch)
179 {
180 if (s.IsEqualTo(kStopSwitchParsing))
181 {
182 stopSwitch = true;
183 continue;
184 }
185 if (!s.IsEmpty() && IsItSwitchChar(s[0]))
186 {
187 if (ParseString(s, switchForms))
188 continue;
189 ErrorLine = s;
190 return false;
191 }
192 }
193 NonSwitchStrings.Add(s);
194 }
195 return true;
196 }
197
198 }
199