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