Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => Topic started by: ollydbg on June 16, 2009, 11:18:18 am

Title: Some thoughts on doing breakpoints persistent
Post by: ollydbg on June 16, 2009, 11:18:18 am
UPDATED 2012-12-15: Patch was in https://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2775&group_id=5358
Some related discussion in Re: Splitting debugger in two - specific debugger and common GUI (http://forums.codeblocks.org/index.php/topic,10908.msg82193.html#msg82193)


Hi, all.

I'm thinking to save the breakpoints in  debuggergdb plugin. (I don't think I have the ability to do the whole job, just plan to do this .... :()
After reading the related source code, I think the best time to "load the breakpoints from a project" is in:

Code
void DebuggerGDB::OnProjectLoadingHook(cbProject* project, TiXmlElement* elem, bool loading)


I think both "breakpoints" list and "watch variables list" can be automatically saved to hard disk, and loaded when a project opened.

Also, we can take the source code from "browsetracker.cpp" as a reference (BrowseTracker plugin).
Code
// ----------------------------------------------------------------------------
void ProjectData::LoadLayout()
// ----------------------------------------------------------------------------
{
    // Load a layout file for this project
    #if defined(LOGGING)
    LOGIT( _T("ProjectData::LoadLayout()for[%s]"),m_ProjectFilename.c_str() );
    #endif

    if (m_ProjectFilename.IsEmpty())
        return ;

    wxFileName fname(m_ProjectFilename);
    fname.SetExt(_T("bmarks"));
    BrowseTrackerLayout layout( m_pCBProject );
    layout.Open(fname.GetFullPath(), m_FileBrowse_MarksArchive, m_FileBook_MarksArchive);
    m_bLayoutLoaded = true;
}
// ----------------------------------------------------------------------------
void ProjectData::SaveLayout()
// ----------------------------------------------------------------------------
{
    // Write a layout file for this project
    #if defined(LOGGING)
    LOGIT( _T("ProjectData::SAVELayout()") );
    #endif

    if (m_ProjectFilename.IsEmpty())
        return ;

    wxFileName fname(m_ProjectFilename);
    fname.SetExt(_T("bmarks"));
    BrowseTrackerLayout layout( m_pCBProject );
    ////DumpBrowse_Marks(wxT("BookMarks"));
    ////DumpBrowse_Marks(wxT("BrowseMarks"));
    layout.Save(fname.GetFullPath(), m_FileBrowse_MarksArchive, m_FileBook_MarksArchive);


    //// *Testing* See if cbEditor is actually there
    //EditorBase* eb = m_EditorBaseArray[1];
    //cbEditor* cbed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(eb);
    //cbStyledTextCtrl* control = cbed->GetControl();
    //#if defined(LOGGING)
    //LOGIT( _T("eb[%p]cbed[%p]control[%p]"), eb, cbed, control );
    //#endif

    //// *Testing* Check against our array
    //eb = m_EditorBaseArray[1];
    //cbed = m_cbEditorArray[1];
    //control = m_cbSTCArray[1];
    //#if defined(LOGGING)
    //LOGIT( _T("eb[%p]cbed[%p]control[%p]"), eb, cbed, control );
    //#endif


}

But I can't determine which Event is good for loading breakpoints.

Code
// -- Project events
    // EVT_PROJECT_OPEN(       BrowseTracker::OnProjectOpened)
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_OPEN, new cbEventFunctor<BrowseTracker, CodeBlocksEvent>(this, &BrowseTracker::OnProjectOpened));
    // EVT_PROJECT_CLOSE(       BrowseTracker::OnProjectOpened)
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_CLOSE, new cbEventFunctor<BrowseTracker, CodeBlocksEvent>(this, &BrowseTracker::OnProjectClosing));

    // EVT_PROJECT_ACTIVATE(   BrowseTracker::OnProjectActivated)
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_ACTIVATE, new cbEventFunctor<BrowseTracker, CodeBlocksEvent>(this, &BrowseTracker::OnProjectActivatedEvent));

    // hook to project loading procedure
    // This hook only occurs if the project has an "extension" xml entry
    ProjectLoaderHooks::HookFunctorBase* myProjhook = new ProjectLoaderHooks::HookFunctor<BrowseTracker>(this, &BrowseTracker::OnProjectLoadingHook);
    m_ProjectHookId = ProjectLoaderHooks::RegisterHook(myProjhook);




