Code::Blocks  SVN r11506
parsewatchvalue.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11491 $
6  * $Id: parsewatchvalue.cpp 11491 2018-10-03 14:40:38Z mortenmacfly $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/debuggergdb/parsewatchvalue.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #ifndef CB_PRECOMP
13 # include <wx/regex.h>
14 #endif
15 
16 #include "parsewatchvalue.h"
17 
18 struct Token
19 {
20  enum Type
21  {
28  };
29 
30  Token() :
31  start(0),
32  end(0),
33  type(Undefined),
34  hasRepeatedChar(false)
35  {
36  }
37  Token(int start_, int end_, Type type_) :
38  start(start_),
39  end(end_),
40  type(type_),
41  hasRepeatedChar(false)
42  {
43  }
44 
45  bool operator == (Token const &t) const
46  {
47  return start == t.start && end == t.end && type == t.type;
48  }
50  {
51  assert(end <= static_cast<int>(s.length()));
52  return s.substr(start, end - start);
53  }
54 
55  void Trim(wxString const &s)
56  {
57  while (start < static_cast<int>(s.length())
58  && (s[start] == wxT(' ') || s[start] == wxT('\t') || s[start] == wxT('\n')))
59  start++;
60  while (end > 0
61  && (s[end - 1] == wxT(' ') || s[end - 1] == wxT('\t') || s[end - 1] == wxT('\n')))
62  end--;
63  }
64 
65  int start, end;
68 };
69 
70 wxRegEx regexRepeatedChars(wxT("^((\\\\'.{1,6}\\\\')|('.{1,6}'))[ \\t](<repeats[ \\t][0-9]+[ \\t]times>)"),
71 #ifndef __WXMAC__
72  wxRE_ADVANCED);
73 #else
75 #endif
76 
80 inline int SkipShortenedString(wxString const &str, int pos)
81 {
82  while (pos < static_cast<int>(str.length()) && str[pos]==wxT('.'))
83  ++pos;
84  return pos;
85 }
86 
87 inline int DetectRepeatingSymbols(wxString const &str, int pos)
88 {
89  int newPos = -1, currPos = pos;
90  while (1)
91  {
92  if (currPos + 4 >= static_cast<int>(str.length()))
93  break;
94  if (str[currPos + 1] != wxT(','))
95  break;
96  if (str[currPos + 3] == wxT('\''))
97  {
98  const wxString &s = str.substr(currPos + 3, str.length() - (currPos + 3));
100  {
101  size_t start, length;
102  regexRepeatedChars.GetMatch(&start, &length, 0);
103  newPos = currPos + 3 + length;
104  if ((newPos + 4 < static_cast<int>(str.length()))
105  && str[newPos] == wxT(',') && str[newPos + 2] == wxT('"'))
106  {
107  newPos += 3;
108  while (newPos < static_cast<int>(str.length()) && str[newPos] != wxT('"'))
109  ++newPos;
110  if (newPos + 1 < static_cast<int>(str.length()) && str[newPos] == wxT('"'))
111  ++newPos;
112  }
113  currPos = newPos;
114  }
115  else
116  break;
117  }
118  else
119  break;
120 
121  // move the current position to point at the '"' character
122  currPos--;
123  }
124  return newPos;
125 }
126 
127 inline bool GetNextToken(wxString const &str, int pos, Token &token)
128 {
129  token.hasRepeatedChar = false;
130  while (pos < static_cast<int>(str.length())
131  && (str[pos] == _T(' ') || str[pos] == _T('\t') || str[pos] == _T('\n')))
132  ++pos;
133 
134  if (pos >= static_cast<int>(str.length()))
135  return false;
136 
137  token.start = -1;
138  bool in_quote = false, in_char = false;
139  int open_braces = 0;
140  struct BraceType { enum Enum { None, Angle, Square, Normal }; };
141  BraceType::Enum brace_type = BraceType::None;
142 
143  switch (static_cast<wxChar>(str[pos]))
144  {
145  case _T('='):
146  token = Token(pos, pos + 1, Token::Equal);
147  return true;
148  case _T(','):
149  token = Token(pos, pos + 1, Token::Comma);
150  return true;
151  case _T('{'):
152  token = Token(pos, pos + 1, Token::OpenBrace);
153  return true;
154  case _T('}'):
155  token = Token(pos, pos + 1, Token::CloseBrace);
156  return true;
157 
158  case _T('"'):
159  in_quote = true;
160  token.type = Token::String;
161  token.start = pos;
162  break;
163  case _T('\''):
164  in_char = true;
165  token.type = Token::String;
166  token.start = pos;
167  break;
168  case _T('<'):
169  token.type = Token::String;
170  token.start = pos;
171  open_braces = 1;
172  brace_type = BraceType::Angle;
173  break;
174  case wxT('['):
175  token.type = Token::String;
176  token.start = pos;
177  open_braces = 1;
178  brace_type = BraceType::Square;
179  break;
180  case wxT('('):
181  token.type = Token::String;
182  open_braces = 1;
183  brace_type = BraceType::Normal;
184  token.start = pos;
185  break;
186  default:
187  token.type = Token::String;
188  token.start = pos;
189  }
190  ++pos;
191 
192  bool escape_next = false;
193  while (pos < static_cast<int>(str.length()))
194  {
195  if (open_braces == 0)
196  {
197  if (str[pos] == _T(',') && !in_quote)
198  {
199  token.end = pos;
200  return true;
201  }
202  else if ((str[pos] == _T('=') || str[pos] == _T('{') || str[pos] == _T('}')) && !in_quote && !in_char)
203  {
204  token.end = pos;
205  return true;
206  }
207  else if (str[pos] == _T('"'))
208  {
209  if (in_quote)
210  {
211  if (!escape_next)
212  {
213  int newPos = DetectRepeatingSymbols(str, pos);
214  if (newPos != -1)
215  {
216  token.hasRepeatedChar = true;
217  token.end = SkipShortenedString(str, newPos);
218  return true;
219  }
220  else
221  {
222  token.end = SkipShortenedString(str, pos + 1);
223  return true;
224  }
225  }
226  else
227  escape_next = false;
228  }
229  else
230  {
231  if (escape_next)
232  return false;
233  in_quote = true;
234  }
235  }
236  else if (str[pos] == _T('\''))
237  {
238  if (!escape_next)
239  in_char = !in_char;
240  escape_next = false;
241  }
242  else if (str[pos] == _T('\\'))
243  escape_next = true;
244  else
245  escape_next = false;
246 
247  switch (brace_type)
248  {
249  case BraceType::Angle:
250  if (str[pos] == wxT('<'))
251  open_braces++;
252  break;
253  case BraceType::Square:
254  if (str[pos] == wxT('['))
255  open_braces++;
256  break;
257  case BraceType::None:
258  default:
259  break;
260  }
261  }
262  else
263  {
264  switch (brace_type)
265  {
266  case BraceType::Angle:
267  if (str[pos] == wxT('<'))
268  open_braces++;
269  else if (str[pos] == wxT('>'))
270  --open_braces;
271  break;
272  case BraceType::Square:
273  if (str[pos] == wxT('['))
274  open_braces++;
275  else if (str[pos] == wxT(']'))
276  --open_braces;
277  break;
278  case BraceType::Normal:
279  if (str[pos] == wxT('('))
280  open_braces++;
281  else if (str[pos] == wxT(')'))
282  --open_braces;
283  break;
284  case BraceType::None:
285  default:
286  break;
287  }
288  }
289  ++pos;
290  }
291 
292  if (in_quote)
293  {
294  token.end = -1;
295  return false;
296  }
297  else
298  {
299  token.end = pos;
300  return true;
301  }
302 }
303 
304 inline cb::shared_ptr<GDBWatch> AddChild(cb::shared_ptr<GDBWatch> parent, wxString const &full_value, Token &name)
305 {
306  wxString const &str_name = name.ExtractString(full_value);
307  cb::shared_ptr<cbWatch> old_child = parent->FindChild(str_name);
308  cb::shared_ptr<GDBWatch> child;
309  if (old_child)
310  child = cb::static_pointer_cast<GDBWatch>(old_child);
311  else
312  {
313  child = cb::shared_ptr<GDBWatch>(new GDBWatch(str_name));
314  cbWatch::AddChild(parent, child);
315  }
316  child->MarkAsRemoved(false);
317  return child;
318 }
319 
320 inline cb::shared_ptr<GDBWatch> AddChild(cb::shared_ptr<GDBWatch> parent, wxString const &str_name)
321 {
322  int index = parent->FindChildIndex(str_name);
323  cb::shared_ptr<GDBWatch> child;
324  if (index != -1)
325  child = cb::static_pointer_cast<GDBWatch>(parent->GetChild(index));
326  else
327  {
328  child = cb::shared_ptr<GDBWatch>(new GDBWatch(str_name));
329  cbWatch::AddChild(parent, child);
330  }
331  child->MarkAsRemoved(false);
332  return child;
333 }
334 
335 wxRegEx regexRepeatedChar(wxT(".+[ \\t](<repeats[ \\t][0-9]+[ \\t]times>)$"));
336 wxRegEx regexFortranArray(wxT("^\\([0-9,]+)$"));
337 
338 inline bool ParseGDBWatchValue(cb::shared_ptr<GDBWatch> watch, wxString const &value, int &start, int length)
339 {
340  watch->SetDebugValue(value);
341  watch->MarkChildsAsRemoved();
342 
343  wxString watchSymbol;
344  watch->GetSymbol(watchSymbol);
345  bool isFortranArray = false;
347  isFortranArray = regexFortranArray.Matches(watchSymbol);
348  wxString watchSymbolNew;
349  bool hasNewWatchSymbol = false;
350 
351  int position = start;
352  Token token, token_name, token_value;
353  wxString pythonToStringValue;
354  bool skip_comma = false;
355  bool last_was_closing_brace = false;
356  int added_children = 0;
357  int token_real_end = 0;
358  while (GetNextToken(value, position, token))
359  {
360  token_real_end = token.end;
361  token.Trim(value);
362  const wxString &str = token.ExtractString(value);
363  if (str.StartsWith(wxT("members of ")))
364  {
365  wxString::size_type pos = str.find(wxT('\n'));
366  if (pos == wxString::npos)
367  {
368  // If the token has no '\n' character, then we have to search the whole value
369  // for the token and then we skip this token completely.
370  wxString::size_type pos_val = value.find(wxT('\n'), token_real_end);
371  if (pos_val == wxString::npos)
372  return false;
373  position = pos_val+1;
374  if (length > 0 && position >= start + length)
375  break;
376  continue;
377  }
378  else
379  {
380  // If we have the '\n' in the token, then we have the next valid token, too,
381  // so we correct the current token to be the correct one.
382  if (str.find_last_of(wxT(':'), pos) == wxString::npos)
383  return false;
384  token.start += pos + 2;
385  token.Trim(value);
386  }
387  }
388 
389  if (!token.hasRepeatedChar && regexRepeatedChar.Matches(str) && g_DebugLanguage != dl_Fortran)
390  {
391  Token expanded_token = token;
392  while (1)
393  {
394  if (value[expanded_token.end] == wxT(','))
395  {
396  position = token.end + 1;
397  token_real_end = position;
398  int comma_end = expanded_token.end;
399  if (GetNextToken(value, position, expanded_token))
400  {
401  const wxString &expanded_str = expanded_token.ExtractString(value);
402  if (!expanded_str.empty() && (expanded_str[0] != wxT('"') && expanded_str[0] != wxT('\'')))
403  {
404  token.end = comma_end;
405  position = comma_end;
406  token_real_end = comma_end;
407  break;
408  }
409  token.end = expanded_token.end;
410  if (regexRepeatedChar.Matches(expanded_str))
411  continue;
412  token_real_end = expanded_token.end;
413  }
414  }
415  else if (expanded_token.end == static_cast<int>(value.length()) || value[expanded_token.end] == wxT('}'))
416  {
417  token.end = expanded_token.end;
418  token_real_end = expanded_token.end;
419  }
420  break;
421  }
422  }
423 
424  switch (token.type)
425  {
426  case Token::String:
427  if (token_name.type == Token::Undefined)
428  token_name = token;
429  else if (token_value.type == Token::Undefined)
430  {
431  if ( wxIsdigit(str[0])
432  || str[0]==wxT('\'')
433  || str[0]==wxT('"')
434  || str[0]==wxT('<')
435  || str[0]==wxT('-')
436  || str.StartsWith(wxT("L\""))
437  || str.StartsWith(wxT("L'")) )
438  {
439  token_value = token;
440  }
441  else
442  {
443  // Detect strings generated by python pretty printing to_string() method.
444  Token expanded_token = token;
445  int firstCloseBrace = -1;
446  for (; expanded_token.end < static_cast<int>(value.length()); ++expanded_token.end)
447  {
448  if (value[expanded_token.end] == wxT('='))
449  {
450  bool foundBrace = false;
451  for (int ii = expanded_token.end + 1; ii < static_cast<int>(value.length()); ++ii)
452  {
453  if (value[ii] == wxT('{'))
454  {
455  foundBrace = true;
456  break;
457  }
458  else if (value[ii] != wxT(' ') && value[ii] != wxT('\t')
459  && value[ii] != wxT('\n') && value[ii] != wxT(' '))
460  {
461  break;
462  }
463 
464  }
465  if (foundBrace)
466  {
467  token.end = token_real_end = expanded_token.end;
468  token_value = token;
469  token_value.end--;
470  pythonToStringValue = token_value.ExtractString(value);
471  }
472  else
473  {
474  while (expanded_token.end >= 0)
475  {
476  if (value[expanded_token.end] == wxT(','))
477  {
478  token.end = token_real_end = expanded_token.end;
479  token_value = token;
480  pythonToStringValue = token_value.ExtractString(value);
481  break;
482  }
483  expanded_token.end--;
484  }
485  }
486  break;
487  }
488  else if (firstCloseBrace == -1 && value[expanded_token.end] == wxT('}'))
489  {
490  firstCloseBrace=expanded_token.end;
491  break;
492  }
493  }
494 
495  if (pythonToStringValue.empty())
496  {
497  if (firstCloseBrace == -1)
498  return false;
499  token.end = token_real_end = firstCloseBrace;
500  token_value = token;
501  pythonToStringValue = token_value.ExtractString(value);
502  if (pythonToStringValue.empty())
503  return false;
504  }
505  }
506  }
507  else
508  return false;
509  last_was_closing_brace = false;
510  break;
511  case Token::Equal:
512  last_was_closing_brace = false;
513  break;
514  case Token::Comma:
515  pythonToStringValue = wxEmptyString;
516  last_was_closing_brace = false;
517  if (skip_comma)
518  skip_comma = false;
519  else
520  {
521  if (token_name.type != Token::Undefined)
522  {
523  if (token_value.type != Token::Undefined)
524  {
525  cb::shared_ptr<GDBWatch> child = AddChild(watch, value, token_name);
526  child->SetValue(token_value.ExtractString(value));
527  }
528  else
529  {
530  cb::shared_ptr<GDBWatch> child;
531  if (g_DebugLanguage == dl_Cpp)
532  {
533  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0;
534  child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children));
535  }
536  else // g_DebugLanguage == dl_Fortran
537  {
538  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 1;
539  wxString childSymbol;
540  if (isFortranArray)
541  {
542  childSymbol = wxString::Format(wxT("(%d,"), start_arr + added_children);
543  childSymbol << watchSymbol.Mid(1);
544  }
545  else
546  {
547  childSymbol = wxString::Format(wxT("(%d)"), start_arr + added_children);
548  }
549  child = AddChild(watch, childSymbol);
550  }
551  child->SetValue(token_name.ExtractString(value));
552  }
553  token_name.type = token_value.type = Token::Undefined;
554  added_children++;
555  }
556  else
557  return false;
558  }
559  break;
560  case Token::OpenBrace:
561  {
562  cb::shared_ptr<GDBWatch> child;
563  if(token_name.type == Token::Undefined)
564  {
565  if (g_DebugLanguage == dl_Cpp)
566  {
567  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0;
568  child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children));
569  }
570  else // g_DebugLanguage == dl_Fortran
571  {
572  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 1;
573  wxString childSymbol;
574  if (isFortranArray)
575  {
576  childSymbol = wxString::Format(wxT("(%d,"), start_arr + added_children);
577  childSymbol << watchSymbol.Mid(1);
578  }
579  else
580  {
581  childSymbol = wxString::Format(wxT("(%d)"), start_arr + added_children);
582  }
583  child = AddChild(watch, childSymbol);
584  }
585  }
586  else if (g_DebugLanguage == dl_Fortran)
587  child = AddChild(watch, token_name.ExtractString(value));
588  else
589  child = AddChild(watch, value, token_name);
590 
592  child->SetValue(wxEmptyString);
593  else if (!pythonToStringValue.empty())
594  child->SetValue(pythonToStringValue);
595  position = token_real_end;
596  added_children++;
597 
598  if(!ParseGDBWatchValue(child, value, position, 0))
599  return false;
600 
601  if(g_DebugLanguage == dl_Fortran && isFortranArray && !hasNewWatchSymbol && token_name.type == Token::Undefined)
602  {
603  // Change watch symbol on the way back for Fortran multidimensional arrays
604  wxString childSymbol;
605  child->GetSymbol(childSymbol);
606  wxString::size_type pos = childSymbol.find_last_of(wxT(':'));
607  if (pos != wxString::npos)
608  {
609  wxString::size_type pos_com = childSymbol.find(wxT(','), pos+2);
610  if (pos_com != wxString::npos)
611  {
612  watchSymbolNew = childSymbol;
613  watchSymbolNew.replace(pos+2, pos_com-(pos+2), wxT(':'));
614  hasNewWatchSymbol = true;
615  }
616  }
617  else
618  {
619  watchSymbolNew << wxT("(:,") << watchSymbol.Mid(1);
620  hasNewWatchSymbol = true;
621  }
622  }
623 
624  token_real_end = position;
625  token_name.type = token_value.type = Token::Undefined;
626  skip_comma = true;
627  last_was_closing_brace = true;
628  }
629  break;
630  case Token::CloseBrace:
631  if (!last_was_closing_brace)
632  {
633  if (token_name.type != Token::Undefined)
634  {
635  if (token_value.type != Token::Undefined)
636  {
637  cb::shared_ptr<GDBWatch> child = AddChild(watch, value, token_name);
638  child->SetValue(token_value.ExtractString(value));
639  }
640  else
641  {
642  cb::shared_ptr<GDBWatch> child;
643  if (g_DebugLanguage == dl_Cpp)
644  {
645  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0;
646  child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children));
647  }
648  else // g_DebugLanguage == dl_Fortran
649  {
650  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 1;
651  wxString childSymbol;
652  if (isFortranArray)
653  {
654  childSymbol = wxString::Format(wxT("(%d,"), start_arr + added_children);
655  childSymbol << watchSymbol.Mid(1);
656  if (!hasNewWatchSymbol)
657  {
658  watchSymbolNew << wxT("(:,") << watchSymbol.Mid(1);
659  hasNewWatchSymbol = true;
660  }
661  }
662  else
663  {
664  childSymbol = wxString::Format(wxT("(%d)"), start_arr + added_children);
665  }
666  child = AddChild(watch, childSymbol);
667  }
668  child->SetValue(token_name.ExtractString(value));
669  }
670  token_name.type = token_value.type = Token::Undefined;
671  added_children++;
672  }
673  else
674  watch->SetValue(wxT(""));
675  }
676 
677  if (hasNewWatchSymbol)
678  watch->SetSymbol(watchSymbolNew);
679 
680  start = token_real_end;
681  return true;
682  case Token::Undefined:
683  default:
684  return false;
685  }
686 
687  position = token_real_end;
688  if (length > 0 && position >= start + length)
689  break;
690  }
691 
692  start = position + 1;
693  if (token_name.type != Token::Undefined)
694  {
695  if (token_value.type != Token::Undefined)
696  {
697  cb::shared_ptr<GDBWatch> child = AddChild(watch, value, token_name);
698  child->SetValue(token_value.ExtractString(value));
699  }
700  else
701  {
702  cb::shared_ptr<GDBWatch> child;
703  if (g_DebugLanguage == dl_Cpp)
704  {
705  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0;
706  child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children));
707  }
708  else // g_DebugLanguage == dl_Fortran
709  {
710  int start_arr = watch->IsArray() ? watch->GetArrayStart() : 1;
711  child = AddChild(watch, wxString::Format(wxT("(%d)"), start_arr + added_children));
712  }
713  child->SetValue(token_name.ExtractString(value));
714  }
715  }
716 
717 
718 
719  return true;
720 }
721 
722 inline wxString RemoveWarnings(wxString const &input)
723 {
724  wxString::size_type pos = input.find(wxT('\n'));
725 
726  if (pos == wxString::npos)
727  return input;
728 
729  wxString::size_type lastPos = 0;
730  wxString result;
731 
732  while (pos != wxString::npos)
733  {
734  wxString const &line = input.substr(lastPos, pos - lastPos);
735 
736  if (!line.StartsWith(wxT("warning:")))
737  {
738  result += line;
739  result += wxT('\n');
740  }
741 
742  lastPos = pos + 1;
743  pos = input.find(wxT('\n'), lastPos);
744  }
745 
746  if (lastPos < input.length())
747  result += input.substr(lastPos, input.length() - lastPos);
748 
749  return result;
750 }
751 
752 inline void RemoveBefore(wxString &str, const wxString &s)
753 {
754  wxString::size_type pos = str.find(s);
755  if (pos != wxString::npos)
756  {
757  str.Remove(0, pos+s.length());
758  str.Trim(false);
759  }
760 }
761 
763 {
764  static wxRegEx nan_line(wxT("nan\\([a-zA-Z0-9]*\\)"));
765  nan_line.Replace(&outStr, wxT("nan"));
766  outStr.Replace(wxT("("),wxT("{"));
767  outStr.Replace(wxT(")"),wxT("}"));
768 }
769 
770 bool ParseGDBWatchValue(cb::shared_ptr<GDBWatch> watch, wxString const &inputValue)
771 {
772  if(inputValue.empty())
773  {
774  watch->SetValue(inputValue);
775  return true;
776  }
777 
778  wxString value = RemoveWarnings(inputValue);
779 
781  PrepareFortranOutput(value);
782 
783  // Try to find the first brace.
784  // If the watch is for a reference the brace is not at position = 0
785  wxString::size_type start = value.find(wxT('{'));
786 
787  if (start != wxString::npos && value[value.length() - 1] == wxT('}'))
788  {
789  // make sure the value is correct, even when the type has changed
790  watch->SetValue(wxEmptyString);
791 
792  int t_start = start + 1;
793  bool result = ParseGDBWatchValue(watch, value, t_start, value.length() - 2);
794  if (result)
795  {
796  if (start > 0)
797  {
798  wxString referenceValue = value.substr(0, start);
799  referenceValue.Trim(true);
800  referenceValue.Trim(false);
801  if (referenceValue.EndsWith(wxT("=")))
802  {
803  referenceValue.RemoveLast(1);
804  referenceValue.Trim(true);
805  }
806  watch->SetValue(referenceValue);
807  }
808  watch->RemoveMarkedChildren();
809  }
810  return result;
811  }
812  else
813  {
814  watch->SetValue(value);
815  watch->RemoveChildren();
816  return true;
817  }
818  return false;
819 }
820 
821 //
822 // struct HWND__ * 0x7ffd8000
823 //
824 // struct tagWNDCLASSEXA
825 // +0x000 cbSize : 0x7c8021b5
826 // +0x004 style : 0x7c802011
827 // +0x008 lpfnWndProc : 0x7c80b529 kernel32!GetModuleHandleA+0
828 // +0x00c cbClsExtra : 0
829 // +0x010 cbWndExtra : 2147319808
830 // +0x014 hInstance : 0x00400000
831 // +0x018 hIcon : 0x0012fe88
832 // +0x01c hCursor : 0x0040a104
833 // +0x020 hbrBackground : 0x689fa962
834 // +0x024 lpszMenuName : 0x004028ae "???"
835 // +0x028 lpszClassName : 0x0040aa30 "CodeBlocksWindowsApp"
836 // +0x02c hIconSm : (null)
837 //
838 // char * 0x0040aa30
839 // "CodeBlocksWindowsApp"
840 //
841 // char [16] 0x0012fef8
842 // 116 't'
843 //
844 // int [10] 0x0012fee8
845 // 0
846 
847 bool ParseCDBWatchValue(cb::shared_ptr<GDBWatch> watch, wxString const &value)
848 {
849  wxArrayString lines = GetArrayFromString(value, wxT('\n'));
850  watch->SetDebugValue(value);
851  watch->MarkChildsAsRemoved();
852 
853  if (lines.GetCount() == 0)
854  return false;
855 
856  static wxRegEx unexpected_error(wxT("^Unexpected token '.+'$"));
857  static wxRegEx resolve_error(wxT("^Couldn't resolve error at '.+'$"));
858 
859  // search for errors
860  for (unsigned ii = 0; ii < lines.GetCount(); ++ii)
861  {
862  if (unexpected_error.Matches(lines[ii])
863  || resolve_error.Matches(lines[ii])
864  || lines[ii] == wxT("No pointer for operator* '<EOL>'"))
865  {
866  watch->SetValue(lines[ii]);
867  return true;
868  }
869  }
870 
871  if (lines.GetCount() == 1)
872  {
873  wxArrayString tokens = GetArrayFromString(lines[0], wxT(' '));
874  if (tokens.GetCount() < 2)
875  return false;
876 
877  int type_token = 0;
878  if (tokens[0] == wxT("class") || tokens[0] == wxT("struct"))
879  type_token = 1;
880 
881  if (static_cast<int>(tokens.GetCount()) < type_token + 2)
882  return false;
883 
884  int value_start = type_token + 1;
885  if (tokens[type_token + 1] == wxT('*'))
886  {
887  watch->SetType(tokens[type_token] + tokens[type_token + 1]);
888  value_start++;
889  }
890  else
891  watch->SetType(tokens[type_token]);
892 
893  if(value_start >= static_cast<int>(tokens.GetCount()))
894  return false;
895 
896  watch->SetValue(tokens[value_start]);
897  watch->RemoveMarkedChildren();
898  return true;
899  }
900  else
901  {
902  wxArrayString tokens = GetArrayFromString(lines[0], wxT(' '));
903 
904  if (tokens.GetCount() < 2)
905  return false;
906 
907  bool set_type = true;
908  if (tokens.GetCount() > 2)
909  {
910  if (tokens[0] == wxT("struct") || tokens[0] == wxT("class"))
911  {
912  if (tokens[2] == wxT('*') || tokens[2].StartsWith(wxT("[")))
913  {
914  watch->SetType(tokens[1] + tokens[2]);
915  set_type = false;
916  }
917  }
918  else
919  {
920  if (tokens[1] == wxT('*') || tokens[1].StartsWith(wxT("[")))
921  {
922 
923  watch->SetType(tokens[0] + tokens[1]);
924  watch->SetValue(lines[1]);
925  return true;
926  }
927  }
928  }
929 
930  if (set_type)
931  watch->SetType(tokens[1]);
932 
933  static wxRegEx class_line(wxT("[ \\t]*\\+(0x[0-9a-f]+)[ \\t]([a-zA-Z0-9_]+)[ \\t]+:[ \\t]+(.+)"));
934  if (!class_line.IsValid())
935  {
936  int *p = NULL;
937  *p = 0;
938  }
939  else
940  {
941  if (!class_line.Matches(wxT(" +0x000 a : 10")))
942  {
943  int *p = NULL;
944  *p = 0;
945  }
946  }
947 
948  for (unsigned ii = 1; ii < lines.GetCount(); ++ii)
949  {
950  if (class_line.Matches(lines[ii]))
951  {
952  cb::shared_ptr<GDBWatch> w = AddChild(watch, class_line.GetMatch(lines[ii], 2));
953  w->SetValue(class_line.GetMatch(lines[ii], 3));
954  w->SetDebugValue(lines[ii]);
955  }
956  }
957  watch->RemoveMarkedChildren();
958  return true;
959  }
960 
961  return false;
962 }
963 
964 GDBLocalVariable::GDBLocalVariable(wxString const &nameValue, size_t start, size_t length)
965 {
966  for (size_t ii = 0; ii < length; ++ii)
967  {
968  if (nameValue[start + ii] == wxT('='))
969  {
970  name = nameValue.substr(start, ii);
971  name.Trim();
972  value = nameValue.substr(start + ii + 1, length - ii - 1);
973  value.Trim(false);
974  error = false;
975  return;
976  }
977  }
978  error = true;
979 }
980 
981 void TokenizeGDBLocals(std::vector<GDBLocalVariable> &results, wxString const &value)
982 {
983  size_t count = value.length();
984  size_t start = 0;
985  int curlyBraces = 0;
986  bool inString = false, inChar = false;
987  bool escaped = false;
988 
989  for (size_t ii = 0; ii < count; ++ii)
990  {
991  wxChar ch = value[ii];
992  switch (ch)
993  {
994  case wxT('\n'):
995  if (!inString && !inChar && curlyBraces == 0)
996  {
997  results.push_back(GDBLocalVariable(value, start, ii - start));
998  start = ii + 1;
999  }
1000  break;
1001  case wxT('{'):
1002  if (!inString && !inChar)
1003  curlyBraces++;
1004  break;
1005  case wxT('}'):
1006  if (!inString && !inChar)
1007  curlyBraces--;
1008  break;
1009  case wxT('"'):
1010  if (!inChar && !escaped)
1011  inString=!inString;
1012  break;
1013  case wxT('\''):
1014  if (!inString && !escaped)
1015  inChar=!inChar;
1016  break;
1017  default:
1018  break;
1019  }
1020 
1021  escaped = (ch == wxT('\\') && !escaped);
1022  }
1023  results.push_back(GDBLocalVariable(value, start, value.length() - start));
1024 }
DLLIMPORT wxArrayString GetArrayFromString(const wxString &text, const wxString &separator=DEFAULT_ARRAY_SEP, bool trimSpaces=true)
Definition: globals.cpp:134
C++ or C language.
DebuggerLanguage g_DebugLanguage
wxString substr(size_t nStart=0, size_t nLen=npos) const
wxRegEx regexRepeatedChars(wxT("^((\'.{1,6}\')|('.{1,6}'))[ \](<repeats[ \][0-9]+[ \]times>)"), wxRE_ADVANCED)
bool operator==(Token const &t) const
size_t length() const
wxString RemoveWarnings(wxString const &input)
wxString & replace(size_t nStart, size_t nLen, const wxString &str)
bool Matches(const wxString &text, int flags=0) const
#define _T(string)
bool wxIsdigit(const wxUniChar &c)
void TokenizeGDBLocals(std::vector< GDBLocalVariable > &results, wxString const &value)
wxString & Remove(size_t pos)
#define wxT(string)
Token(int start_, int end_, Type type_)
bool empty() const
size_t find(const wxString &str, size_t nStart=0) const
wxRegEx regexFortranArray(wxT("^\[0-9,]+)$"))
wxUSE_UNICODE_dependent wxChar
int Replace(wxString *text, const wxString &replacement, size_t maxMatches=0) const
bool GetNextToken(wxString const &str, int pos, Token &token)
bool ParseGDBWatchValue(cb::shared_ptr< GDBWatch > watch, wxString const &value, int &start, int length)
a symbol found in the parsed files, it can be many kinds, such as a variable, a class and so on...
Definition: token.h:82
wxString & RemoveLast(size_t n=1)
size_t Replace(const wxString &strOld, const wxString &strNew, bool replaceAll=true)
wxString ExtractString(wxString const &s) const
bool GetMatch(size_t *start, size_t *len, size_t index=0) const
size_t size_type
Fortran language.
wxString wxEmptyString
size_t find_last_of(const wxString &str, size_t nStart=npos) const
GDBLocalVariable(wxString const &nameValue, size_t start, size_t length)
wxRegEx regexRepeatedChar(wxT(".+[ \](<repeats[ \][0-9]+[ \]times>)$"))
wxString & Trim(bool fromRight=true)
void RemoveBefore(wxString &str, const wxString &s)
static void AddChild(cb::shared_ptr< cbWatch > parent, cb::shared_ptr< cbWatch > watch)
void PrepareFortranOutput(wxString &outStr)
bool IsValid() const
static const size_t npos
void Trim(wxString const &s)
bool EndsWith(const wxString &suffix, wxString *rest=NULL) const
bool ParseCDBWatchValue(cb::shared_ptr< GDBWatch > watch, wxString const &value)
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
size_t GetCount() const
bool hasRepeatedChar
#define NULL
Definition: prefix.cpp:59
static wxString Format(const wxString &format,...)
wxString Mid(size_t first, size_t nCount=wxString::npos) const
int DetectRepeatingSymbols(wxString const &str, int pos)
int SkipShortenedString(wxString const &str, int pos)
GDB can shorten the string.
bool AddChild(int childIdx)
add a child token
Definition: token.cpp:267