Author Topic: GDB & Code::Blocks : Is it possible to add own registering classes ?  (Read 6093 times)

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
When the debugger started, we can see :
Registered new type: wxString
Registered new type: STL String
Registered new type: STL Vector

I have my own string class derived from std::wstring (unicode string).
Problem, I cannot see it into the compiler as wxString (wxString with wxWidgets 2.9.0 couldn't be see too).
Could we add own registered type and how to add it ?
I have tryed to modify gdb_types.script  without any success.
I know we can add initialized commands to debugger in debugger settings but I don't know how to add own class reader into gdb and I think it is not the good topic to ask this kind of question for gdb configuration...

Is it possible to add own class into Code::Blocks ?
Thanks for reply.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: GDB & Code::Blocks : Is it possible to add own registering classes ?
« Reply #2 on: January 28, 2010, 04:47:38 pm »
I have modified this file to be able to see std::string and std::wstring (unicode strings) based on wxString.
If it could help someone.
For my class, derived from std::wstring, it don't work, it make gdb crash !

Code
/*
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * $Revision: 5783 $
 * $Id: gdb_types.script 5783 2009-09-14 15:17:56Z mortenmacfly $
 * $HeadURL: http://svn.berlios.de/svnroot/repos/codeblocks/trunk/src/scripts/gdb_types.script $
 */

// Registers new types with driver
function RegisterTypes(driver)
{
//    signature:
//    driver.RegisterType(type_name, regex, eval_func, parse_func);

    // STL WString
    driver.RegisterType(
        _T("STL WString"),
        _T("[^[:alnum:]_]*(wstring)[^[:alnum:]_]*"),
        _T("Evaluate_StlWString"),
        _T("Parse_StlWString")
    );

    // wxString
    driver.RegisterType(
        _T("wxString"),
        _T("[^[:alnum:]_]*wxString[^[:alnum:]_]*"),
        _T("Evaluate_wxString"),
        _T("Parse_wxString")
    );

    // STL String
    driver.RegisterType(
        _T("STL String"),
        _T("[^[:alnum:]_]*string[^[:alnum:]_]*"),
        _T("Evaluate_StlString"),
        _T("Parse_StlString")
    );

    // STL Vector
    driver.RegisterType(
        _T("STL Vector"),
        _T("[^[:alnum:]_]*vector<.*"),
        _T("Evaluate_StlVector"),
        _T("Parse_StlVector")
    );

    Log(_T("Registering types for the debugger."));
}

////////////////////////////////////////////////////////////////////////////////
// wxString
////////////////////////////////////////////////////////////////////////////////

// This function tells the driver how to evaluate this type.
// a_str contains the variable.
// start contains the starting position. Useful for arrays.
// count contains the count of evaluation. Useful for arrays. If 0, evaluate from start (variable) to end of array.
// result must contain the debugger's command when it returns.
function Evaluate_wxString(type, a_str, start, count)
{
    local oper = _T(".");

    if (type.Find(_T("*"), false) > 0)
        oper = _T("->");

    local result = _T("output /c ") + a_str + oper + _T("m_pchData[") + start + _T("]@");
    if (count != 0)
        result = result + count;
    else
        result = result + _T("((wxStringData*)") + a_str + oper + _T("m_pchData - 1)->nDataLength");
    return result;
}

// This function parses driver's output.
// When it returns, the _T("result") argument contains the parsing result.
function Parse_wxString(a_str, start)
{
    local result = _T("\"");
    local len = a_str.length();
    local c = 0;
    while (c < len)
    {
        switch (a_str.GetChar(c))
        {
            case '\'':
                ++c;
                while (c < len)
                {
                    switch (a_str.GetChar(c))
                    {
                        case '\\':
                            result.AddChar(a_str.GetChar(c++));
                            result.AddChar(a_str.GetChar(c++));
                            break;
                        default:
                            result.AddChar(a_str.GetChar(c++));
                            break;
                    }
                    if (a_str.GetChar(c) == '\'')
                        break;
                }
                break;

            default:
                break;
        }
        ++c;
    }
    result = result + _T("\"");
    return result;
}

////////////////////////////////////////////////////////////////////////////////
// STL String
////////////////////////////////////////////////////////////////////////////////

function Evaluate_StlString(type, a_str, start, count)
{
    local oper = _T(".");

    if (type.Find(_T("*"), false) > 0)
        oper = _T("->");

    local result = _T("output ") + a_str + oper + _T("c_str()[") + start + _T("]@");
    if (count != 0)
        result = result + count;
    else
        result = result + a_str + oper + _T("size()");
    return result;
}

function Parse_StlString(a_str, start)
{
    // nothing needs to be done
    return a_str;
}

////////////////////////////////////////////////////////////////////////////////
// STL Vector
////////////////////////////////////////////////////////////////////////////////

function Evaluate_StlVector(type, a_str, start, count)
{
    local result = _T("pvector ") + a_str;
    return result;
}

function Parse_StlVector(a_str, start)
{
    local size_pos = a_str.Find(_T("Vector size = "));

    if (size_pos < 0)
        return _T("");

    // copy the end of the a_str, so we don't search the whole string when we look for capacity
    local vector_info_str = a_str.Mid(size_pos, a_str.length() - size_pos);
    size_pos = 0;

    local capacity_pos = vector_info_str.Find(_T("Vector capacity = "));
    if (capacity_pos < 0)
        return _T("");

    local size_value = vector_info_str.Mid(14, capacity_pos - 15);
    local size = wxString_ToLong(size_value);

    local capacity_end_pos = vector_info_str.Find(_T("Element"));
    if(capacity_end_pos < 0)
        return _T("");
    capacity_pos += 18;
    local capacity_value = vector_info_str.Mid(capacity_pos, capacity_end_pos - capacity_pos - 1);
    local element_type_value = vector_info_str.Mid(capacity_end_pos + 15,
                                                   vector_info_str.length() - capacity_end_pos - 15);

    local result = _T("[size] = ") + size_value + _T(",\n");
    result += _T("[capacity] = ") + capacity_value + _T(",\n");
    result += _T("[element type] = ") + element_type_value;

    if(size > 0)
        result += _T(",\n");

    local value_str = a_str;
    for(local item = 0; item < size; item += 1)
    {
        local elem_str = _T("elem[") + item + _T("]: ");
        local elem_start = value_str.Find(elem_str);
        local elem_end = 0;
        if(item == size - 1)
            elem_end = value_str.Find(_T("Vector size"));
        else
            elem_end = value_str.Find(_T("elem[") + (item + 1) + _T("]: "));

        if(elem_start >= 0 && elem_end >= 0)
        {
            local elem_value = value_str.Mid(elem_start, elem_end - elem_start);
            local equal_pos = elem_value.Find(_T(" = "));
            if(equal_pos >= 0)
                elem_value.Remove(0, equal_pos + 3);
            if(item > 0)
                result += _T(",");
            result += _T("[") + item + _T("] = ") + elem_value + _T("\n");
        }
        else
            break;

        value_str.Remove(0, elem_end);
    }
    if(result.length() > 0)
    {
        return _T("{ " ) + result + _T(" } ");
    }
    return "";
}

////////////////////////////////////////////////////////////////////////////////
// STL WString
////////////////////////////////////////////////////////////////////////////////
function Evaluate_StlWString(type, a_str, start, count)
{
    local oper = _T(".");

    if (type.Find(_T("*"), false) > 0)
        oper = _T("->");

    local result = _T("output /c ") + a_str + oper + _T("c_str()[") + start + _T("]@");
    if (count != 0)
        result = result + count;
    else
        result = result + a_str + oper + _T("size()");
    return result;
}

function Parse_StlWString(a_str, start)
{
    local result = _T("\"");
    local len = a_str.length();
    local c = 0;
    while (c < len)
    {
        switch (a_str.GetChar(c))
        {
            case '\'':
                ++c;
                while (c < len)
                {
                    switch (a_str.GetChar(c))
                    {
                        case '\\':
                            result.AddChar(a_str.GetChar(c++));
                            result.AddChar(a_str.GetChar(c++));
                            break;
                        default:
                            result.AddChar(a_str.GetChar(c++));
                            break;
                    }
                    if (a_str.GetChar(c) == '\'')
                        break;
                }
                break;

            default:
                break;
        }
        ++c;
    }
    result = result + _T("\"");
    return result;
}

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: GDB & Code::Blocks : Is it possible to add own registering classes ?
« Reply #3 on: January 28, 2010, 09:52:10 pm »
For my class, derived from std::wstring, it don't work, it make gdb crash !
That is a gdb problem, it has crashed :) // you can try to report it to the gdb devs
What is your gdb version?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: GDB & Code::Blocks : Is it possible to add own registering classes ?
« Reply #4 on: January 29, 2010, 06:18:44 am »
I use GNU gdb (GDB) 7.0.1
For my class, when I write same command directly with gdb it's working but with the script that executed same things it crashed.
1> Do you think it is possible to add into Code::Blocks release the std::wstring script ? I think more and more peaple will use Unicode compilation and so will use wstring...
2> When arabic character are used, GDB don't write these characters... :-(
3> Yesterday, I read that this script will probably splitted into more files : One for predefined script (gived with Code::Blocks) and another for user, I think it is a very good idea !
« Last Edit: January 29, 2010, 06:31:25 am by Feneck91 »

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: GDB & Code::Blocks : Is it possible to add own registering classes ?
« Reply #5 on: January 29, 2010, 07:01:24 am »
I use GNU gdb (GDB) 7.0.1
If you are on windows, switch to 7.0.2, because 7.0.1 is known to have problems.

