bool ParseGDBWatchValue(cb::shared_ptr<GDBWatch> watch, wxString const &inputValue) { if(inputValue.empty()) { watch->SetValue(inputValue); return true; } wxString value = RemoveWarnings(inputValue); // Try to find the first brace. // If the watch is for a reference the brace is not at position = 0 wxString::size_type start = value.find(wxT('{')); if (start != wxString::npos && value[value.length() - 1] == wxT('}')) { // make sure the value is correct, even when the type has changed watch->SetValue(wxEmptyString); int t_start = start + 1; bool result = ParseGDBWatchValue(watch, value, t_start, value.length() - 2); if (result) { if (start > 0) { wxString referenceValue = value.substr(0, start); referenceValue.Trim(true); referenceValue.Trim(false); if (referenceValue.EndsWith(wxT("="))) { referenceValue.RemoveLast(1); referenceValue.Trim(true); } watch->SetValue(referenceValue); } watch->RemoveMarkedChildren(); } return result; } else { watch->SetValue(value); watch->RemoveChildren(); return true; } return false; }
bool ParseCDBWatchValue(cb::shared_ptr<GDBWatch> watch, wxString const &value) { wxArrayString lines = GetArrayFromString(value, wxT('\n')); watch->SetDebugValue(value); watch->MarkChildsAsRemoved(); if (lines.GetCount() == 0) return false; static wxRegEx unexpected_error(wxT("^Unexpected token '.+'$")); static wxRegEx resolve_error(wxT("^Couldn't resolve error at '.+'$")); // search for errors for (unsigned ii = 0; ii < lines.GetCount(); ++ii) { if (unexpected_error.Matches(lines[ii]) || resolve_error.Matches(lines[ii]) || lines[ii] == wxT("No pointer for operator* '<EOL>'")) { watch->SetValue(lines[ii]); return true; } } if (lines.GetCount() == 1) { wxArrayString tokens = GetArrayFromString(lines[0], wxT(' ')); if (tokens.GetCount() < 2) return false; int type_token = 0; if (tokens[0] == wxT("class") || tokens[0] == wxT("struct")) type_token = 1; if (static_cast<int>(tokens.GetCount()) < type_token + 2) return false; int value_start = type_token + 1; if (tokens[type_token + 1] == wxT('*')) { watch->SetType(tokens[type_token] + tokens[type_token + 1]); value_start++; } else watch->SetType(tokens[type_token]); if(value_start >= static_cast<int>(tokens.GetCount())) return false; watch->SetValue(tokens[value_start]); watch->RemoveMarkedChildren(); return true; } else { wxArrayString tokens = GetArrayFromString(lines[0], wxT(' ')); if (tokens.GetCount() < 2) return false; bool set_type = true; if (tokens.GetCount() > 2) { if (tokens[0] == wxT("struct") || tokens[0] == wxT("class")) { if (tokens[2] == wxT('*') || tokens[2].StartsWith(wxT("["))) { watch->SetType(tokens[1] + tokens[2]); set_type = false; } } else { if (tokens[1] == wxT('*') || tokens[1].StartsWith(wxT("["))) { watch->SetType(tokens[0] + tokens[1]); watch->SetValue(lines[1]); return true; } } } if (set_type) watch->SetType(tokens[1]); static wxRegEx class_line(wxT("[ \\t]*\\+(0x[0-9a-f]+)[ \\t]([a-zA-Z0-9_]+)[ \\t]+:[ \\t]+(.+)")); if (!class_line.IsValid()) { int *p = NULL; *p = 0; } else { if (!class_line.Matches(wxT(" +0x000 a : 10"))) { int *p = NULL; *p = 0; } } for (unsigned ii = 1; ii < lines.GetCount(); ++ii) { if (class_line.Matches(lines[ii])) { cb::shared_ptr<GDBWatch> w = AddChild(watch, class_line.GetMatch(lines[ii], 2)); w->SetValue(class_line.GetMatch(lines[ii], 3)); w->SetDebugValue(lines[ii]); } } watch->RemoveMarkedChildren(); return true; } return false; }
inline bool ParseGDBWatchValue(cb::shared_ptr<GDBWatch> watch, wxString const &value, int &start, int length) { watch->SetDebugValue(value); watch->MarkChildsAsRemoved(); int position = start; Token token, token_name, token_value; wxString pythonToStringValue; bool skip_comma = false; bool last_was_closing_brace = false; int added_children = 0; int token_real_end = 0; while (GetNextToken(value, position, token)) { token_real_end = token.end; token.Trim(value); const wxString &str = token.ExtractString(value); if (str.StartsWith(wxT("members of "))) { wxString::size_type pos = str.find(wxT('\n')); if (pos == wxString::npos) { // If the token has no '\n' character, then we have to search the whole value // for the token and then we skip this token completely. wxString::size_type pos_val = value.find(wxT('\n'), token_real_end); if (pos_val == wxString::npos) return false; position = pos_val+1; if (length > 0 && position >= start + length) break; continue; } else { // If we have the '\n' in the token, then we have the next valid token, too, // so we correct the current token to be the correct one. if (str.find_last_of(wxT(':'), pos) == wxString::npos) return false; token.start += pos + 2; token.Trim(value); } } if (!token.hasRepeatedChar && regexRepeatedChar.Matches(str)) { Token expanded_token = token; while (1) { if (value[expanded_token.end] == wxT(',')) { position = token.end + 1; token_real_end = position; int comma_end = expanded_token.end; if (GetNextToken(value, position, expanded_token)) { const wxString &expanded_str = expanded_token.ExtractString(value); if (!expanded_str.empty() && (expanded_str[0] != wxT('"') && expanded_str[0] != wxT('\''))) { token.end = comma_end; position = comma_end; token_real_end = comma_end; break; } token.end = expanded_token.end; if (regexRepeatedChar.Matches(expanded_str)) continue; token_real_end = expanded_token.end; } } else if (expanded_token.end == static_cast<int>(value.length())) { token.end = expanded_token.end; token_real_end = expanded_token.end; } break; } } switch (token.type) { case Token::String: if (token_name.type == Token::Undefined) token_name = token; else if (token_value.type == Token::Undefined) { if ( wxIsdigit(str[0]) || str[0]==wxT('\'') || str[0]==wxT('"') || str[0]==wxT('<') || str[0]==wxT('-') || str.StartsWith(wxT("L\"")) || str.StartsWith(wxT("L'")) ) { token_value = token; } else { // Detect strings generated by python pretty printing to_string() method. Token expanded_token = token; int firstCloseBrace = -1; for (; expanded_token.end < static_cast<int>(value.length()); ++expanded_token.end) { if (value[expanded_token.end] == wxT('=')) { bool foundBrace = false; for (int ii = expanded_token.end + 1; ii < static_cast<int>(value.length()); ++ii) { if (value[ii] == wxT('{')) { foundBrace = true; break; } else if (value[ii] != wxT(' ') && value[ii] != wxT('\t') && value[ii] != wxT('\n') && value[ii] != wxT(' ')) { break; } } if (foundBrace) { token.end = token_real_end = expanded_token.end; token_value = token; token_value.end--; pythonToStringValue = token_value.ExtractString(value); } else { while (expanded_token.end >= 0) { if (value[expanded_token.end] == wxT(',')) { token.end = token_real_end = expanded_token.end; token_value = token; pythonToStringValue = token_value.ExtractString(value); break; } expanded_token.end--; } } break; } else if (firstCloseBrace == -1 && value[expanded_token.end] == wxT('}')) { firstCloseBrace=expanded_token.end; break; } } if (pythonToStringValue.empty()) { if (firstCloseBrace == -1) return false; token.end = token_real_end = firstCloseBrace; token_value = token; pythonToStringValue = token_value.ExtractString(value); if (pythonToStringValue.empty()) return false; } } } else return false; last_was_closing_brace = false; break; case Token::Equal: last_was_closing_brace = false; break; case Token::Comma: pythonToStringValue = wxEmptyString; last_was_closing_brace = false; if (skip_comma) skip_comma = false; else { if (token_name.type != Token::Undefined) { if (token_value.type != Token::Undefined) { cb::shared_ptr<GDBWatch> child = AddChild(watch, value, token_name); child->SetValue(token_value.ExtractString(value)); } else { int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0; cb::shared_ptr<GDBWatch> child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children)); child->SetValue(token_name.ExtractString(value)); } token_name.type = token_value.type = Token::Undefined; added_children++; } else return false; } break; case Token::OpenBrace: { cb::shared_ptr<GDBWatch> child; if(token_name.type == Token::Undefined) { int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0; child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children)); } else child = AddChild(watch, value, token_name); if (!pythonToStringValue.empty()) child->SetValue(pythonToStringValue); position = token_real_end; added_children++; if(!ParseGDBWatchValue(child, value, position, 0)) return false; token_real_end = position; token_name.type = token_value.type = Token::Undefined; skip_comma = true; last_was_closing_brace = true; } break; case Token::CloseBrace: if (!last_was_closing_brace) { if (token_name.type != Token::Undefined) { if (token_value.type != Token::Undefined) { cb::shared_ptr<GDBWatch> child = AddChild(watch, value, token_name); child->SetValue(token_value.ExtractString(value)); } else { int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0; cb::shared_ptr<GDBWatch> child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children)); child->SetValue(token_name.ExtractString(value)); } token_name.type = token_value.type = Token::Undefined; added_children++; } else watch->SetValue(wxT("")); } start = token_real_end; return true; case Token::Undefined: default: return false; } position = token_real_end; if (length > 0 && position >= start + length) break; } start = position + 1; if (token_name.type != Token::Undefined) { if (token_value.type != Token::Undefined) { cb::shared_ptr<GDBWatch> child = AddChild(watch, value, token_name); child->SetValue(token_value.ExtractString(value)); } else { int start_arr = watch->IsArray() ? watch->GetArrayStart() : 0; cb::shared_ptr<GDBWatch> child = AddChild(watch, wxString::Format(wxT("[%d]"), start_arr + added_children)); child->SetValue(token_name.ExtractString(value)); } } return true; }