EVT_PROJECT_ACTIVATE?
EVT_PROJECT_OPEN?


Any Comments?

Thanks!

Title: Re: Some thoughts on doing breakpoints persistant
Post by: MortenMacFly on June 16, 2009, 12:11:45 pm
I think both "breakpoints" list and "watch variables list" can be automatically saved to hard disk, and loaded when a project opened.
Notice that the watches can already be saved/loaded. You can have a look at how this is done...

Notice that this info should *not* be in a project file. This is developer-specific and not project specific. It mus be an external (addon) file or alike.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: oBFusCATed on June 16, 2009, 12:43:43 pm
Do we have such common file? Or everybody should save to his/her own file?
Visual studio for example uses project_name.user file for such thing?
We can do something similar and provide a common interface for it.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: MortenMacFly on June 16, 2009, 12:56:21 pm
We can do something similar and provide a common interface for it.
Probably a "layout" file would do. Similar like it's done with the project layout.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: Jenna on June 16, 2009, 01:01:52 pm
We can do something similar and provide a common interface for it.
Probably a "layout" file would do. Similar like it's done with the project layout.

This is developer-specific and not project specific. It mus be an external (addon) file or alike.
That's the same for the layout-file we have at the moment and should probably be changed in a similar way we might do for watches/bp's.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: MortenMacFly on June 16, 2009, 02:14:52 pm
That's the same for the layout-file we have at the moment and should probably be changed in a similar way we might do for watches/bp's.
Why? I don't put the layout files under version control because that's *my* setup. So if the BP's are also in some kind of layout file it'd be OK... or not?!
Title: Re: Some thoughts on doing breakpoints persistant
Post by: killerbot on June 16, 2009, 02:22:08 pm
yes, breakpoints should not be in cbp, put in a file which should not be version controlled.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 16, 2009, 03:32:47 pm
In the browsetracker plugin, all the "browse_Marks" will be recorded in a your_project_name.bmarks file.

It is a XML file format. For example:

Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<BrowseTracker_layout_file>
<ActiveTarget name="Debug" />
<File name="LearnWX1App.cpp" open="1" top="0" tabpos="4">
<Cursor position="646" topLine="0" />
<BrowseMarks positions="472,646" />
<Book_Marks positions="" />
</File>
<File name="LearnWX1Main.cpp" open="1" top="0" tabpos="1">
<Cursor position="3467" topLine="67" />
<BrowseMarks positions="1728,2413,3467" />
<Book_Marks positions="" />
</File>
<File name="LearnWX1Main.h" open="1" top="0" tabpos="2">
<Cursor position="1476" topLine="24" />
</File>
<File name="resource.rc" open="0" top="0" tabpos="0">
<Cursor position="48" topLine="0" />
</File>
<File name="wx_pch.h" open="1" top="0" tabpos="3">
<Cursor position="396" topLine="0" />
</File>
</BrowseTracker_layout_file>

Every files will be recorded, including the "tab position", the Cursor position, the "BrowseMarks positions".

Seems we can just add another entry like below
Code
<File name="LearnWX1App.cpp" open="1" top="0" tabpos="4">
<Cursor position="646" topLine="0" />
<BrowseMarks positions="472,646" />
<Book_Marks positions="" />
                <Break_Points positions= "XXXXXX, XXXXXX, XXXXXX"
</File>

