Problem solve Get help with specific problems with your technologies, process and projects.

Show nesting in ABAP code

Copy and paste the attached function module-code to create a utility to show you how your ABAP is nested.

Copy and paste the attached function module-code to create a utility to show you how your ABAP is nested. Your code should NOT start in column 1 and Pretty Printer indentation is expected.

Shown below is:
1) Sample output
2) Function module
3) Sample program to invoke function module

Type ZCDF_T_PGM_TEXT is a table type definition, standard table, default key, with structure ZCDF_PGM_TEXT that has a single field called txt that is character, length 80.

The code was written in 4.6C. 4.7 users might want to add the TRY command.

Question/comments? I can be reached at cfolwell@csc.com.
1) 
FORM any_form.
  IF this = true.
  | CASE x.
  | ] WHEN '1'.
  | ] WHEN '2'.
  | ] [ statement.
  | ] [ IF that = true.
  | ] [ } statement.
  | ] [ } statement.
  | ] [ } statement.
  | ] [ } CASE t.
  | ] [ } { WHEN OTHERS.
  | ] [ } ENDCASE.
  | ] [ ENDIF.
  | ] WHEN '3'.
  | ] [ statement.
  | ] [ statement.
  | ] WHEN OTHERS.
  | ENDCASE.
  ENDIF.
ENDFORM.

2)
FUNCTION z_cdf_lineup_commands .
*"----------------------------------------------------------------------
*"*"Local interface:
*"  IMPORTING
*"     VALUE(IP_LINEUP_TXT) TYPE  C DEFAULT '|][}{'
*"  CHANGING
*"     REFERENCE(CP_PGM_TEXT) TYPE  ZCDF_T_PGM_TEXT
*"----------------------------------------------------------------------

  DATA:
    lw_nest_ind(1)     TYPE c, "nest character needed?
    lw_overlay_txt(80) TYPE c, "line of nesting markings
    lw_txt_len_num     TYPE i, "length of marking chars
    lw_char_ofs_num    TYPE i, "offset of nesting character to use
    lw_cmnd_ofs_num    TYPE i, "offset of SAP command of interest
    lw_deep_num        TYPE i. "how many nested levels deep?

  FIELD-SYMBOLS:
    <l_pgm_line> TYPE zcdf_pgm_text.

* Find first space, then sy-fdpos tells length of data.

  IF ip_lineup_txt CA '# #'.

    lw_txt_len_num = sy-fdpos.

  ELSE.  "no blanks

    DESCRIBE FIELD ip_lineup_txt
      LENGTH lw_txt_len_num.

  ENDIF.

* LOOP thru program text and add nesting markings.

  LOOP AT cp_pgm_text
    ASSIGNING <l_pgm_line>.

*   Avoid comment lines.

    IF <l_pgm_line>-txt(1) NE '*'.

*     Find first command on line.
*      Only a single comand per line
*      The command cannot start in column 1, must be
*      in a processing block.

      IF <l_pgm_line>-txt CS ' IF '        OR
         <l_pgm_line>-txt CS ' CASE '      OR
         <l_pgm_line>-txt CS ' LOOP '      OR
         <l_pgm_line>-txt CS ' LOOP. '     OR
         <l_pgm_line>-txt CS ' SELECT '    OR
         <l_pgm_line>-txt CS ' CATCH '     OR
         <l_pgm_line>-txt CS ' DEFINE '    OR
         <l_pgm_line>-txt CS ' TRY '       OR
         <l_pgm_line>-txt CS ' BEGIN OF '  OR
         <l_pgm_line>-txt CS ' WHILE '.

*       Save offset of the command without leading space.

        lw_cmnd_ofs_num = sy-fdpos + 1.

*       Avoid command in a line ending comment.  First get the offset
*        of the start of the comment if any.  If found, sy-fdpos
*        will contain the offset.  If not found, sy-fdpos is set
*        to the length of the text.

        IF <l_pgm_line>-txt CS '"'.
        ENDIF.

*       Only continue if the command was found before the ".

        IF lw_cmnd_ofs_num < sy-fdpos.

          lw_nest_ind = 'X'.

*         Special handling for SELECT.  Some versions of SELECT are
*          NOT loops, for example SELECT SINGLE and
*          SELECT...INTO TABLE.  If not a loop, then no nesting
*          mark required.

          IF <l_pgm_line>-txt+lw_cmnd_ofs_num(6) = 'SELECT'.

            lw_nest_ind = space.

            PERFORM check_select_command
              USING cp_pgm_text
                    sy-tabix
              CHANGING lw_nest_ind.

          ENDIF.

