Package org.epic.debug.db

Source Code of org.epic.debug.db.StackFrame

package org.epic.debug.db;

import java.io.IOException;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.*;
import org.epic.debug.PerlDebugPlugin;
import org.epic.debug.ui.action.*;

public class StackFrame extends DebugElement implements IStackFrame
{
    private static final IRegisterGroup[] NO_REGISTER_GROUPS =
        new IRegisterGroup[0];
   
    private static final String DB_DUMP_LOCAL_VARS;   
    private static final String DB_DUMP_GLOBAL_VARS;
    private static final String DB_DUMP_INTERNAL_VARS;
   
    private static final Set PERL_INTERNAL_VARS = initInternalVars();

    private PerlVariable[] vars;
    private final PerlDebugThread thread;
    private final IPath path;
    private final IPath localPath;
    private final int lineNumber;
    private final DebuggerInterface db;
    private StackFrame previous;
    private final int frameIndex; // 0 = top stack frame, 1 = one below...
    private final HashMap rememberedVariables; // only for RFE 1708299
   
    static
    {
        DB_DUMP_LOCAL_VARS = HelperScript.load("dump_local_vars.pl");
        DB_DUMP_GLOBAL_VARS = HelperScript.load("dump_global_vars.pl");
        DB_DUMP_INTERNAL_VARS = HelperScript.load("dump_internal_vars.pl");
    }
   
    public StackFrame(
        PerlDebugThread thread,
        IPath path,
        int lineNumber,
        IPath localPath,
        DebuggerInterface db,
        StackFrame previous,
        int frameIndex) throws DebugException
    {
        super(thread.getDebugTarget());
       
        if (previous != null) previous.previous = null; // conserve memory

        this.thread = thread;
        this.path = path;
        this.localPath = localPath;
        this.lineNumber = lineNumber;
        this.db = db;
        this.previous = previous;
        this.frameIndex = frameIndex;
        this.rememberedVariables = new HashMap();
       
        if (HighlightVarUpdatesActionDelegate.getPreferenceValue())
            getVariables();
    }

    public boolean canResume()
    {
        return thread.canResume();
    }

    public boolean canStepInto()
    {
        return thread.canStepInto();
    }

    public boolean canStepOver()
    {
        return thread.canStepOver();
    }

    public boolean canStepReturn()
    {
        return thread.canStepReturn();
    }

    public boolean canSuspend()
    {
        return thread.canSuspend();
    }

    public boolean canTerminate()
    {
        return thread.canTerminate();
    }
   
    public void discardCachedVars()
    {
        this.vars = null;
        rememberedVariables.clear();
        fireChangeEvent(DebugEvent.CONTENT);
    }

    public int getCharEnd() throws DebugException
    {
        return -1;
    }

    public int getCharStart() throws DebugException
    {
        return -1;
    }
   
    public int getFrameIndex()
    {
        return frameIndex;
    }

    public int getLineNumber() throws DebugException
    {
        return lineNumber;
    }

    /**
     * @return path of the stack frame, valid in the file system
     *         of EPIC, or null if the path could not be resolved
     */
    public IPath getLocalPath()
    {
        return localPath;
    }

    public String getModelIdentifier()
    {
        return thread.getModelIdentifier();
    }

    public String getName() throws DebugException
    {
        return path.lastSegment() + "[line: " + Integer.toString(lineNumber) + "]";
    }

    /**
     * @return path of the stack frame, valid in the file system
     *         of "perl -d"; this path is not necessarily local to EPIC
     */
    public IPath getPath()
    {
        return path;
    }
   
    public PerlDebugThread getPerlThread()
    {
        return thread;
    }
   
    /**
     * @return the given variable as it was on the previous suspend or
     *         null if it is not remembered
     */
    public PerlVariable getPreviousVariable(PerlVariable var)
    {
        if (previous == null) return null;
        return previous.getRememberedVariable(
            var.getDumpedEntity().getAddress());
    }
   
    public IRegisterGroup[] getRegisterGroups() throws DebugException
    {
        return NO_REGISTER_GROUPS;
    }

    public IThread getThread()
    {
        return thread;
    }

    public IVariable[] getVariables() throws DebugException
    {
        if (!thread.isSuspended()) return new IVariable[0];
        if (this.vars == null)
        {       
            try
            {
                List vars = new ArrayList();
               
                if (ShowPerlInternalVariableActionDelegate.getPreferenceValue()) dumpInternalVars(vars);
                if (ShowGlobalVariableActionDelegate.getPreferenceValue()) dumpGlobalVars(vars);
                if (ShowLocalVariableActionDelegate.getPreferenceValue() && db.hasPadWalker()) dumpLocalVars(vars);
                this.vars = (PerlVariable[]) vars.toArray(new PerlVariable[vars.size()]);

                if (HighlightVarUpdatesActionDelegate.getPreferenceValue() &&
                    rememberedVariables.isEmpty()) rememberVariables();
               
                fireChangeEvent(DebugEvent.CONTENT);
            }
            catch (IOException e)
            {
                throw new DebugException(new Status(
                    IStatus.ERROR,
                    PerlDebugPlugin.getUniqueIdentifier(),
                    IStatus.OK,
                    "An error occurred while retrieving variables from the debugger process",
                    e));
            }
        }
        return this.vars;
    }