Edit: This will be mess up  :(, debuggerGDB plugin should have its own layout file like

your_project_name.bps


 :D
Title: Re: Some thoughts on doing breakpoints persistant
Post by: oBFusCATed on June 16, 2009, 03:55:10 pm
Having 100 files in the project's directory is bad and ugly.

There should be only one file looking like:

Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<cb_project_setting>
       <layout> ala bala </layout>
       <debugger_plugin> ala bala </debugger_plugin>
       <browse_tracker_plugin> </browse_tracker_plugin>
       .
       .
</cb_project_setting>

And there should be an easy way to get your data:
Code
CProjData *data = some_manager->GetProjectSettings()->GetData("layout");

do something with the data....

 some_manager->GetProjectSettings()->SetData("layout", data);

p.s. by the way, I don't know what is the API for dealing with xml inside C::B :)
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 16, 2009, 04:10:44 pm
It use tinyXML related functions.

See: Source/Base/tinyXML/*.cpp

your_project_name.cbp
your_project_name.layout
your_project_name.bmarks

all the above files have the same XML format. :D
Title: Re: Some thoughts on doing breakpoints persistant
Post by: MortenMacFly on June 16, 2009, 04:55:06 pm
There should be only one file looking like:
Sure not! I don't want to share my breakpoints with other developers on the same project.

So settings like BP's cannot be in the project file. Because that's what you share with other developers. In addition it would be modified every time you change a BP. However - important settings about the setup of the debugger itself (e.g. parameters for a remote connection) belong into the project file so that's why we have that "debugger" section there.

So it would not be 100 files. It's a 1:1 relation to your project file. but it's local ("for your eyes") only because that's how the use case is in the end.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: oBFusCATed on June 16, 2009, 05:06:40 pm
Yes, I'm not saying to put the user settings in the project file.
I'm saying that I don't want to have 10-20 files in my project dir:
myproject.layout
myproject.bps
myproject.books
myproject.svnplg
myproject.whatnot

but just one:

myproject.user.settings (for example) that is not in svn as the other.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 16, 2009, 05:40:30 pm
I suggest the first step is to use separate setting files.

then after that, we can combine them together, I'm concerning mutiply-accessing to single file from different plugins will cause conflicts.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: MortenMacFly on June 16, 2009, 06:01:01 pm
myproject.user.settings (for example) that is not in svn as the other.
Agreed.
I'm concerning mutiply-accessing to single file from different plugins will cause conflicts.
Indeed. So the only solution I see is that the core provides methods to the plugin to write settings into a file handled by the core. This way all plugins have the possibility to store their (volatile) information in a file other than the project file. Still plugin may need own config files. So we cannot ensure it'll stay a single file.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: oBFusCATed on June 16, 2009, 06:06:08 pm
Indeed. So the only solution I see is that the core provides methods to the plugin to write settings into a file handled by the core. This way all plugins have the possibility to store their (volatile) information in a file other than the project file. Still plugin may need own config files. So we cannot ensure it'll stay a single file.

We talk about data per project.
If a plugin needs some global configuration, the core can(must) still provide an interface for storing settings.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 16, 2009, 06:16:33 pm
We talk about data per project.
If a plugin needs some global configuration, the core can(must) still provide an interface for storing settings.

Yes, There are many *.ini files  for plugin global settings in APPDATA folder.

Edit:
Some global settings were using XML format, such as "default.conf"
Others use INI file format.


For example the BrowseTracker.ini
Code
BrowseMarksEnabled=1
BrowseMarksStyle=0
BrowseMarksToggleKey=0
LeftMouseDelay=400
BrowseMarksClearAllMethod=0

I'm not sure the core supply method to access these ini files.


Edit2

I found in cbproject.cpp, there are some code do the "your_project_name.layout" file IO.

Code
bool cbProject::SaveLayout()
{
    if (m_Filename.IsEmpty())
        return false;

    wxFileName fname(m_Filename);
    fname.SetExt(_T("layout"));
    ProjectLayoutLoader loader(this);
    return loader.Save(fname.GetFullPath());
}

bool cbProject::LoadLayout()
{
   if (m_Filename.IsEmpty())
        return false;
    int openmode = Manager::Get()->GetConfigManager(_T("project_manager"))->ReadInt(_T("/open_files"), (long int)1);
    bool result = false;

    if(openmode==2)
    {
        // Do not open any files
        result = true;
    }
    else
    {
        Manager::Get()->GetEditorManager()->HideNotebook();
        if(openmode == 0) // Open all files
        {
            FilesList::Node* node = m_Files.GetFirst();
            while(node)
            {
                ProjectFile* f = node->GetData();
                Manager::Get()->GetEditorManager()->Open(f->file.GetFullPath(),0,f);
                node = node->GetNext();
            }
            result = true;
        }
        else if(openmode == 1)// Open last open files
        {
            wxFileName fname(m_Filename);
            fname.SetExt(_T("layout"));
            ProjectLayoutLoader loader(this);
            if (loader.Open(fname.GetFullPath()))
            {
                typedef std::map<int, ProjectFile*> open_files_map;
                open_files_map open_files;

                // Get all files to open and sort them according to their tab-position:
                FilesList::Node* node = m_Files.GetFirst();
                while(node)
                {
                    ProjectFile* f = node->GetData();
                    if (f->editorOpen)
                        open_files[f->editorTabPos] = f;
                    node = node->GetNext();
                }

                // Load all requested files
                std::vector<LoaderBase*> filesInMemory;
                for (open_files_map::iterator it = open_files.begin(); it != open_files.end(); ++it)
                {
                    filesInMemory.push_back(Manager::Get()->GetFileManager()->Load((*it).second->file.GetFullPath()));
                }
                // Open all requested files:
                size_t i = 0;
                for (open_files_map::iterator it = open_files.begin(); it != open_files.end(); ++it)
                {
                    cbEditor* ed = Manager::Get()->GetEditorManager()->Open(filesInMemory[i], (*it).second->file.GetFullPath(),0,(*it).second);
                    if (ed)
                        ed->SetProjectFile((*it).second);
                    ++i;
                }

                ProjectFile* f = loader.GetTopProjectFile();
                if (f)
                {
                    Manager::Get()->GetLogManager()->DebugLog(_T("Top Editor: ") + f->file.GetFullPath());
                    EditorBase* eb = Manager::Get()->GetEditorManager()->Open(f->file.GetFullPath());
                    if(eb)
                        eb->Activate();
                }
//                Manager::Get()->GetAppWindow()->Thaw();
            }
            result = true;
        }
        else
            result = false;
        Manager::Get()->GetEditorManager()->ShowNotebook();
    }
    return result;
}
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 17, 2009, 10:48:19 am
Hi, I'm doing a simple test.
Here is a breakpoints layout file
Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<BreakPoints_layout_file>
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="58" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="74" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="71" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="68" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="66" />
</BreakPoints_layout_file>

My question is:
Is there any way I can change the absolute file name to relative file name?

Since my code is like this:

Code
// ----------------------------------------------------------------------------
bool BreakPointsLayout::Save(const wxString& filename, BreakpointsList &breakPointsList)
// ----------------------------------------------------------------------------
{
    const char* ROOT_TAG = "BreakPoints_layout_file";

    TiXmlDocument doc;
    doc.SetCondenseWhiteSpace(false);
    doc.InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
    TiXmlElement* rootnode = static_cast<TiXmlElement*>(doc.InsertEndChild(TiXmlElement(ROOT_TAG)));
    if (!rootnode)
        return false;


    for (int i = breakPointsList.GetCount() - 1; i >= 0; --i)
    {
        DebuggerBreakpoint* bp = breakPointsList[i];
        //Only save the breakpoints belong to the current project
        if (bp->userData == m_pProject)
        {
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Got one")));
            TiXmlElement* node = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("BreakPoint")));
            node->SetAttribute("file", cbU2C(bp->filename));
            node->SetAttribute("position", bp->line);
            //RemoveBreakpoint(i, true);
        }
    }


    return cbSaveTinyXMLDocument(&doc, filename);
}

bp->filename is a full name.

But in debugger_def.h

Code
struct DebuggerBreakpoint
{
enum BreakpointType
{
bptCode = 0, ///< Normal file/line breakpoint
bptFunction, ///< Function signature breakpoint
bptData ///< Data breakpoint
};

    /** Constructor.
      * Sets default values for members.
      */
    DebuggerBreakpoint()
        : type(bptCode),
        line(0),
        index(-1),
        temporary(false),
        enabled(true),
        active(true),
        useIgnoreCount(false),
        ignoreCount(0),
        useCondition(false),
        wantsCondition(false),
        address(0),
        alreadySet(false),
        breakOnRead(false),
        breakOnWrite(true),
        userData(0)
    {}
    BreakpointType type; ///< The type of this breakpoint.
    wxString filename; ///< The filename for the breakpoint (kept as relative).

It said the file name should  keep as relative. :(


Any Comments?

Thanks
Title: Re: Some thoughts on doing breakpoints persistant
Post by: Jenna on June 17, 2009, 12:12:01 pm
You can use the MakeRelativeTo-function of wxFileName.

The code below is not tested !

Code
    wxFileName fname;

    for (int i = breakPointsList.GetCount() - 1; i >= 0; --i)
    {
        DebuggerBreakpoint* bp = breakPointsList[i];
        //Only save the breakpoints belong to the current project
        if (bp->userData == m_pProject)
        {
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Got one")));
            TiXmlElement* node = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("BreakPoint")));
            fname.Assign(bp->filename);
            if (fname.IsAbsolute())
            {
                fname.MakeRelativeTo(m_pProject->GetBasePath());
            }
            node->SetAttribute("file", cbU2C(fname.GetFullPath()));
            node->SetAttribute("position", bp->line);
            //RemoveBreakpoint(i, true);
        }
    }