*         Add nesting character if needed.

          IF lw_nest_ind = 'X'.

            lw_deep_num      = lw_deep_num + 1.
            lw_char_ofs_num  = ( lw_deep_num - 1 ) MOD lw_txt_len_num.

*           If the offset has become negative,
*            something strange has happened.  For example, this can
*            happen if IFs are not indented properly.
*            Avoid negative offsets.

            IF lw_char_ofs_num < 0.
              lw_char_ofs_num = 0.
            ENDIF.

*           Set marking in overlay line.

            lw_overlay_txt+lw_cmnd_ofs_num(1) =
              ip_lineup_txt+lw_char_ofs_num(1).

*           Special handling for CASE.  WHEN must follow so provide for
*            a marking of WHEN.

            IF <l_pgm_line>-txt+lw_cmnd_ofs_num(4) = 'CASE'.

              lw_deep_num      = lw_deep_num + 1.
              lw_char_ofs_num  = ( lw_deep_num - 1 ) MOD lw_txt_len_num.

*             If the offset has become negative,
*              something strange has happened.  For example, this can
*              happen if IFs are not indented properly.
*              Avoid negative offsets.

              IF lw_char_ofs_num < 0.
                lw_char_ofs_num = 0.
              ENDIF.

*             Set marking in overlay line for upcoming WHEN statement.
*              Assumption is that indentation is 2 characters.

              lw_cmnd_ofs_num = lw_cmnd_ofs_num + 2.

              lw_overlay_txt+lw_cmnd_ofs_num(1) =
                ip_lineup_txt+lw_char_ofs_num(1).

            ENDIF.

          ENDIF.

        ENDIF.

      ENDIF.

*     Now check for ending commands.
*      Starting and ending commands on the same line are supported.
*      Multiple commands on a line are not supported.

      IF <l_pgm_line>-txt CS ' ENDIF. '              OR
         <l_pgm_line>-txt CS ' ENDCASE. '            OR
         <l_pgm_line>-txt CS ' ENDLOOP. '            OR
         <l_pgm_line>-txt CS ' ENDSELECT. '          OR
         <l_pgm_line>-txt CS ' ENDCATCH. '           OR
         <l_pgm_line>-txt CS ' ENDTRY. '             OR
         <l_pgm_line>-txt CS ' END-OF_DEFINITION. '  OR
         <l_pgm_line>-txt CS ' END OF '              OR
         <l_pgm_line>-txt CS ' ENDWHILE. '.

*       Save offset of the command without leading space.

        lw_cmnd_ofs_num = sy-fdpos + 1.

*       Avoid ending command in a line ending comment.

        IF <l_pgm_line>-txt CS '"'.
        ENDIF.

*       Only continue if the ending command was found before the ".

        IF lw_cmnd_ofs_num < sy-fdpos.

*         Find the current end of the overlay line.

          IF lw_overlay_txt CP '*# '.

            lw_char_ofs_num = sy-fdpos - 1.

*           Something strange has happened.  Avoid negative offsets.

            IF lw_char_ofs_num < 0.
              lw_char_ofs_num = 0.
            ENDIF.

*           Remove marking (+ everything to the right)
*            from overlay line.

            lw_overlay_txt+lw_char_ofs_num = space.

            lw_deep_num = lw_deep_num - 1.

*           Special handling for ENDCASE. When CASE found, both
*            CASE and WHEN were marked. Now for ENDCASE, undo
*            mark for both CASE and WHEN.

            IF <l_pgm_line>-txt+lw_cmnd_ofs_num(7) = 'ENDCASE'.

*             Find current end of overlay line.

              IF lw_overlay_txt CP '*# '.

                lw_char_ofs_num = sy-fdpos - 1.

*               Something strange has happened.  Avoid negative offsets.

                IF lw_char_ofs_num < 0.
                  lw_char_ofs_num = 0.
                ENDIF.

*               Remove marking (+ everything to the right)
*                from overlay

                lw_overlay_txt+lw_char_ofs_num = space.

                lw_deep_num = lw_deep_num - 1.

              ENDIF.

            ENDIF.

          ENDIF.

        ENDIF.

      ENDIF.

    ENDIF.

*   Insert nesting marks into source code.

    OVERLAY <l_pgm_line>-txt WITH lw_overlay_txt.

  ENDLOOP.

