
ABAP already offers an extensive set of standard breaktpoints that can be flexibly applied. You can also create watchpoints which can evaluate the value in a watched variable according to a range of conditions.
Even so, there is always a need for an even more intelligent breakpoint or watchpoint if you are debugging a difficult problem. For example, you may need a custom breakpoint that stops when a particular internal table is read. Or you may need a watchpoint that stops when the current value of a variable differs from its previous value, a test that can't be expressed in a standard watchpoint.
With debugger scripting, you can quickly implement any combination of breakpoint and watchpoint functionality that you might need.
Creating a Custom Breakpoint
Here is a sample program that stops whenever the debugged program reads from a specified internal table. You can see the complete script in transaction SAS. Just load the standard script RSTPDA_SCRIPT_BP_READ_TAB.
*---------------------------------------------------------------------*
* CLASS lcl_debugger_script DEFINITION
*---------------------------------------------------------------------*
*
*---------------------------------------------------------------------*
CLASS lcl_debugger_script DEFINITION INHERITING FROM cl_tpda_script_class_super .
PUBLIC SECTION.
METHODS: prologue REDEFINITION,
init REDEFINITION,
script REDEFINITION,
end REDEFINITION.
PRIVATE SECTION.
DATA range_it TYPE tpda_range_it.
ENDCLASS. "lcl_debugger_script DEFINITION
*---------------------------------------------------------------------*
* CLASS lcl_debugger_script IMPLEMENTATION
*---------------------------------------------------------------------*
*
*---------------------------------------------------------------------*
CLASS lcl_debugger_script IMPLEMENTATION.
METHOD prologue.
*** generate abap_source (source handler for ABAP)
super->prologue( ).
ENDMETHOD. "prolog
METHOD init.
DATA l_cancel TYPE flag.
CALL FUNCTION 'TPDA_SCRIPT_CALL_SEL_SCREEN'
EXPORTING
p_screen = if_tpda_sel_screens=>c_scr_itab
IMPORTING
p_range_it = range_it
p_cancel = l_cancel.
IF l_cancel = abap_true.
MESSAGE s144(tpda) .
RAISE EXCEPTION TYPE cx_tpda_stop_scripting_request.
ELSEIF range_it IS INITIAL.
MESSAGE s144(tpda) .
RAISE EXCEPTION TYPE cx_tpda_stop_scripting_request.
ENDIF.
ENDMETHOD. "init
METHOD script.
DATA: l_itabs_it TYPE cl_tpda_script_scan_itab_read=>ty_it_tables,
l_itab LIKE LINE OF l_itabs_it,
l_scan_object TYPE REF TO cl_tpda_script_scan_itab_read,
l_curr_itab TYPE string.
l_scan_object ?= cl_tpda_script_scan=>scan(
p_program = abap_source->program( )
p_include = abap_source->include( )
p_line = abap_source->line( )
).
l_itabs_it = l_scan_object->it_tables( ).
LOOP AT l_itabs_it INTO l_itab.
IF l_itab IN range_it.
me->break( ).
ENDIF.
ENDLOOP.
ENDMETHOD. "script
ENDCLASS. "lcl_debugger_script IMPLEMENTATION
To use the script, you would do the following:
Start the program to debug in the debugger and choose the Script tab.
Load the script, start it, and enter the name(s) of the internal tables to watch..
Each time the script stops, you can do any debugging that is necessary. You can then decide on the Script tab whether to continue running the script to the next breakpoint or to end the script.
If you reach the end of the program before you end the script, enter the /h OK-Code and press the Back key ( F3) to return control to the debugger session so that you can end the script.
Creating a Custom Watchpoint
Assume that your program is losing lines of an internal table somewhere in a large processing loop. Somehow, lines in the table are being deleted when they should not be.
Here is a script that would let you efficiently localize the problem by stopping when the number of lines in the table decreases. The script is triggered to run by a watchpoint on the number of lines in the table. The script stops at the watchpoint, however, only when the new number of lines in the table is less than it was at the last watchpoint.
The script lets you skip all of the meaningless changes to the number of lines in the table. It stops the program in the debugger only at the change in the variable that you need to see.
*---------------------------------------------------------------------*
* CLASS lcl_debugger_script DEFINITION
*---------------------------------------------------------------------*
*
*---------------------------------------------------------------------*
CLASS lcl_debugger_script DEFINITION INHERITING FROM cl_tpda_script_class_super .
PUBLIC SECTION.
METHODS: prologue REDEFINITION,
init REDEFINITION,
script REDEFINITION,
end REDEFINITION.
PRIVATE SECTION.
DATA saved_count TYPE i.
ENDCLASS. "lcl_debugger_script DEFINITION
*---------------------------------------------------------------------*
* CLASS lcl_debugger_script IMPLEMENTATION
*---------------------------------------------------------------------*
*
*---------------------------------------------------------------------*
CLASS lcl_debugger_script IMPLEMENTATION.
METHOD prologue.
*** generate abap_source (source handler for ABAP)
super->prologue( ).
ENDMETHOD. "prolog
METHOD script.
DATA table_descr TYPE REF TO cl_tpda_script_tabledescr.
DATA l_count TYPE i.
* Use a script wizard function to get a handle
* for accessing the internal table from your script
****************************************************************
*Interface (CLASS = CL_TPDA_SCRIPT_DATA_DESCR / METHOD = FACTORY )
*Importing
* REFERENCE( P_VAR_NAME ) TYPE TPDA_VAR_NAME
*Returning
* VALUE( P_DATADESCR ) TYPE REF TO CL_TPDA_SCRIPT_DATA_DESCR
****************************************************************
table_descr = cl_tpca_script_data_descr=>factory(
p_var_name = 'ITAB' ).
* Get the current line count of the table.
****************************************************************
*Interface (CLASS = CL_TPDA_SCRIPT_TABLEDESCR / METHOD = LINECNT )
*Returning
* VALUE( P_LINES ) TYPE I
****************************************************************
p_lines = table_descr->linecnt( ).
IF l_count < saved_count.
* Break if the line count of the table DECREASES.
me->break( ).
ENDIF.
saved_count = l_count.
ENDMETHOD. "script
ENDCLASS. "lcl_debugger_script IMPLEMENTATION
*----------------
To use the script, you would do the following:
Start the program to debug in the debugger and choose the Script tab.
Load or create the script and trigger it to run at a watchpoint for a change in the number of lines in the internal table. Then start the script.
At each breakpoint triggered by the script, you can do any debugging that is necessary. You can then decide on the Script tab whether to continue running the script to the next breakpoint or to end the script.
If you reach the end of the program before you end the script, enter the /h OK-Code and press the Back key ( F3) to return control to the debugger session so that you can end the script.