Quoting Bert Wesarg <[EMAIL PROTECTED]>:

> This is my proposal for fixing several issues with the handling of compiled
> macro programs.
>
> The first is a memory leak in source/macro.c::readCheckMacroString(), if we
> the caller wants to parse only the macro, i.e. passing runWindow == NULL.
> This was reported as SF BUG#2078867.
Still haven't tried this out.

> The second is more subtile: if a macro function definition overwrites a
> previously one we unconditionaly free the old program.  But this old
> program
> is may be currently in use.  To solve this I have introduced a reference
> count
> for the program and FreeProgram() really releases the program only if this
> drops to zero.  To track references to the program it is needed to put the
> program pointer into the stack frame and increment the reference count.
>
> There are currently 3 places were we build up a stacke frame, each needs
> different handling of the program pointer:
>
> 1) ExecuteMacro():
>    The caller is already responsible for freeing the prog (its runMacro()).
>    Therefore we put a NULL pointer for the prog into the frame.
>
> 2) RunMacroAsSubrCall():
>    Here the caller passes the reference count to this function, so we don't
>    need to increment the reference.
>    The callers are runMacro() and readCheckMacroString().
>
> 3) callSubroutine():
>    This is the usual usage: increment the reference and put it into the
> stack
>    frame.

Your patch ups the refcount on function call and lowers it on return. A
great improvement. However, you don't deal with a macro crash. This should
do the lowering (FreeMacro()) for every frame still in the stack before
freeing it.

BTW did you try my macro-bug-location tracker yet? I've implemented a
built-in array variable called $failure containing the last crash's error
message, its invoking window (document), focus window, current function,
where this is defined (menu entry/macro file) and textual position of the
offending statement. Another new built-in, edit_macro(), allows you to open
a macro menu definition and position the cursor in its text. (You can use
existing functions to open a macro file.) This means you can write a macro
which will take you to the offending code directly!

For example, the macro:

  dialog(2 + 1 / 0)

crashes with division by zero. $failure gives text positions 11 to 16 (with
'd' at position 0), so you highlight the operator and arguments causing the
crash as follows:
  err = $failure
  if (err.menu != "") {
    edit_macro(err.menu, err.menu_item, err.start, err.end)
    dialog("Error calling " err.menu " entry " err.menu_item "\n" \
           "from window " err.called_from "\n" \
           "Error was:\n" err.error)
  }
(The above doesn't check $failure for valid content; so if you run it before
any failure occurs, it'll fail. Run it a second time and it'll identify the
problem as the array key ".menu" in the second line.)

Step one of built-in macro debugging now works...

The "whole works" tarball is here:
http://ajbj.free.fr/nedit/neditHome/neditHome-2008-09-19.tar.gz

You'll see that parse.y has a whole load of extra stuff to support position
tracking. If you have a moment, give it a go.

Tony
-- 
NEdit Develop mailing list - [email protected]
http://www.nedit.org/mailman/listinfo/develop

Reply via email to