ENDFUNCTION.

*---------------------------------------------------------------------*
*      Form  check_select_command
*
*       Check if a SELECT command is initiating a loop
*       requiring ENDSELECT
*
*       Input Parameters -
*         ipt_pgm_text   - Program Text;passed by ref to avoid copying
*         ip_tabix       - Index in table where SELECT was found
*       Changing Parameters -
*         cp_nest_ind    - 'X' indicates SELECT starts a loop
*----------------------------------------------------------------------*

FORM check_select_command
  USING ipt_pgm_text    TYPE zcdf_t_pgm_text
        value(ip_tabix) TYPE sy-tabix
  CHANGING cp_nest_ind  TYPE c.

  DATA:
    l_period_ind  TYPE zgn_ind,
    l_fdpos       TYPE sy-fdpos,
    lwa_pgm_text  TYPE zcdf_pgm_text,
    l_select_txt  TYPE string.

  cp_nest_ind  = space.
  l_period_ind = space.

  LOOP AT ipt_pgm_text
    FROM ip_tabix
    INTO lwa_pgm_text.

*   Avoid comment lines.

    CHECK lwa_pgm_text-txt(1) NE '*'.

*   Eliminate any line ending comment.

    IF lwa_pgm_text-txt CS '"'.
    ENDIF.

    IF sy-fdpos NE 0 AND sy-fdpos LE 79.
      lwa_pgm_text-txt+sy-fdpos = space.
    ENDIF.

*   If ending period found, eliminate anything after the period.

    IF lwa_pgm_text-txt CS '.'.
    ENDIF.

    IF sy-fdpos NE 0 AND sy-fdpos LE 79.
      l_period_ind = 'X'.
    ENDIF.

    IF sy-fdpos NE 0 AND sy-fdpos LT 79.
      l_fdpos = sy-fdpos + 1.
      lwa_pgm_text-txt+l_fdpos = space.
    ENDIF.

*   Add to our string.

    CONCATENATE l_select_txt lwa_pgm_text-txt
                INTO l_select_txt
                SEPARATED BY space.

*   If period found, SELECT end has been reached.

    IF l_period_ind = 'X'.
      EXIT.                 "EXIT the LOOP
    ENDIF.

  ENDLOOP.

* Our STRING variable now has the complete SELECT command.
*  Cleanup before we do our searches.

  CONDENSE l_select_txt.

* Look for options determining if loop started.

* Loading into an internal table without package size does NOT
*  start a loop.

  IF ( l_select_txt CS 'INTO TABLE'                             OR
       l_select_txt CS 'INTO CORRESPONDING FIELDS OF TABLE'     OR
       l_select_txt CS 'APPENDING TABLE'                        OR
       l_select_txt CS 'APPENDING CORRESPONDING FIELDS OF TABLE' )  AND
     l_select_txt NS 'PACKAGE SIZE'.

    cp_nest_ind = space.      "no loop
    EXIT.                     "EXIT subroutine

  ENDIF.

* SELECT SINGLE does NOT start loop.

  IF l_select_txt CS 'SELECT SINGLE'.

    cp_nest_ind = space.      "no loop
    EXIT.                     "EXIT subroutine

  ENDIF.

* Otherwise, start SELECT LOOP

  cp_nest_ind = 'X'.

ENDFORM.                    " check_select_command

3)
REPORT  zcdf_show_program.

PARAMETER: pa_rpt  TYPE programm   OBLIGATORY,
           pa_ste  TYPE rdir_rstat OBLIGATORY
                   DEFAULT 'A'.      " 'A'ctive or 'I'nactive source.

DATA:
  t_abap_text TYPE zcdf_t_pgm_text.

START-OF-SELECTION.

  READ REPORT pa_rpt INTO t_abap_text STATE pa_ste.
  
  CALL FUNCTION 'Z_CDF_LINEUP_COMMANDS'
       CHANGING
            cp_pgm_text = t_abap_text.

  EDITOR-CALL FOR t_abap_text.
This was last published in October 2003

Dig Deeper on SAP ABAP

PRO+

Content

Find more PRO+ content and other member only offers, here.

Start the conversation

Send me notifications when other members comment.

By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy

Please create a username to comment.

-ADS BY GOOGLE

SearchManufacturingERP

SearchOracle

SearchDataManagement

SearchAWS

SearchBusinessAnalytics

SearchCRM

SearchContentManagement

SearchFinancialApplications

Close