Offline eeghem

  • Single posting newcomer
  • *
  • Posts: 2
I've been recently using C::B and Qt, hence my interest in adding types to the gdb_types.script file. After some experimenting I was able to neatly print the QString. In case anyone is interesed, I solved it using the following steps:

1. in the RegisterTypes function I added:
Code
driver.RegisterType (_T("Qt String"), _T("[^[:alnum:]_]*QString[^[:alnum:]_]*"), _T("Evaluate_QtString"), _T("Parse_QtString"))

2. in the file I added the functions Evaluate_QtString and Parse_QtString like this:
Code
function Evaluate_QtString (type, a_str, start, count) {
    // determine the method of accessing the variable (if it is a reference use the
    // '.' else use the '->'.
    local oper = _T(".");
    if (type.Find(_T("*"), false) > 0)
        oper = _T("->");

    // create the output string send to the debugger
    // since it is a qstring we actually want the debugger to do the following
    // (char*) stringvar.d
    local result = _T("output /c ") + a_str + oper + _T("d.data[0]@") + a_str + oper + _T("d.size");
    return result;
}

function Parse_QtString (a_str, start) {
    return Parse_wxString (a_str, start);
}

Note that I reuse the Parse_wxString. No need to reinvent the wheel. The result is quite satisfactoring  :D.

Ruud

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
I've been recently using C::B and Qt, hence my interest in adding types to the gdb_types.script file. After some experimenting I was able to neatly print the QString. In case anyone is interesed, I solved it using the following steps:

I just find some discussion about viewing the Qt string, see here:
Re: Debugging QString
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.