]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.cpp
Add ELF Tool Chain's brandelf(1) to contrib
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmdArgValString.cpp
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 //++
11 // File:        MICmdArgValString.cpp
12 //
13 // Overview:    CMICmdArgValString implementation.
14 //
15 // Environment: Compilers:  Visual C++ 12.
16 //                          gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 //              Libraries:  See MIReadmetxt.
18 //
19 // Copyright:   None.
20 //--
21
22 // In-house headers:
23 #include "MICmdArgValString.h"
24 #include "MICmdArgContext.h"
25
26 //++ ------------------------------------------------------------------------------------
27 // Details: CMICmdArgValString constructor.
28 // Type:    Method.
29 // Args:    None.
30 // Return:  None.
31 // Throws:  None.
32 //--
33 CMICmdArgValString::CMICmdArgValString(void)
34     : m_bHandleQuotedString(false)
35     , m_bAcceptNumbers(false)
36     , m_bHandleDirPaths(false)
37     , m_bHandleAnything(false)
38 {
39 }
40
41 //++ ------------------------------------------------------------------------------------
42 // Details: CMICmdArgValString constructor.
43 // Type:    Method.
44 // Args:    vbAnything  - (R) True = Parse a string and accept anything, false = do not accept anything.
45 // Return:  None.
46 // Throws:  None.
47 //--
48 CMICmdArgValString::CMICmdArgValString(const bool vbAnything)
49     : m_bHandleQuotedString(false)
50     , m_bAcceptNumbers(false)
51     , m_bHandleDirPaths(false)
52     , m_bHandleAnything(vbAnything)
53 {
54 }
55
56 //++ ------------------------------------------------------------------------------------
57 // Details: CMICmdArgValString constructor.
58 // Type:    Method.
59 // Args:    vbHandleQuotes      - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to
60 // next delimiting space character.
61 //          vbAcceptNumbers     - (R) True = Parse a string and accept as a number if number, false = numbers not recognised
62 // as string types.
63 //          vbHandleDirPaths    - (R) True = Parse a string and accept as a file path if a path, false = file paths are not
64 // recognised as string types.
65 // Return:  None.
66 // Throws:  None.
67 //--
68 CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths)
69     : m_bHandleQuotedString(vbHandleQuotes)
70     , m_bAcceptNumbers(vbAcceptNumbers)
71     , m_bHandleDirPaths(vbHandleDirPaths)
72     , m_bHandleAnything(false)
73 {
74 }
75
76 //++ ------------------------------------------------------------------------------------
77 // Details: CMICmdArgValString constructor.
78 // Type:    Method.
79 // Args:    vrArgName       - (R) Argument's name to search by.
80 //          vbMandatory     - (R) True = Yes must be present, false = optional argument.
81 //          vbHandleByCmd   - (R) True = Command processes *this option, false = not handled.
82 //          vbHandleQuotes  - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to
83 // next delimiting space character. (Dflt = false)
84 //          vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as
85 // string types. (Dflt = false)
86 // Return:  None.
87 // Throws:  None.
88 //--
89 CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
90                                        const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */)
91     : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd)
92     , m_bHandleQuotedString(vbHandleQuotes)
93     , m_bAcceptNumbers(vbAcceptNumbers)
94     , m_bHandleDirPaths(false)
95     , m_bHandleAnything(false)
96 {
97 }
98
99 //++ ------------------------------------------------------------------------------------
100 // Details: CMICmdArgValString destructor.
101 // Type:    Overridden.
102 // Args:    None.
103 // Return:  None.
104 // Throws:  None.
105 //--
106 CMICmdArgValString::~CMICmdArgValString(void)
107 {
108 }
109
110 //++ ------------------------------------------------------------------------------------
111 // Details: Parse the command's argument options string and try to extract the value *this
112 //          argument is looking for.
113 // Type:    Overridden.
114 // Args:    vrwArgContext   - (RW) The command's argument options string.
115 // Return:  MIstatus::success - Functional succeeded.
116 //          MIstatus::failure - Functional failed.
117 // Throws:  None.
118 //--
119 bool
120 CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext)
121 {
122     if (vrwArgContext.IsEmpty())
123         return MIstatus::success;
124
125     if (m_bHandleQuotedString)
126         return (ValidateQuotedText(vrwArgContext) || ValidateQuotedTextEmbedded(vrwArgContext));
127
128     return ValidateSingleText(vrwArgContext);
129 }
130
131 //++ ------------------------------------------------------------------------------------
132 // Details: Parse the command's argument options string and try to extract only the next
133 //          word delimited by the next space.
134 // Type:    Method.
135 // Args:    vrwArgContext   - (RW) The command's argument options string.
136 // Return:  MIstatus::success - Functional succeeded.
137 //          MIstatus::failure - Functional failed.
138 // Throws:  None.
139 //--
140 bool
141 CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext)
142 {
143     if (vrwArgContext.GetNumberArgsPresent() == 1)
144     {
145         const CMIUtilString &rArg(vrwArgContext.GetArgsLeftToParse());
146         if (IsStringArg(rArg))
147         {
148             m_bFound = true;
149             m_bValid = true;
150             m_argValue = rArg;
151             vrwArgContext.RemoveArg(rArg);
152             return MIstatus::success;
153         }
154         else
155             return MIstatus::failure;
156     }
157
158     // More than one option...
159     const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs());
160     CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
161     while (it != vecOptions.end())
162     {
163         const CMIUtilString &rArg(*it);
164         if (IsStringArg(rArg))
165         {
166             m_bFound = true;
167
168             if (vrwArgContext.RemoveArg(rArg))
169             {
170                 m_bValid = true;
171                 m_argValue = rArg;
172                 return MIstatus::success;
173             }
174             else
175                 return MIstatus::failure;
176         }
177
178         // Next
179         ++it;
180     }
181
182     return MIstatus::failure;
183 }
184
185 //++ ------------------------------------------------------------------------------------
186 // Details: Parse the command's argument options string and try to extract all the words
187 //          between quotes then delimited by the next space. Can fall through to
188 //          ValidateSingleText() or ValidateQuotedQuotedTextEmbedded().
189 // Type:    Method.
190 // Args:    vrwArgContext   - (RW) The command's argument options string.
191 // Return:  MIstatus::success - Functional succeeded.
192 //          MIstatus::failure - Functional failed.
193 // Throws:  None.
194 //--
195 bool
196 CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext)
197 {
198     // CODETAG_QUOTEDTEXT_SIMILAR_CODE
199     CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
200     const MIchar cQuote = '"';
201
202     // Look for first quote of two
203     MIint nPos = strOptions.find(cQuote);
204     if (nPos == (MIint)std::string::npos)
205         return ValidateSingleText(vrwArgContext);
206
207     // Is one and only quote at end of the string
208     const MIint nLen = strOptions.length();
209     if (nPos == (MIint)(nLen - 1))
210         return MIstatus::failure;
211
212     // Quote must be the first character in the string or be preceeded by a space
213     if ((nPos > 0) && (strOptions[nPos - 1] != ' '))
214         return MIstatus::failure;
215
216     // Need to find the other quote
217     const MIint nPos2 = strOptions.rfind(cQuote);
218     if (nPos2 == (MIint)std::string::npos)
219         return MIstatus::failure;
220
221     // Is there quotes surrounding string formatting embedded quotes
222     if (IsStringArgQuotedQuotedTextEmbedded(strOptions))
223         return ValidateQuotedQuotedTextEmbedded(vrwArgContext);
224
225     // Make sure not same back quote, need two quotes
226     if (nPos == nPos2)
227         return MIstatus::failure;
228
229     // Extract quoted text
230     const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPos2 - nPos + 1).c_str();
231     if (vrwArgContext.RemoveArg(strQuotedTxt))
232     {
233         m_bFound = true;
234         m_bValid = true;
235         m_argValue = strOptions.substr(nPos + 1, nPos2 - nPos - 1).c_str();
236         return MIstatus::success;
237     }
238
239     return MIstatus::failure;
240 }
241
242 //++ ------------------------------------------------------------------------------------
243 // Details: Parse the command's argument options string and try to extract all the words
244 //          between quotes then delimited by the next space. If there any string format
245 //          characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\""
246 //          becomes "%5d". Can fall through to ValidateQuotedText().
247 // Type:    Method.
248 // Args:    vrwArgContext   - (RW) The command's argument options string.
249 // Return:  MIstatus::success - Functional succeeded.
250 //          MIstatus::failure - Functional failed.
251 // Throws:  None.
252 //--
253 bool
254 CMICmdArgValString::ValidateQuotedTextEmbedded(CMICmdArgContext &vrwArgContext)
255 {
256     // CODETAG_QUOTEDTEXT_SIMILAR_CODE
257     CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
258     const MIchar cBckSlash = '\\';
259     const MIint nPos = strOptions.find(cBckSlash);
260     if (nPos == (MIint)std::string::npos)
261         return ValidateQuotedText(vrwArgContext);
262
263     // Back slash must be the first character in the string or be preceeded by a space
264     // or '\\'
265     const MIchar cSpace = ' ';
266     if ((nPos > 0) && (strOptions[nPos - 1] != cSpace))
267         return MIstatus::failure;
268
269     // Need to find the other back slash
270     const MIint nPos2 = strOptions.rfind(cBckSlash);
271     if (nPos2 == (MIint)std::string::npos)
272         return MIstatus::failure;
273
274     // Make sure not same back slash, need two slashs
275     if (nPos == nPos2)
276         return MIstatus::failure;
277
278     // Look for the two quotes
279     const MIint nLen = strOptions.length();
280     const MIchar cQuote = '"';
281     const MIint nPosQuote1 = nPos + 1;
282     const MIint nPosQuote2 = (nPos2 < nLen) ? nPos2 + 1 : nPos2;
283     if ((nPosQuote1 != nPosQuote2) && (strOptions[nPosQuote1] != cQuote) && (strOptions[nPosQuote2] != cQuote))
284         return MIstatus::failure;
285
286     // Extract quoted text
287     const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPosQuote2 - nPos + 1).c_str();
288     if (vrwArgContext.RemoveArg(strQuotedTxt))
289     {
290         m_bFound = true;
291         m_bValid = true;
292         m_argValue = strQuotedTxt;
293         return MIstatus::success;
294     }
295
296     return MIstatus::failure;
297 }
298
299 //++ ------------------------------------------------------------------------------------
300 // Details: Parse the command's argument options string and try to extract all the words
301 //          between quotes then delimited by the next space. If there any string format
302 //          characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\""
303 //          becomes "%5d".
304 // Type:    Method.
305 // Args:    vrwArgContext   - (RW) The command's argument options string.
306 // Return:  MIstatus::success - Functional succeeded.
307 //          MIstatus::failure - Functional failed.
308 // Throws:  None.
309 //--
310 bool
311 CMICmdArgValString::ValidateQuotedQuotedTextEmbedded(CMICmdArgContext &vrwArgContext)
312 {
313     // CODETAG_QUOTEDTEXT_SIMILAR_CODE
314     CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
315     const MIint nPos = strOptions.find("\"\\\"");
316     if (nPos == (MIint)std::string::npos)
317         return MIstatus::failure;
318
319     const MIint nPos2 = strOptions.rfind("\\\"\"");
320     if (nPos2 == (MIint)std::string::npos)
321         return MIstatus::failure;
322
323     const MIint nLen = strOptions.length();
324     if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2)))
325         return MIstatus::failure;
326
327     // Quote must be the first character in the string or be preceeded by a space
328     // or '\\'
329     const MIchar cSpace = ' ';
330     if ((nPos > 0) && (strOptions[nPos - 1] != cSpace))
331         return MIstatus::failure;
332
333     // Extract quoted text
334     const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPos2 - nPos + 3).c_str();
335     if (vrwArgContext.RemoveArg(strQuotedTxt))
336     {
337         m_bFound = true;
338         m_bValid = true;
339         m_argValue = strQuotedTxt;
340         return MIstatus::success;
341     }
342
343     return MIstatus::failure;
344 }
345
346 //++ ------------------------------------------------------------------------------------
347 // Details: Examine the string and determine if it is a valid string type argument.
348 // Type:    Method.
349 // Args:    vrTxt   - (R) Some text.
350 // Return:  bool    - True = yes valid arg, false = no.
351 // Throws:  None.
352 //--
353 bool
354 CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const
355 {
356     if (m_bHandleQuotedString)
357         return (IsStringArgQuotedText(vrTxt) || IsStringArgQuotedTextEmbedded(vrTxt) || IsStringArgQuotedQuotedTextEmbedded(vrTxt) ||
358                 IsStringArgSingleText(vrTxt)); // Still test for this as could just be one word still
359
360     return IsStringArgSingleText(vrTxt);
361 }
362
363 //++ ------------------------------------------------------------------------------------
364 // Details: Examine the string and determine if it is a valid string type argument or
365 //          option value. If the string looks like a long option, short option, a thread
366 //          group ID or just a number it is rejected as a string type value. There is an
367 //          option to allow the string to accept a number as a string type.
368 // Type:    Method.
369 // Args:    vrTxt   - (R) Some text.
370 // Return:  bool    - True = yes valid argument value, false = something else.
371 // Throws:  None.
372 //--
373 bool
374 CMICmdArgValString::IsStringArgSingleText(const CMIUtilString &vrTxt) const
375 {
376     // Accept anything as string word
377     if (m_bHandleAnything)
378         return true;
379
380     if (!m_bHandleDirPaths)
381     {
382         // Look for directory file paths, if found reject
383         const bool bHavePosSlash = (vrTxt.find_first_of("/") != std::string::npos);
384         const bool bHaveBckSlash = (vrTxt.find_first_of("\\") != std::string::npos);
385         if (bHavePosSlash || bHaveBckSlash)
386             return false;
387     }
388
389     // Look for --someLongOption, if found reject
390     if (0 == vrTxt.find("--"))
391         return false;
392
393     // Look for -f type short options, if found reject
394     if ((0 == vrTxt.find("-")) && (vrTxt.length() == 2))
395         return false;
396
397     // Look for thread group i1 i2 i3...., if found reject
398     if ((vrTxt.find("i") == 0) && ::isdigit(vrTxt[1]))
399         return false;
400
401     // Look for numbers, if found reject
402     if (!m_bAcceptNumbers && vrTxt.IsNumber())
403         return false;
404
405     return true;
406 }
407
408 //++ ------------------------------------------------------------------------------------
409 // Details: Examine the string and determine if it is a valid string type argument.
410 //          Take into account quotes surrounding the text. Note this function falls
411 //          through to IsStringArgSingleText() should the criteria match fail.
412 // Type:    Method.
413 // Args:    vrTxt   - (R) Some text.
414 // Return:  bool    - True = yes valid arg, false = no.
415 // Throws:  None.
416 //--
417 bool
418 CMICmdArgValString::IsStringArgQuotedText(const CMIUtilString &vrTxt) const
419 {
420     // CODETAG_QUOTEDTEXT_SIMILAR_CODE
421     const MIchar cQuote = '"';
422     const MIint nPos = vrTxt.find(cQuote);
423     if (nPos == (MIint)std::string::npos)
424         return false;
425
426     // Is one and only quote at end of the string
427     if (nPos == (MIint)(vrTxt.length() - 1))
428         return false;
429
430     // Quote must be the first character in the string or be preceeded by a space
431     // Also check for embedded string formating quote
432     const MIchar cBckSlash = '\\';
433     const MIchar cSpace = ' ';
434     if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) && (vrTxt[nPos - 2] != cSpace))
435     {
436         return false;
437     }
438     if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace))
439         return false;
440
441     // Need to find the other quote
442     const MIint nPos2 = vrTxt.rfind(cQuote);
443     if (nPos2 == (MIint)std::string::npos)
444         return false;
445
446     // Make sure not same quote, need two quotes
447     if (nPos == nPos2)
448         return MIstatus::failure;
449
450     return true;
451 }
452
453 //++ ------------------------------------------------------------------------------------
454 // Details: Examine the string and determine if it is a valid string type argument.
455 //          Take into account quotes surrounding the text. Take into account string format
456 //          embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls
457 //          through to IsStringArgQuotedText() should the criteria match fail.
458 // Type:    Method.
459 // Args:    vrTxt   - (R) Some text.
460 // Return:  bool    - True = yes valid arg, false = no.
461 // Throws:  None.
462 //--
463 bool
464 CMICmdArgValString::IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const
465 {
466     // CODETAG_QUOTEDTEXT_SIMILAR_CODE
467     const MIchar cBckSlash = '\\';
468     const MIint nPos = vrTxt.find(cBckSlash);
469     if (nPos == (MIint)std::string::npos)
470         return false;
471
472     // Slash must be the first character in the string or be preceeded by a space
473     const MIchar cSpace = ' ';
474     if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace))
475         return false;
476
477     // Need to find the other matching slash
478     const MIint nPos2 = vrTxt.rfind(cBckSlash);
479     if (nPos2 == (MIint)std::string::npos)
480         return false;
481
482     // Make sure not same back slash, need two slashs
483     if (nPos == nPos2)
484         return MIstatus::failure;
485
486     return false;
487 }
488
489 //++ ------------------------------------------------------------------------------------
490 // Details: Examine the string and determine if it is a valid string type argument.
491 //          Take into account quotes surrounding the text. Take into account string format
492 //          embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls
493 //          through to IsStringArgQuotedTextEmbedded() should the criteria match fail.
494 // Type:    Method.
495 // Args:    vrTxt   - (R) Some text.
496 // Return:  bool    - True = yes valid arg, false = no.
497 // Throws:  None.
498 //--
499 bool
500 CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const
501 {
502     const MIint nPos = vrTxt.find("\"\\\"");
503     if (nPos == (MIint)std::string::npos)
504         return false;
505
506     const MIint nPos2 = vrTxt.rfind("\\\"\"");
507     if (nPos2 == (MIint)std::string::npos)
508         return false;
509
510     const MIint nLen = vrTxt.length();
511     if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2)))
512         return false;
513
514     return true;
515 }