PreExecLine: aLine is about to execute; handle current line marker, breakpoints and step into/over/out.
| 79 | |
| 80 | // PreExecLine: aLine is about to execute; handle current line marker, breakpoints and step into/over/out. |
| 81 | int Debugger::PreExecLine(Line *aLine) |
| 82 | { |
| 83 | // Using this->mCurrLine might perform a little better than the alternative, at the expense of a |
| 84 | // small amount of complexity in stack_get (which is only called by request of the debugger client): |
| 85 | // mStack.mTop->line = aLine; |
| 86 | mCurrLine = aLine; |
| 87 | |
| 88 | // Check for a breakpoint on the current line: |
| 89 | Breakpoint *bp = aLine->mBreakpoint; |
| 90 | if (bp && bp->state == BS_Enabled) |
| 91 | { |
| 92 | if (bp->temporary) |
| 93 | { |
| 94 | aLine->mBreakpoint = NULL; |
| 95 | delete bp; |
| 96 | } |
| 97 | return Break(); |
| 98 | } |
| 99 | |
| 100 | if ((mInternalState == DIS_StepInto |
| 101 | || mInternalState == DIS_StepOver && mStack.Depth() <= mContinuationDepth |
| 102 | || mInternalState == DIS_StepOut && mStack.Depth() < mContinuationDepth) // Due to short-circuit boolean evaluation, mStack.Depth() is only evaluated once and only if mInternalState is StepOver or StepOut. |
| 103 | // Although IF/ELSE/LOOP skips its block-begin, standalone/function-body block-begin still gets here; we want to skip it: |
| 104 | && aLine->mActionType != ACT_BLOCK_BEGIN && (aLine->mActionType != ACT_BLOCK_END || aLine->mAttribute) // Ignore { and }; except for function-end, since we want to break there after a "return" to inspect variables while they're still in scope. |
| 105 | && aLine->mLineNumber) // Some scripts (i.e. LowLevel/code.ahk) use mLineNumber==0 to indicate the Line has been generated and injected by the script. |
| 106 | { |
| 107 | return Break(); |
| 108 | } |
| 109 | |
| 110 | // Check if a command was sent asynchronously (while the script was running). |
| 111 | // Such commands may also be detected via the AHK_CHECK_DEBUGGER message, |
| 112 | // but if the program is checking for messages infrequently or not at all, |
| 113 | // the check here is needed to ensure the debugger is responsive. |
| 114 | if (HasPendingCommand()) |
| 115 | { |
| 116 | // A command was sent asynchronously. |
| 117 | return ProcessCommands(); |
| 118 | } |
| 119 | |
| 120 | return DEBUGGER_E_OK; |
| 121 | } |
| 122 | |
| 123 | |
| 124 | bool Debugger::HasPendingCommand() |
no test coverage detected