Instead of m_pProject->GetBasePath() it might also make sense to use m_pProject->GetCommonTopLevelPath().
Depends on what the debugger-plugin wants.

No time to look into it at themoment.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 17, 2009, 01:13:46 pm
Thanks for your help. Now, using the MakeRelativeTo() function ,I can save and load the saved breakpoints( simple position based breakpoints)

There is only one thing left. Since when I load the project, the BreakpointsList were successfully loaded from a projectname.bps file. But the UI has not notified. See the image below:
(http://img5.imageshack.us/img5/3061/bp1i.png)

Breakpoints on Line 77 73 and 71 were loaded, but they were not shown on the editor. Even I add another breakpoint on line 59.

Then only way to show the breakpoints icon in the editor is "reopen the main.cpp file", see below:

(http://img4.imageshack.us/img4/2483/bp2.png)

So, I need a way to "notify the editor" after all the breakpoints were loaded.

Title: Re: Some thoughts on doing breakpoints persistant
Post by: Jenna on June 17, 2009, 01:23:10 pm
Do you use AddBreakpoint from debugger-plugin or from editor ?

You can use the function from cbEditor, if the source-file is already opened and set notifyDebugger to true or use the function from debugger-plugin, if the file is not (yet) opened.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 17, 2009, 01:26:57 pm
Do you use AddBreakpoint from debugger-plugin or from editor ?

You can use the function from cbEditor, if the source-file is already opened and set notifyDebugger to true or use the function from debugger-plugin, if the file is not (yet) opened.

I totally use the function AddBreakpoint from debuggergdb plugin  debuggerstate.

I will try it now, Thanks very much!
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 17, 2009, 02:10:49 pm
Sorry, I can't figure how to check if the current file was opened in cbEditor. Can someone help me?

here is the patch.( The patch has include some patches from oBFusCATed adding a command entry)


http://sites.google.com/site/studycodeblocks/imagescb/breakpoints.patch This patch has been updated in

https://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2775&group_id=5358


Here is some explanation about this patch:

1, I add two files: breakpointslayout.cpp and breakpointslayout.h(They are similar with code in BrowserTracker plugin)

2, I add some code in doing DebuggerGDB::OnProjectOpened and DebuggerGDB::OnProjectClosed

3, When a project is opened, I will use Addbreakpoints function in debuggerstate structure.

4, when a project is closed, I just read the breakpointsList in debuggerstate, then save them to a xml file.

5, I still can't find a way to notify cbEditor, so, the breakpoints add silently. :(



By the way, I can't upload an attachment any more(upload folder is FULL), can someone help me?  :(

Thanks

Edit:

Here are some ideas:

Code
class ProjectFile  : public BlockAllocated<ProjectFile, 1000>
{
......
        /** If true, the file is open inside an editor. */
        bool editorOpen; // layout info


Can we use "ProjectFile" related method?
Title: Re: Some thoughts on doing breakpoints persistant
Post by: Jenna on June 17, 2009, 02:35:41 pm
You can try:
Code
EditorBase* eb = Manager::Get()->GetEditorManager()->IsOpen(filename);
or
Code
cbEditor* ed = Manager::Get()->GetEditorManager()->IsBuiltinOpen( filename );

Both return NULL if not opened.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 17, 2009, 02:40:34 pm
@jens
Thanks very much! I will try it....So excited!!!

Edit:

Problem solved!!!! Works perfectly! Just change this function to:

Code
// ----------------------------------------------------------------------------
bool BreakpointsLayout::Load(const wxString& filename, DebuggerState * pDebuggerState)
// ----------------------------------------------------------------------------
{
    TiXmlDocument doc;
    if (!TinyXML::LoadDocument(filename, &doc))
        return false;

    TiXmlElement* root;
    TiXmlElement* elem;
    wxString fname;
    ProjectFile* pf;


    root = doc.FirstChildElement("Breakpoints_layout_file");
    if (!root)
    {
        return false;
    }

    elem = root->FirstChildElement("Breakpoint");

    while (elem)
    {
        wxString fname = cbC2U(elem->Attribute("file"));
        ProjectFile* pf;
        if (fname.IsEmpty())
        {
            break;
        }
        else
            pf = m_pProject->GetFileByFilename(fname);

        wxString filenamePath = pf->file.GetFullPath();

        int line = 0;
        if (not elem->QueryIntAttribute("position", &line) == TIXML_SUCCESS)
            break;

        //Manager::Get()->GetLogManager()->DebugLog(F(_T("file='%s', line='%d'"), filenamePath.c_str(), line));


        cbEditor* ed = Manager::Get()->GetEditorManager()->IsBuiltinOpen( filenamePath );
        if (ed==NULL){
            pDebuggerState->AddBreakpoint(filenamePath,line); //add breakpoints silently
            Manager::Get()->GetLogManager()->DebugLog(F(_T("silently add bp file='%s', line='%d'"), filenamePath.c_str(), line));
        }
        else{
            ed->AddBreakpoint(line);
            Manager::Get()->GetLogManager()->DebugLog(F(_T("add bp from editor file='%s', line='%d'"), filenamePath.c_str(), line));

        }
        elem = elem->NextSiblingElement();
    }
    return true;
}//Load



Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 20, 2009, 03:17:16 pm
Hi, every one.
I have finished the finally patch.

Both watches and breakpoints can be persistent with the current project.

I add the patch here:

https://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2775&group_id=5358

Here is the example of a projectname.bps file

Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Debugger_layout_file>
<BreakpointsList>
<Breakpoint file="main.cpp" position="67" />
<Breakpoint file="main.cpp" position="69" />
<Breakpoint file="main.cpp" position="62" />
<Breakpoint file="main.cpp" position="58" />
</BreakpointsList>
<WatchesList>
<Watch variable="abcdefg" />
<Watch variable="llll" />
</WatchesList>
</Debugger_layout_file>


Any comments and enhancements are welcome!!

Thanks. :D
Title: Re: Some thoughts on doing breakpoints persistant
Post by: Jenna on June 20, 2009, 03:44:53 pm
I did not (yet)test it, but what came in my mind:

what about the other attributes of the breakpoints and watches ?

The breakpoints might be data, function or conditional breakpoints (might be more possibilities, I don't know at the moment).
The same is for watches: might be watches as character, hex ..., or as array with begin and count.

Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 20, 2009, 03:53:29 pm
hehe, this is the first step.

I only add codes in debuggerGDB.cpp. For "watches types" and "breakpoints types", things will be more complicated, so, they should be added to the separate cpp and h files.
Title: Re: Some thoughts on doing breakpoints persistant
Post by: MortenMacFly on June 22, 2009, 06:55:10 am
The same is for watches: might be watches as character, hex ..., or as array with begin and count.
Notice that watches can already be saved / loaded (including this info).
Title: Re: Some thoughts on doing breakpoints persistant
Post by: ollydbg on June 22, 2009, 08:11:33 am
The same is for watches: might be watches as character, hex ..., or as array with begin and count.
Notice that watches can already be saved / loaded (including this info).

Where can I find the code? (save watches with other info?)

The only code I can find is:

Code
void DebuggerTree::OnSaveWatchFile(wxCommandEvent& event)
{
    // Verify that there ARE watches to save
    size_t wc = m_Watches.GetCount();
    if (wc<1)
    {
        cbMessageBox(_("There are no watches in the list to save."),
                     _("Save Watches"), wxICON_ERROR);
        return;
    }

    wxString fname;
    wxFileDialog dlg (Manager::Get()->GetAppWindow(),
                    _T("Save debugger watch file"),
                    _T(""),
                    _T(""),
                    _T("Watch files (*.watch)|*.watch|Any file (*)|*"),
                    wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
    PlaceWindow(&dlg);
    if (dlg.ShowModal() != wxID_OK)
        return;

    wxTextFile tf(dlg.GetPath());
    bool bSuccess = false;

    // Create() will fail if the file exist -> must use Open() if file exist
    if (tf.Exists())
    {
        bSuccess = tf.Open();
        if (bSuccess) tf.Clear(); // remove old content (if any)
    }
    else
    {
        bSuccess = tf.Create();
    }

    if (bSuccess)
    {
        // iterate over each watch and write them to the file buffer
        for (size_t i = 0; i < wc; ++i)
        {
            Watch& w = m_Watches[i];
            tf.AddLine(w.keyword);
        }
        tf.Write(); // Write buffer to file
        tf.Close(); // release file handle
    }
    else
        Manager::Get()->GetLogManager()->DebugLog(_T("Error opening debugger watch file: ") + fname);
}

Seems no other info was saved :(
Title: Re: Some thoughts on doing breakpoints persistent
Post by: ollydbg on December 15, 2012, 07:05:51 am
Active this thread :)
What should we do if we want to save all the user setting information in one file, those include:
The setting should be one file for each c::b project.
1, project layout (which file of the project should be opened/shown after loading the project), caret position
2, breakpoints
3, watches
4, bookmarks
5, other user setting dedicated to the project file.

We should unify the interface, but I have no idea how to implement this.

The user setting file should be saved/loaded as the same time as "bool cbProject::SaveLayout() and bool cbProject::LoadLayout()".
Title: Re: Some thoughts on doing breakpoints persistent
Post by: oBFusCATed on December 15, 2012, 09:39:56 am
Two questions:
what will we do with a project opened in a workspace and outside a workspace or in two different workspaces?
Also what about the inactive projects in a workspace?

I'm more in favour of a .user directory next to the workspace file, if there is a workspace of course, else place it next to the project file.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: MortenMacFly on December 15, 2012, 10:01:49 am
I'm more in favour of a .user directory next to the workspace file
Why a directory? Isn't a descriptive file (maybe more) enough?

A general question: We have the project file where we can save stuff in it, right? So what we want to save here is something which is user-dependent and shall not be e.g. committed, right? What about using the concept of the project layout file, rename it to *.user.settings ("user" replaced with the actual user so you can have multiple in parallel) and extend it with the other stuff we want?
Title: Re: Some thoughts on doing breakpoints persistent
Post by: oBFusCATed on December 15, 2012, 10:13:02 am
I want to make it directory in order to make the project/workspace directory a bit more clear.
My idea is to move all useless to the user files there, like the layout, depend, bmarks, etc.
If we choose a single file we will have to redo all current code, which saves user files.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: MortenMacFly on December 15, 2012, 11:38:22 am
If we choose a single file we will have to redo all current code, which saves user files.
We don't have such code yet to my knowledge. My proposal was not to add new files, but to use/tweak what we have. And using ignore patterns for version control avoids the (already) visible clutter. In the end it would be a 1:1 relation between project files and files with meta-data. Having an API in place could also allow plugins to make use of it... How does that sound?
Title: Re: Some thoughts on doing breakpoints persistent
Post by: oBFusCATed on December 15, 2012, 12:14:14 pm
We don't have such code yet to my knowledge.
What about the code used to save .depend, .layout, .bmarks files?

All of them use different format. I was thinking of providing a function like GetUserFilePath(...) which returns a proper folder.
But I've not tried to implement it, yet, because of the workspace problem.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: MortenMacFly on December 15, 2012, 02:39:07 pm
What about the code used to save .depend, .layout, .bmarks files?
Al-right... now I know what you mean. I thought you only think about the .layout stuff and additional stuff.

I was thinking of providing a function like GetUserFilePath(...)
Well what about if you return a proper file instead and simply change the the methods to create its own node in this fiel instead of creating an new one? The file would look then like:

Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_meta_data_file>
  <debugger>
    <bmarks>
    </bmarks>
    <connectivity>
    </connectivity>
  </debugger>
  <core>
    <layout>
    </layout>
    <stuff_from_core_like_project_settings>
    </stuff_from_core_like_project_settings>
  </core>
</CodeBlocks_project_meta_data_file>

Note that with the .depend file it is different: It comes from a 3rd party lib and we cannot change it to something else, nor integrate it,not even move it most likely without changing the depends lib.

...whatever we choose it requires some refactoring, for sure.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: oBFusCATed on December 15, 2012, 02:47:11 pm
This is another option, but it is more limiting, because all files should be saved in xml format.

And yes, some refactoring will be required anyway.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: ollydbg on December 15, 2012, 02:58:03 pm
Well what about if you return a proper file instead and simply change the the methods to create its own node in this fiel instead of creating an new one? The file would look then like:

Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_meta_data_file>
  <debugger>
    <bmarks>
    </bmarks>
    <connectivity>
    </connectivity>
  </debugger>
  <core>
    <layout>
    </layout>
    <stuff_from_core_like_project_settings>
    </stuff_from_core_like_project_settings>
  </core>
</CodeBlocks_project_meta_data_file>


The sdk can have a interface like:
Code
Manager::Get()->GetProjectMetaDataManager(_T("core"))         //Get the "core" Node.
which return a Node pointer, then the client plugins can write and wrote on these Node/blocks.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: oBFusCATed on December 15, 2012, 03:25:06 pm
The sdk can have a interface like:
Code
Manager::Get()->GetProjectMetaDataManager(_T("core"))         //Get the "core" Node.
which return a Node pointer, then the client plugins can write and wrote on these Node/blocks.
Doesn't like.
Title: Re: Some thoughts on doing breakpoints persistent
Post by: ollydbg on December 15, 2012, 03:30:28 pm
The sdk can have a interface like:
Code
Manager::Get()->GetProjectMetaDataManager(_T("core"))         //Get the "core" Node.
which return a Node pointer, then the client plugins can write and wrote on these Node/blocks.
Doesn't like.
:), I'm not good at design interface, so can you give a good way? How can the interface like?
Title: Re: Some thoughts on doing breakpoints persistent
Post by: MortenMacFly on December 15, 2012, 04:13:08 pm
This is another option, but it is more limiting, because all files should be saved in xml format.
Yes, that is a limitation. I understand that this wouldn't be needed for the .user folder. However, the .user folder may not work, too because plugins may require relative files or simply not make use of the API (like the cscope plugin). So you still (most likely will) have clutter. Another case that won't work with XML on the other hand are the build logs in HTML...

Aaargh... we have so many cases... And btw: Talking about the debugger raises another one: What, if we want to have target related temporary settings, like connectivity options per target - that does make sense you know...
Title: Re: Some thoughts on doing breakpoints persistent
Post by: oBFusCATed on December 15, 2012, 04:17:52 pm
Aaargh... we have so many cases... And btw: Talking about the debugger raises another one: What, if we want to have target related temporary settings, like connectivity options per target - that does make sense you know...
It could be saved per target in the file.

About cscope, I suppose the plugin can be modified to generate its files in .user.
The valgrind plugin also generates a xml file, which could be save in .user.
Another benefit of using a directory is that files could be shared/backuped and so on (even if not supported by us :) )