Here is one for you. Although such a language construction does not make much sense I would like to know why the nested LOOP AT SCREEN cause infinite loop (recursion?).
Let us take the following simple program.
REPORT yyy.
PARAMETERS:
p_x1 TYPE abap_bool.
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
BREAK-POINT.
ENDLOOP.
The BREAK-POINT statement will be executed only 4 times. This leads to an assumption that such a nested loop would run 16 times. Instead the below mentioned program runs forever and ends with a timeout exception.
REPORT yyy.
PARAMETERS:
p_x1 TYPE abap_bool.
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
LOOP AT SCREEN.
ASSERT 1 = 1.
ENDLOOP.
ENDLOOP.
It looks like nesting LOOP AT SCREEN causes either an infinite loop or some kind of an infinite recursion.
Why is it so? Is it documented somewhere? The extended check does not report anything regarding the loop. The same applies to Code Inspector as well.
EDIT
I have also checked whether this is a general problem for internal tables with a header line. It seems not.
REPORT YYY.
DATA: gt_t000 TYPE t000 OCCURS 10 WITH HEADER LINE.
START-OF-SELECTION.
SELECT * FROM t000
INTO TABLE gt_t000[].
LOOP AT gt_t000.
LOOP AT gt_t000.
WRITE / gt_t000-mandt.
ENDLOOP.
ENDLOOP.
Related
In case a user sets a parameter to skip the processing of the logical database it should be skipped. But unfortunately, I can't find a way, since whatever I try the reports ends completly. Example of what I tried:
REPORT zxxxx.
TABLES: pernr.
NODES peras.
PARAMETERS: p_skip AS CHECKBOX.
START-OF-SELECTION.
IF p_skip = abap_true.
RETURN. " Also tried EXIT.
ENDIF.
GET peras.
WRITE 'ABC'.
end-of-selection.
WRITE 'test'.
My expectation was that the Report jumps directly to "END-OF-SELECTION", but it doesn't.
What statement do I need to use here? Or is there a workaround? (Otherwise I have to write the logic for the LDB myself)
The STOP statement has to be used, if you want to jump directly to END-OF-SELECTION.
IF p_skip = abap_true.
STOP.
ENDIF.
https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapstop.htm
It might be worth mentioning that logical databases are already obsolete.
As I rarely loop into a field symbol, I often forget to use ASSIGNING instead of INTO which will promptly cause an abend. Is there a valid use of INTO with <fieldsymbol> or is this something that the syntax checker really ought to catch?
LOOP...INTO is perfectly valid but it will work differently. LOOP...INTO transports the values to the structure provided but ASSIGNING assigns the field symbol to the actual table rows.
The only difference is if you are going to change the table contents. See the following:
* Changes all entries in the CARRID column of lt_flights to 50.
LOOP AT lt_flights ASSIGNING <flight>.
<flight>-carrid = 50.
ENDLOOP.
* Does not change the entries in lt_flights (MODIFY...FROM would be required).
ASSIGN <flight> TO ls_flight.
LOOP AT lt_flights INTO <flight>.
<flight>-carrid = 50.
ENDLOOP.
LOOP...INTO with a field symbol would be useless unless you had some kind of dynamic programming requirement.
It is valid when <fieldsymbol> was previously assigned to a structure which has the type of the lines of the table you loop over.
It is a perfectly valid statement:
APPEND INITIAL LINE TO lt_foo ASSIGNING <ls_foo>.
READ TABLE lt_bar INTO <ls_foo> INDEX 1.
A field symbol just takes the place of a variable - at almost any point - so the syntax check can't flag this as invalid. It might issue a warning, though...
I am trying to debug code that typically functions properly and has been in production for a while, but has some errors associated with particular case runs.
I have a class called "Guarantee", and a variable / object, "myDem", which is of that class. The class has an associated function called "NumberOfGuaranteeDays". The first image given below shows a Long variable called "numRows" being assigned to this function call on "myDem". When this assigment is made -- and, therefore, the "NumberOfGuaranteeDays" function is called -- I receive an Overflow error.
After the function call "NumberOfGuaranteeDays" is run, which is a fairly complex call with many sub-functions itself, then class attempts to terminate itself, and return the value (the number of days, which is an integer... in this case it's 32561). It is during this termination step and the assignment of "numRows" to the value 32561, when the error occurs.
Here I simply demonstrate that the very next step within the code, if I step through it, is where the error message is returned back to me.
Finally I wanted to provide "proof" that the value assigned to "numRows" is 32561, of type Integer, which can acceptably be assigned to a Long. Note in the far right in the watch part of the window, the value "res" is the value which is returned from the "NumberOfGuaranteeDays" call, which is then assigned to the variable "numRows".
As far as I can tell, there are only 2 possibilities for why a crash can be occurring:
There is an error in the attempt to terminate the class. I don't understand how this could lead to an "overflow" error, though.
There is an error in the assignment of the value calculated from "NumberOfGuaranteeDays" to the variable "numRows". This sort of assignment could potentially have an overflow, but not in this case. The return from "NumberOfGuaranteeDays", which is the "res" integer set at 32561, is assigned to "numRows", which is a Long.
So, since neither of these possibilities that I can imagine make sense, I figure there must be another possibility I cannot see. Thank you all in advance for the help!
I opted to put in cut & pasted images instead of writing as code because so much of what's critical to understanding the steps is seeing "proof" of where I am in the debugging stages. If actual code snippets would help, let me know.
Thank you!
Mike
Is it possible to dynamically create parameters from table entries?
For example like this:
SELECTION-SCREEN BEGIN OF BLOCK example WITH TITLE text-01
LOOP AT example_internal_table INTO example_workarea
IF example_workarea-field = criteria.
PARAMETERS: (example_workareafield) AS CHECKBOX.
ENDIF.
ENDLOOP.
SELECTION-SCREEN END OF BLOCK example.
The code snippet above throws the error that example-workarea-field is not a constant. Does this mean it isn't possible to dynamically declare parameters or am I just doing it wrong? Thanks
Correct. PARAMETERS statements compile into selection screens at compile time, not at runtime. Therefore you cannot do what you want in the way you have proposed.
However, it is possible to have some form of dynamic screens.
Look at the answers to this question: For the I/O fields in a normal ABAP screen, can i get them to behave like a SELECT-OPTIONS?
This gives you two starting points: The use of subscreens, which you can call dynamically, or the use of FREE_SELECTIONS_INIT as examples.
Depending on how crazy you are about this, you can also investigate:
http://help.sap.com/abapdocu_702/en/abenabap_language_dynamic.htm
You could load the DYNPRO and dynamically change the screen, activate and then run a report that calls the changed screen.
This is of course a different approach from using PARAMETERS and should only be used for pet projects, not real production code as these statements are for internal use. I believe this is the approach that SE16 uses when it generates a selection screen for a table.
In a LLVM pass, I'd like to record the loop trip count of a loop. One part I did was inserting a function call before the terminator of the header block of each loop. I found that this method did not work well, because if a loop has n iterations, the header block will be executed n+1 times. This fact holds for "for" and "while" loop, but it does not hold for "do while" loop. I insert the function call to the second block of "for" and "while" loops, and to the first block of "do while" loops. This works only if I know a priori the kind the targeted loop, which is impossible through purely bitcode. My question is: is there a universal way (handling all kinds of loops) to insert a function call, which will be called exactly the same times as the number of iterations.
Put the function call at the start of the body of the loop. Why are you trying to put it in the header?
for (...) {
increment_trip_count();
...
}
If you insert the function call in the beginning of the loop body, you will get the correct count.