    public boolean hasRegisterGroups() throws DebugException
    {
        return false;
    }

    public boolean hasVariables() throws DebugException
    {
        return true;
    }

    public boolean isStepping()
    {
        return thread.isStepping();
    }

    public boolean isSuspended()
    {
        return thread.isSuspended();
    }

    public boolean isTerminated()
    {
        return thread.isTerminated();
    }

    public void resume() throws DebugException
    {
        thread.resume();
    }

    public void stepInto() throws DebugException
    {
        thread.stepInto();
    }

    public void stepOver() throws DebugException
    {
        thread.stepOver();
    }

    public void stepReturn() throws DebugException
    {
        thread.stepReturn();
    }

    public void suspend() throws DebugException
    {
        thread.suspend();
    }

    public void terminate() throws DebugException
    {
        thread.terminate();
    }
   
    private void dumpGlobalVars(List vars) throws IOException, DebugException
    {
        String globalVarsString = db.eval(DB_DUMP_GLOBAL_VARS);
        if (globalVarsString == null) return;
       
        try
        {
            DumpedEntityReader r = new DumpedEntityReader(globalVarsString);
            while (r.hasMoreEntities())
            {
                DumpedEntity ent = r.nextEntity();
                if (!PERL_INTERNAL_VARS.contains(ent.getName()))
                    vars.add(new PackageVariable(db, this, ent));
            }
        }
        catch (Exception e)
        {
            PerlDebugPlugin.log(e);
            throw new DebugException(new Status(
                Status.ERROR,
                PerlDebugPlugin.getUniqueIdentifier(),
                Status.OK,
                "An error occurred while dumping global variables; " +
                "contents of the Variables view may become invalid",
                e));
        }
    }

    private void dumpInternalVars(List vars) throws IOException, DebugException
    {
        String internalVarsString = db.eval(DB_DUMP_INTERNAL_VARS);
        if (internalVarsString == null) return;
       
        try
        {
            DumpedEntityReader r = new DumpedEntityReader(internalVarsString);
            while (r.hasMoreEntities())
            {
                DumpedEntity ent = r.nextEntity();
                if (PERL_INTERNAL_VARS.contains(ent.getName()))
                    vars.add(new PackageVariable(db, this, ent));
            }
        }
        catch (Exception e)
        {
            PerlDebugPlugin.log(e);
            throw new DebugException(new Status(
                Status.ERROR,
                PerlDebugPlugin.getUniqueIdentifier(),
                Status.OK,
                "An error occurred while dumping Perl internal variables; " +
                "contents of the Variables view may become invalid",
                e));
        }
    }

    private void dumpLocalVars(List vars) throws IOException, DebugException
    {        
        String code = HelperScript.replace(
            DB_DUMP_LOCAL_VARS,
            "#SET_OFFSET#",
            "my $offset = " + frameIndex + ";");

        String localVarsString = db.eval(code);
        if (localVarsString == null) return;
       
        try
        {       
            DumpedEntityReader r = new DumpedEntityReader(localVarsString);               
            while (r.hasMoreEntities())
            {
                vars.add(new LexicalVariable(
                    db,
                    this,
                    r.nextEntity()));
            }
        }
        catch (Exception e)
        {
            throw new DebugException(new Status(
                Status.ERROR,
                PerlDebugPlugin.getUniqueIdentifier(),
                Status.OK,
                "An error occurred while dumping local variables; " +
                "contents of the Variables view may become invalid",
                e));
        }
    }
   
    private PerlVariable getRememberedVariable(String addr)
    {
        return (PerlVariable) rememberedVariables.get(addr);
    }
   
    private static Set initInternalVars()
    {
        ResourceBundle rb = ResourceBundle.getBundle("org.epic.debug.perlIntVars");
        Enumeration e = rb.getKeys();
        Set vars = new HashSet();
        while (e.hasMoreElements()) vars.add(e.nextElement());
        return vars;
    }
   
    private void rememberVariables() throws DebugException
    {
        LinkedList queue = new LinkedList();
        queue.add(this.vars);
       
        while (!queue.isEmpty())
        {
            IVariable[] vars = (IVariable[]) queue.removeFirst();
       
            for (int i = 0; i < vars.length; i++)
            {
                if (!(vars[i] instanceof PerlVariable))
                    continue; // could be an ArraySlice
               
                PerlVariable var = (PerlVariable) vars[i];
                String addr = var.getDumpedEntity().getAddress();
               
                if (rememberedVariables.put(addr, var) == null &&
                    var.getValue().hasVariables())
                {
                    queue.add(var.getValue().getVariables());
                }
            }
        }
    }
}
TOP

Related Classes of org.epic.debug.db.StackFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.