I have a problem with a user exit where I need to access a table specifically CHECK_CATSDB that is three levels below the user exit 3 in CATS. This table cannot be modified unless I can access the stack memory directly. I would prefer this than having to modify the code to do the same.
I have looked into the system call ABAP_CALLSTACK but this only returnes the stack call sequence I need something more direct like SAPCORE but I don't know how to access the table at the specific level of the stack. Anyone checked that out yet by figuring what fm SYSTEM_CALLSTACK is doing?
REPORT ztest. DATA: gt_test TYPE TABLE OF char255, gs_test TYPE char255.. DO 10 TIMES. gs_test=Root Root Root Root. APPEND gs_test TO gt_test. ENDDO. PERFORM my_form1. FORM my_form1. DATA: lt_test TYPE TABLE OF char255, ls_test TYPE char255.. DO 10 TIMES. ls_test=my_form1 my_form1 my_form1. APPEND ls_test TO lt_test. ENDDO. PERFORM my_form2. ENDFORM. FORM my_form. * accessing the root memory for globals is easy even if it is in other calling programs FIELD-SYMBOLS: <lt_test> TYPE TABLE. ASSIGN ((ZTEST)GT_TEST) TO <lt_test> * problem reading local data from my_form1 FIELD-SYMBOLS: <lt_test1> TYPE TABLE. ASSIGN ((ZTEST)??????) TO <lt_test1> IMPORT <lt_test1> FROM MEMORY ID ???. ENDFORM.
Any hints are very welcome.
Edited by: Andreas Mau on May 17, 2008 12:41 AM
Edited by: Andreas Mau on May 17, 2008 12:45 AM
honestly I do not think that it is good idea to play with stack. I think it is even not possible in ABAP. ABAP is higher level language and I really appreciate it (this is not C and even in C it is not good idea). I know that my comment will not help you to solve problem
Thanks for you reply but my problem belongs to 1% of SAP's inefficient solutions and shortcomings for user exits. Especially in CATS where SAP supports user exits to check user input values but has missed the point that values could be passed back to the calling program. This is just one of a number of user exits I have to fight with that are inefficient and lack to fit business requirement details. So I would appreciate it if you could respond with the corresponding code hint. Of course I can circumvent the problem always with a core mod but this is even uglier.
Please check this peace info ,might assist you.
SYSTEM_CALLSTACK to display the call hierarchy (for example, in error handling).
Using this function, you can show this extra information to help analyze the problem.
Example of using the system callstack function
DATA: ta_callstack TYPE sys_callst,
wa_callstack LIKE LINE OF ta_callstack.
*& Form call_routine_1
*& Form call_routine_2
CALL FUNCTION 'SYSTEM_CALLSTACK'
et_callstack = ta_callstack.
LOOP AT ta_callstack INTO wa_callstack.
WRITE: / wa_callstack-progname,
The output will look like this:
ZZ_SYSTEM_CALLSTACK FORM CALL_ROUTINE_2
ZZ_SYSTEM_CALLSTACK FORM CALL_ROUTINE_1
ZZ_SYSTEM_CALLSTACK EVENT START-OF-SELECTION
Getting the current call stack
Sometimes, especially inside user-exits that are called in several different places, we need to know where it was called to decide what to do.
Some fields in the "sy" structure can be useful for this: sy-tcode (transaction), sy-repid (current main program), sy-cprog, sy-xprog, sy-xform, etc.
This info might not be enough, however: we might need to know if we are inside a given form, for example, even if we might be several levels below (the form called another form, which in turn called another form, that then called a function, that called our exit..).
To know this, we need to get the current call stack. In debug mode, we can see it by clicking the button "Calls". Getting that info in our programs is just as easy: just use function SYSTEM_CALLSTACK, and you'll get an internal table with that same information.
Thanks for the reply. As I have noted in my original message this is what I have and know to get the system call stack, what I need to know is how to get to to the corresponding memory ID of the call stack at any given level. One can get the table information in debug mode in the system areas->abap memory menu.for ITAB-PAGES. This will list all table IDs and double click on the corresponding table ID will show the table content. I need to know how the code behind this looks like to access any table in the corresponding stack level.
If you can't access the variables defined higher in the stack, (which as has been said seems an inherently dangerous thing to do), then it looks like modification is the only way. You could use implicit enhancements. If the code three levels higher is a class attribute, you could define a setter to set its value - even if it is private.
I am sorry to answer to a so old post (May 2008), but I've got a clue for other people who have the same question :
As Matt said (in March 2009 ), using implicit enhancement options is possible, and I have also another ugly way to do it (it works in release 7.0), which allows a direct read/write access to a local variable, provided that the routine FORM1 is in the stack of course :
1) Implement an implicit enhancement option somewhere in the program containing FORM1 (PROG1) so that to execute it the soonest possible after PROG1 is loaded :
TYPES ty_zz_t_char255 TYPE TABLE OF char255. FIELD-SYMBOLS <gt_zz_char255> TYPE ty_zz_t_char255. DATA gt_zz_char255_dummy TYPE ty_zz_t_char255. ASSIGN gt_zz_char255_dummy TO <gt_zz_char255>.
The reason why I use a dummy variable is explained in step 3 below.
2) Implement an implicit enhancement option at the beginning of FORM1, assign the local variable LT_TEST to the global field symbol (note that you must not do ASSIGN lt_test ... because the implicit enhancement point is at the beginning of the form and so LT_TEST is not known at compile time and would not be accepted at activation)
ASSIGN ('LT_TEST') TO <gt_zz_char255>.
3) In your program (FORM2) :
FIELD-SYMBOLS: <lt_char255> TYPE TABLE OF char255. ASSIGN ('(PROG1)<GT_ZZ_CHAR255>') TO <lt_char255>.
Be careful here, the ASSIGN statement dumps (GETWA_NOT_ASSIGNED) if FORM1 is not in the stack (I mean it dumps when FORM2 is not called by FORM1 but by another routine, which is itself not called by FORM1, or in other words, FORM1 does not call FORM2 directly or indirectly). The only way to prevent this is to be sure that (PROG1)<GT_ZZ_CHAR255> is always assigned, it's why I used global variable gt_zz_char255_dummy in PROG1.
Again I advise doing that only as the last solution, and it must be considered as a modification of the standard, as said in [ABAP documentation|http://help.sap.com/abapdocu_70/en/ABAPASSIGN_MEM_AREA_DYNAMIC_DOBJ.htm]
I was just wondering if you discovered any fix for this. I too have an issue where I have need of making an enhancement to some standard function module code that is multiple call layers deep from the orignial program/report.
I thought I was going crazy because the first variable I needed to read happened to be at the calling/root level and I had no issues using the ASSIGN (prog)variable approach. However, just one call level up from where I need to make my change the same approach does not work...
If you have found a way to do this without putting an enhancement higher up to basically save to memory the variables you need I would appreciate hearing about it.
Sorry for th elate reply, but no. I used an enhancement point in the routine and passed it through the session memory, at leats the enhancement point does not require a developer key and also keeps being inclued in any updates/upgrades. I know there is a way using the ABAP system calls but without docu it is virtually impossible to read stack variables. That this shoul actually be possible one can gather from the fact that the debugger can go back in any level opf the stack and all we would need is something similar.
It gets even worse with the new portal session memory when it is unknown what th eother session is and how to find it.