1 //===-- MICmdArgValString.cpp -----------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // In-house headers:
11 #include "MICmdArgValString.h"
12 #include "MICmdArgContext.h"
13
14 //++
15 //------------------------------------------------------------------------------------
16 // Details: CMICmdArgValString constructor.
17 // Type: Method.
18 // Args: None.
19 // Return: None.
20 // Throws: None.
21 //--
CMICmdArgValString()22 CMICmdArgValString::CMICmdArgValString()
23 : m_bHandleQuotedString(false), m_bAcceptNumbers(false),
24 m_bHandleDirPaths(false), m_bHandleAnything(false) {}
25
26 //++
27 //------------------------------------------------------------------------------------
28 // Details: CMICmdArgValString constructor.
29 // Type: Method.
30 // Args: vbAnything - (R) True = Parse a string and accept anything, false =
31 // do not accept anything.
32 // Return: None.
33 // Throws: None.
34 //--
CMICmdArgValString(const bool vbAnything)35 CMICmdArgValString::CMICmdArgValString(const bool vbAnything)
36 : m_bHandleQuotedString(vbAnything), m_bAcceptNumbers(false),
37 m_bHandleDirPaths(false), m_bHandleAnything(vbAnything) {}
38
39 //++
40 //------------------------------------------------------------------------------------
41 // Details: CMICmdArgValString constructor.
42 // Type: Method.
43 // Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes
44 // spaces are not delimiters, false = only text up to
45 // next delimiting space character.
46 // vbAcceptNumbers - (R) True = Parse a string and accept as a
47 // number if number, false = numbers not recognised
48 // as string types.
49 // vbHandleDirPaths - (R) True = Parse a string and accept as a file
50 // path if a path, false = file paths are not
51 // recognised as string types.
52 // Return: None.
53 // Throws: None.
54 //--
CMICmdArgValString(const bool vbHandleQuotes,const bool vbAcceptNumbers,const bool vbHandleDirPaths)55 CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes,
56 const bool vbAcceptNumbers,
57 const bool vbHandleDirPaths)
58 : m_bHandleQuotedString(vbHandleQuotes), m_bAcceptNumbers(vbAcceptNumbers),
59 m_bHandleDirPaths(vbHandleDirPaths), m_bHandleAnything(false) {}
60
61 //++
62 //------------------------------------------------------------------------------------
63 // Details: CMICmdArgValString constructor.
64 // Type: Method.
65 // Args: vrArgName - (R) Argument's name to search by.
66 // vbMandatory - (R) True = Yes must be present, false = optional
67 // argument.
68 // vbHandleByCmd - (R) True = Command processes *this option, false =
69 // not handled.
70 // vbHandleQuotes - (R) True = Parse a string surrounded by quotes
71 // spaces are not delimiters, false = only text up to
72 // next delimiting space character. (Dflt = false)
73 // vbAcceptNumbers - (R) True = Parse a string and accept as a number
74 // if number, false = numbers not recognised as
75 // string types. (Dflt = false)
76 // Return: None.
77 // Throws: None.
78 //--
CMICmdArgValString(const CMIUtilString & vrArgName,const bool vbMandatory,const bool vbHandleByCmd,const bool vbHandleQuotes,const bool vbAcceptNumbers)79 CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName,
80 const bool vbMandatory,
81 const bool vbHandleByCmd,
82 const bool vbHandleQuotes /* = false */,
83 const bool vbAcceptNumbers /* = false */)
84 : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd),
85 m_bHandleQuotedString(vbHandleQuotes), m_bAcceptNumbers(vbAcceptNumbers),
86 m_bHandleDirPaths(false), m_bHandleAnything(false) {}
87
88 //++
89 //------------------------------------------------------------------------------------
90 // Details: CMICmdArgValString constructor.
91 // Type: Method.
92 // Args: vrArgName - (R) Argument's name to search by.
93 // vbMandatory - (R) True = Yes must be present, false = optional
94 // argument.
95 // vbHandleByCmd - (R) True = Command processes *this option, false =
96 // not handled.
97 // vbHandleQuotes - (R) True = Parse a string surrounded by quotes
98 // spaces are not delimiters, false = only text up to
99 // next delimiting space character.
100 // vbAcceptNumbers - (R) True = Parse a string and accept as a number
101 // if number, false = numbers not recognised as
102 // vbHandleDirPaths - (R) True = Parse a string and accept as a file
103 // path if a path, false = file paths are not
104 // string types.
105 // Return: None.
106 // Throws: None.
107 //--
CMICmdArgValString(const CMIUtilString & vrArgName,const bool vbMandatory,const bool vbHandleByCmd,const bool vbHandleQuotes,const bool vbAcceptNumbers,const bool vbHandleDirPaths)108 CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName,
109 const bool vbMandatory,
110 const bool vbHandleByCmd,
111 const bool vbHandleQuotes,
112 const bool vbAcceptNumbers,
113 const bool vbHandleDirPaths)
114 : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd),
115 m_bHandleQuotedString(vbHandleQuotes), m_bAcceptNumbers(vbAcceptNumbers),
116 m_bHandleDirPaths(vbHandleDirPaths), m_bHandleAnything(false) {}
117
118 //++
119 //------------------------------------------------------------------------------------
120 // Details: CMICmdArgValString destructor.
121 // Type: Overridden.
122 // Args: None.
123 // Return: None.
124 // Throws: None.
125 //--
~CMICmdArgValString()126 CMICmdArgValString::~CMICmdArgValString() {}
127
128 //++
129 //------------------------------------------------------------------------------------
130 // Details: Parse the command's argument options string and try to extract the
131 // value *this
132 // argument is looking for.
133 // Type: Overridden.
134 // Args: vrwArgContext - (RW) The command's argument options string.
135 // Return: MIstatus::success - Functional succeeded.
136 // MIstatus::failure - Functional failed.
137 // Throws: None.
138 //--
Validate(CMICmdArgContext & vrwArgContext)139 bool CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext) {
140 if (vrwArgContext.IsEmpty())
141 return m_bMandatory ? MIstatus::failure : MIstatus::success;
142
143 if (m_bHandleQuotedString)
144 return ValidateQuotedText(vrwArgContext);
145
146 return ValidateSingleText(vrwArgContext);
147 }
148
149 //++
150 //------------------------------------------------------------------------------------
151 // Details: Parse the command's argument options string and try to extract only
152 // the next
153 // word delimited by the next space.
154 // Type: Method.
155 // Args: vrwArgContext - (RW) The command's argument options string.
156 // Return: MIstatus::success - Functional succeeded.
157 // MIstatus::failure - Functional failed.
158 // Throws: None.
159 //--
ValidateSingleText(CMICmdArgContext & vrwArgContext)160 bool CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext) {
161 const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs());
162 CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
163 while (it != vecOptions.end()) {
164 const CMIUtilString &rArg(*it);
165 if (IsStringArg(rArg)) {
166 m_bFound = true;
167
168 if (vrwArgContext.RemoveArg(rArg)) {
169 m_bValid = true;
170 m_argValue = rArg.StripSlashes();
171 return MIstatus::success;
172 } else
173 return MIstatus::failure;
174 }
175
176 // Next
177 ++it;
178 }
179
180 return MIstatus::failure;
181 }
182
183 //++
184 //------------------------------------------------------------------------------------
185 // Details: Parse the command's argument options string and try to extract all
186 // the words
187 // between quotes then delimited by the next space.
188 // Type: Method.
189 // Args: vrwArgContext - (RW) The command's argument options string.
190 // Return: MIstatus::success - Functional succeeded.
191 // MIstatus::failure - Functional failed.
192 // Throws: None.
193 //--
ValidateQuotedText(CMICmdArgContext & vrwArgContext)194 bool CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext) {
195 const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs());
196 if (vecOptions.size() == 0)
197 return MIstatus::failure;
198
199 const CMIUtilString &rArg(vecOptions[0]);
200 if (!IsStringArg(rArg))
201 return MIstatus::failure;
202
203 m_bFound = true;
204
205 if (vrwArgContext.RemoveArg(rArg)) {
206 m_bValid = true;
207 const char cQuote = '"';
208 m_argValue = rArg.Trim(cQuote).StripSlashes();
209 return MIstatus::success;
210 }
211
212 return MIstatus::failure;
213 }
214
215 //++
216 //------------------------------------------------------------------------------------
217 // Details: Examine the string and determine if it is a valid string type
218 // argument.
219 // Type: Method.
220 // Args: vrTxt - (R) Some text.
221 // Return: bool - True = yes valid arg, false = no.
222 // Throws: None.
223 //--
IsStringArg(const CMIUtilString & vrTxt) const224 bool CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const {
225 if (m_bHandleQuotedString)
226 return (IsStringArgQuotedText(vrTxt) ||
227 IsStringArgQuotedTextEmbedded(vrTxt) ||
228 IsStringArgQuotedQuotedTextEmbedded(vrTxt) ||
229 IsStringArgSingleText(
230 vrTxt)); // Still test for this as could just be one word still
231
232 return IsStringArgSingleText(vrTxt);
233 }
234
235 //++
236 //------------------------------------------------------------------------------------
237 // Details: Examine the string and determine if it is a valid string type
238 // argument or
239 // option value. If the string looks like a long option, short option,
240 // a thread
241 // group ID or just a number it is rejected as a string type value.
242 // There is an
243 // option to allow the string to accept a number as a string type.
244 // Type: Method.
245 // Args: vrTxt - (R) Some text.
246 // Return: bool - True = yes valid argument value, false = something else.
247 // Throws: None.
248 //--
IsStringArgSingleText(const CMIUtilString & vrTxt) const249 bool CMICmdArgValString::IsStringArgSingleText(
250 const CMIUtilString &vrTxt) const {
251 if (!m_bHandleDirPaths) {
252 // Look for directory file paths, if found reject
253 const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos);
254 const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos);
255 if (bHavePosSlash || bHaveBckSlash)
256 return false;
257 }
258
259 // Look for --someLongOption, if found reject
260 if (0 == vrTxt.find("--"))
261 return false;
262
263 // Look for -f type short options, if found reject
264 if ((0 == vrTxt.find('-')) && (vrTxt.length() == 2))
265 return false;
266
267 // Look for thread group i1 i2 i3...., if found reject
268 if ((vrTxt.find('i') == 0) && ::isdigit(vrTxt[1]))
269 return false;
270
271 // Look for numbers, if found reject
272 if (!m_bAcceptNumbers && vrTxt.IsNumber())
273 return false;
274
275 return true;
276 }
277
278 //++
279 //------------------------------------------------------------------------------------
280 // Details: Examine the string and determine if it is a valid string type
281 // argument.
282 // Take into account quotes surrounding the text. Note this function
283 // falls
284 // through to IsStringArgSingleText() should the criteria match fail.
285 // Type: Method.
286 // Args: vrTxt - (R) Some text.
287 // Return: bool - True = yes valid arg, false = no.
288 // Throws: None.
289 //--
IsStringArgQuotedText(const CMIUtilString & vrTxt) const290 bool CMICmdArgValString::IsStringArgQuotedText(
291 const CMIUtilString &vrTxt) const {
292 // Accept anything as string word
293 if (m_bHandleAnything)
294 return true;
295
296 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
297 const char cQuote = '"';
298 const size_t nPos = vrTxt.find(cQuote);
299 if (nPos == std::string::npos)
300 return false;
301
302 // Is one and only quote at end of the string
303 if (nPos == (vrTxt.length() - 1))
304 return false;
305
306 // Quote must be the first character in the string or be preceded by a space
307 // Also check for embedded string formating quote
308 const char cBckSlash = '\\';
309 const char cSpace = ' ';
310 if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) &&
311 (vrTxt[nPos - 2] != cSpace)) {
312 return false;
313 }
314 if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace))
315 return false;
316
317 // Need to find the other quote
318 const size_t nPos2 = vrTxt.rfind(cQuote);
319 if (nPos2 == std::string::npos)
320 return false;
321
322 // Make sure not same quote, need two quotes
323 if (nPos == nPos2)
324 return MIstatus::failure;
325
326 return true;
327 }
328
329 //++
330 //------------------------------------------------------------------------------------
331 // Details: Examine the string and determine if it is a valid string type
332 // argument.
333 // Take into account quotes surrounding the text. Take into account
334 // string format
335 // embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this
336 // function falls
337 // through to IsStringArgQuotedText() should the criteria match fail.
338 // Type: Method.
339 // Args: vrTxt - (R) Some text.
340 // Return: bool - True = yes valid arg, false = no.
341 // Throws: None.
342 //--
IsStringArgQuotedTextEmbedded(const CMIUtilString & vrTxt) const343 bool CMICmdArgValString::IsStringArgQuotedTextEmbedded(
344 const CMIUtilString &vrTxt) const {
345 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
346 const char cBckSlash = '\\';
347 const size_t nPos = vrTxt.find(cBckSlash);
348 if (nPos == std::string::npos)
349 return false;
350
351 // Slash must be the first character in the string or be preceded by a space
352 const char cSpace = ' ';
353 if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace))
354 return false;
355
356 // Need to find the other matching slash
357 const size_t nPos2 = vrTxt.rfind(cBckSlash);
358 if (nPos2 == std::string::npos)
359 return false;
360
361 // Make sure not same back slash, need two slashes
362 if (nPos == nPos2)
363 return MIstatus::failure;
364
365 return false;
366 }
367
368 //++
369 //------------------------------------------------------------------------------------
370 // Details: Examine the string and determine if it is a valid string type
371 // argument.
372 // Take into account quotes surrounding the text. Take into account
373 // string format
374 // embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this
375 // function falls
376 // through to IsStringArgQuotedTextEmbedded() should the criteria match
377 // fail.
378 // Type: Method.
379 // Args: vrTxt - (R) Some text.
380 // Return: bool - True = yes valid arg, false = no.
381 // Throws: None.
382 //--
IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString & vrTxt) const383 bool CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(
384 const CMIUtilString &vrTxt) const {
385 const size_t nPos = vrTxt.find("\"\\\"");
386 if (nPos == std::string::npos)
387 return false;
388
389 const size_t nPos2 = vrTxt.rfind("\\\"\"");
390 if (nPos2 == std::string::npos)
391 return false;
392
393 const size_t nLen = vrTxt.length();
394 return !((nLen > 5) && ((nPos + 2) == (nPos2 - 2)));
395 }
396