void PythonDebugger::DeleteBreakpoint(cb::shared_ptr<cbBreakpoint> bp)
{
    if(!IsPythonFile(bp->GetLocation()))
        return;
    wxString sfile=bp->GetLocation();
    int line = bp->GetLine();

    for (size_t i=0;i<m_bplist.size();++i)
    {
        if(m_bplist[i]!=bp)
            continue;
//        if(m_bplist[i]->GetFilename()==bp->GetFilename() && m_bplist[i]->GetLine()==bp->GetLine())
        m_bplist.erase(m_bplist.begin()+i);
        if(m_DebuggerActive)
        {
//            if(sfile.Contains(_T(" ")))
//            {
//                wxFileName f(sfile);
//                sfile=f.GetShortPath();
//            }
            wxString cmd=_T("clear ")+sfile+_T(":")+wxString::Format(_T("%i"),line)+_T("\n");
            DispatchCommands(cmd,DBGCMDTYPE_BREAKPOINT);
         }
         return;
    }
}
inline bool TestIfMarkedForRemoval(cb::shared_ptr<cbWatch> watch)
{
    if(watch->IsRemoved())
        return true;
    else
    {
        watch->RemoveMarkedChildren();
        return false;
    }
}
inline cb::shared_ptr<GDBWatch> AddChild(cb::shared_ptr<GDBWatch> parent, wxString const &str_name)
{
    int index = parent->FindChildIndex(str_name);
    cb::shared_ptr<GDBWatch> child;
    if (index != -1)
        child = cb::static_pointer_cast<GDBWatch>(parent->GetChild(index));
    else
    {
        child = cb::shared_ptr<GDBWatch>(new GDBWatch(str_name));
        cbWatch::AddChild(parent, child);
    }
    child->MarkAsRemoved(false);
    return child;
}
void RemoveMissingChildren(cb::shared_ptr<cbWatch> parent, const std::set<wxString> &knownsyms)
{
    for (int i=0; i<parent->GetChildCount(); ++i)
    {
        cb::shared_ptr<cbWatch> p(parent->GetChild(i));
        wxString s;
        p->GetSymbol(s);
        if (knownsyms.find(s)==knownsyms.end())
        {
            parent->RemoveChild(i);
            --i;
            continue;
        }
    }
}
void PythonDebugger::UpdateWatch(cb::shared_ptr<cbWatch> watch)
{
    if(IsRunning())
    {
//        watch->RemoveChildren(); //TODO: Update instead of removing children

        wxString symbol;
        watch->GetSymbol(symbol);
        DispatchCommands(_T("ps ")+symbol+_T("\n"),DBGCMDTYPE_WATCHEXPRESSION);
    }
}
void PythonDebugger::ExpandWatch(cb::shared_ptr<cbWatch> watch)
{
    if(IsRunning())
    {
        if (watch == m_locals_watch)
            DispatchCommands(_T("pl *Locals:\n"),DBGCMDTYPE_WATCHGETCHILDREN);
        else
        {
            wxString symbol;
            watch->GetSymbol(symbol);
            DispatchCommands(_T("pm ")+symbol+_T("\n"),DBGCMDTYPE_WATCHGETCHILDREN);
        }
    }
}
inline cb::shared_ptr<GDBWatch> AddChild(cb::shared_ptr<GDBWatch> parent, wxString const &full_value, Token &name)
{
    wxString const &str_name = name.ExtractString(full_value);
    cb::shared_ptr<cbWatch> old_child = parent->FindChild(str_name);
    cb::shared_ptr<GDBWatch> child;
    if (old_child)
        child = cb::static_pointer_cast<GDBWatch>(old_child);
    else
    {
        child = cb::shared_ptr<GDBWatch>(new GDBWatch(str_name));
        cbWatch::AddChild(parent, child);
    }
    child->MarkAsRemoved(false);
    return child;
}
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;
}