SAP 代码扫描工具

描述:

ZSCANNER是一个先进的代码分析工具,旨在提供对程序和功能模块内部工作的全面见解。它揭示了代码的技术细节,包括正在创建、读取、更新或删除的数据表(CRUD操作),以及正在调用的类、功能模块和BAPI(业务插件)。为了提高操作效率,ZScanner包括一个快速错误消息定位功能,允许用户直接导航到导致错误的特定代码行。

我们将其用于AS-IS项目研究和快速操作。

ZSCANNER:

*&---------------------------------------------------------------------*
*& Report  ZSCANNER
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zscanner.

INCLUDE zscanner_top.
INCLUDE zscanner_s01.
INCLUDE zscanner_f01.
INCLUDE zscanner_f02.


AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_modify_screen.


START-OF-SELECTION.

  IF p_ck1 = abap_true.

***GET basic info -- programs
    PERFORM frm_get_basic_info.

***GET PROGRAMS-includings
    PERFORM frm_get_devc_pgmna.

  ELSE.

***Get basic info -- functions
    PERFORM frm_get_basic_func_info.

  ENDIF.

***GET FUNCTION GROUPS && CLASS
  PERFORM frm_get_devc_func.

***GET CLASSES
*  PERFORM frm_get_devc_class.


***GET KEY WORDS.
  PERFORM frm_key_word_scan.


***ALV
  PERFORM frm_alv_list.

INCLUDE zscanner_top.

*&---------------------------------------------------------------------*
*&  Include           ZSCANNER_TOP
*&---------------------------------------------------------------------*

TABLES: tstc, tfdir.

CONSTANTS:
  con_true  TYPE afx_dte_boolean VALUE 'X',
  con_false TYPE afx_dte_boolean VALUE ' '.

DATA: gr_tcode TYPE RANGE OF tstc-tcode,
      gr_pgmna TYPE RANGE OF tstc-pgmna.

DATA: BEGIN OF gs_alv_item,
        repname    TYPE sy-repid,
        dynnr      TYPE sy-dynnr,
        versno     TYPE vrsd-versno,
        line_no    TYPE rsrow,
        text       TYPE text255,
        hit        TYPE xfeld,
        cell_color TYPE lvc_t_scol,
      END OF gs_alv_item,

      gt_alv_item LIKE STANDARD TABLE OF gs_alv_item.


TYPES: BEGIN OF t_str_lines,
         devclass LIKE tadir-devclass,
         progname LIKE rs38m-programm,
         linno    LIKE rslgaxdata-line,
         line     LIKE abapsource-line,
       END OF t_str_lines.

DATA: BEGIN OF g_tab_lines OCCURS 0,
        devclass LIKE tadir-devclass,
        progname LIKE rs38m-programm,
        linno    LIKE rslgaxdata-line,
        line     LIKE abapsource-line,
      END   OF g_tab_lines.


TYPES: BEGIN OF ts_result,
         sel,
         tcode      TYPE tstc-tcode,    "t-code
         pgmna      TYPE tstc-pgmna,    "program
         fname      TYPE rs38l_fnam,    "function module
         instance   TYPE char100,
         title      TYPE trdirt-text,
         spras      TYPE tadir-masterlang,
         created_on TYPE tadir-created_on,
         changed_on TYPE tadir-created_on,
         devclass   TYPE tadir-devclass,
         devclass_t TYPE tdevct-ctext,
         component  TYPE tdevc-component,  "package component??
         select     TYPE char255,
         insert     TYPE char255,
         delete     TYPE char255,
         update     TYPE char255,
         callfunc   TYPE char255,
         callbapi   TYPE char255,
         callrfc    TYPE char255,
         callclass  TYPE char255,
         calltran   TYPE char255,
         submit     TYPE char255,
         forms      TYPE char255,
         isalv      TYPE flag,
         lines      TYPE i,
         button_t   TYPE char255,
       END OF ts_result.
TYPES: tt_result TYPE TABLE OF ts_result.
DATA: gt_result TYPE tt_result,
      gs_result TYPE ts_result.

TYPES: BEGIN OF ts_prog,
         main_name TYPE trdir-name,   "主程序
         name      TYPE trdir-name,
         type      TYPE char02,    "01-program, 02-function, 03-class,
         from      TYPE i,
         to        TYPE i,
         lines     TYPE i,
       END OF ts_prog.
TYPES: tt_prog TYPE TABLE OF ts_prog.
DATA: gt_prog      TYPE tt_prog,
      gs_prog      TYPE ts_prog,
      gt_prog_part TYPE tt_prog,      "section for FORM
      gs_prog_part TYPE ts_prog.

TYPES: BEGIN OF ts_function,
         main_name TYPE trdir-name,   "主程序
         pname     TYPE trdir-name,   "当前程序
         name      TYPE rs38l-name,
         position  TYPE i,            "function所在程序的行
         type      TYPE char02,    "01-function, 02-BAPI, 03-STD.function, 04-destination RFC
       END OF ts_function,
       tt_function TYPE TABLE OF ts_function.
DATA: gt_function TYPE tt_function,
      gs_function TYPE ts_function.


TYPES: BEGIN OF ts_class,
         main_name  TYPE trdir-name,   "主程序
         class_name TYPE eu_lname,        "CLASS
         include    TYPE programm,     "调用CLASS的程序名
       END OF ts_class,
       tt_class TYPE TABLE OF ts_class.
DATA: gt_class TYPE tt_class,
      gs_class TYPE ts_class.

TYPES: BEGIN OF ts_key_word,
         main_name TYPE trdir-name,   "主程序
         name      TYPE trdir-name,   "程序
         keyname   TYPE char40,
         type      TYPE char10,       "
         position  TYPE i,
         ddtext   TYPE dd02t-ddtext,
       END OF ts_key_word,
       tt_key_word TYPE TABLE OF ts_key_word.
DATA: gs_key_word TYPE ts_key_word,
      gt_key_word TYPE tt_key_word.
DATA: gs_detail TYPE ts_key_word,
      gt_detail TYPE tt_key_word.

DATA: gr_code_std TYPE RANGE OF rsmptexts-obj_code.
TYPES: BEGIN OF ts_button,
         main_name TYPE trdir-name,
         obj_code  TYPE rsmptexts-obj_code,
         text      TYPE rsmptexts-text,
       END OF ts_button,
       tt_button TYPE TABLE OF ts_button.
DATA: gs_button TYPE ts_button,
      gt_button TYPE tt_button.

DEFINE append_to_key_word.
  gs_key_word-main_name = &1.
  gs_key_word-name      = &2.
  gs_key_word-keyname   = &3.
  gs_key_word-position  = &4.
  gs_key_word-type      = &5.
  APPEND gs_key_word TO gt_key_word.
  CLEAR gs_key_word.
END-OF-DEFINITION.


INCLUDE zscanner_s01.

*&---------------------------------------------------------------------*
*&  Include           ZSCANNER_S01
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b0 WITH FRAME TITLE text-000.
PARAMETERS: p_ck1 RADIOBUTTON GROUP g1 DEFAULT 'X' USER-COMMAND u1,
            p_ck2 RADIOBUTTON GROUP g1.
SELECTION-SCREEN END OF BLOCK b0.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
SELECT-OPTIONS: s_tcode FOR tstc-tcode MODIF ID m3,
                s_pgmna FOR tstc-pgmna MODIF ID m3,
                s_fname   FOR tfdir-funcname MODIF ID m4.
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN: BEGIN OF BLOCK b2 WITH FRAME TITLE text-002.
PARAMETERS: p_prog AS CHECKBOX DEFAULT con_true MODIF ID m1,
            p_fugr AS CHECKBOX DEFAULT con_true MODIF ID m2,
            p_cinc AS CHECKBOX DEFAULT con_true.
SELECTION-SCREEN END OF BLOCK b2.


INCLUDE zscanner_f01.

*&---------------------------------------------------------------------*
*&  Include           ZSCANNER_F01
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Form  FRM_MODIFY_SCREEN
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_modify_screen .

  LOOP AT SCREEN.

    IF p_ck1 = abap_true.

      IF screen-group1 = 'M1'.
        screen-input = 0.
      ENDIF.

      IF screen-group1 = 'M4'.
        screen-active = 0.
      ENDIF.

    ELSE.

      IF screen-group1 = 'M3'.
        screen-active = 0.
      ENDIF.

      IF screen-group1 = 'M1'.
        screen-active = 0.
      ENDIF.

      IF screen-group1 = 'M2'.
        screen-input = 0.
      ENDIF.

    ENDIF.

    MODIFY SCREEN.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_BASIC_INFO
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_basic_info .

  DATA: lr_pgmna TYPE RANGE OF trdir-name,
        lt_tstc  TYPE TABLE OF tstc.
  DATA: lt_source  TYPE abaptxt255_tab.


  IF s_tcode IS NOT INITIAL.

    SELECT * FROM tstc
      INTO TABLE lt_tstc
      WHERE tcode IN s_tcode.
    IF sy-subrc = 0.

      lr_pgmna = VALUE #( FOR ls_tstc IN lt_tstc
                          ( sign = 'I'
                            option = 'EQ'
                            low = ls_tstc-pgmna ) ).
    ENDIF.
  ENDIF.


***GET programs
  SELECT
    tadir~object,
    tadir~obj_name,
    tadir~devclass,
    tadir~masterlang,
    tadir~component,
    tadir~created_on,
    tstc~tcode,
    reposrc~cnam
    INTO TABLE @DATA(lt_tadir)
    FROM tadir
    INNER JOIN reposrc ON reposrc~progname = tadir~obj_name
    LEFT JOIN tstc ON tstc~pgmna = tadir~obj_name             "NO TCODE IN-CASE
    WHERE reposrc~subc EQ '1'     "Executable program
      AND obj_name IN @lr_pgmna
      AND obj_name IN @s_pgmna
      AND pgmid = 'R3TR'
      AND object = 'PROG'
    .
  IF sy-subrc <> 0.
    MESSAGE s001(00) WITH 'No program found!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.


  LOOP AT lt_tadir INTO DATA(ls_tadir).

    APPEND INITIAL LINE TO gt_prog ASSIGNING FIELD-SYMBOL(<ls_prog>).
    <ls_prog>-main_name = ls_tadir-obj_name.
    <ls_prog>-name      = ls_tadir-obj_name.
    <ls_prog>-type      = '01'.
    READ REPORT ls_tadir-obj_name INTO lt_source.
    <ls_prog>-from = 1.
    <ls_prog>-to = lines( lt_source ).
    <ls_prog>-lines = lines( lt_source ).
    UNASSIGN <ls_prog>.

    APPEND INITIAL LINE TO gt_result ASSIGNING FIELD-SYMBOL(<ls_result>).
    "T-code
    <ls_result>-tcode = ls_tadir-tcode.
    "Program
    <ls_result>-pgmna = ls_tadir-obj_name.
    "Language
    <ls_result>-spras = ls_tadir-masterlang.
    "Create_ON
    <ls_result>-created_on = ls_tadir-created_on.
    "Package
    <ls_result>-devclass = ls_tadir-devclass.
    "Title
    SELECT SINGLE text INTO <ls_result>-title FROM trdirt
      WHERE name = <ls_result>-pgmna AND sprsl = <ls_result>-spras.
    "Package Desc.
    SELECT SINGLE ctext INTO <ls_result>-devclass_t FROM tdevct
      WHERE devclass = <ls_result>-devclass AND spras = <ls_result>-spras.
    "Package Component
    SELECT SINGLE component FROM tdevc INTO <ls_result>-component
      WHERE devclass = <ls_result>-devclass.
    "Last changed
    SELECT SINGLE udat FROM trdir INTO <ls_result>-changed_on
      WHERE name = <ls_result>-pgmna.

    UNASSIGN <ls_result>.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DEVC_PGMNA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_devc_pgmna .

  DATA: lv_program TYPE sy-repid,
        lt_inc_tmp TYPE TABLE OF tadir-obj_name.
  DATA: lt_source  TYPE abaptxt255_tab.

***Get includes
  LOOP AT gt_prog INTO DATA(ls_pgmna).

    lv_program = ls_pgmna-name.
    CALL FUNCTION 'RS_GET_ALL_INCLUDES'
      EXPORTING
        program    = lv_program
      TABLES
        includetab = lt_inc_tmp
      EXCEPTIONS
        OTHERS     = 0.

    LOOP AT lt_inc_tmp INTO DATA(ls_inc_tmp).
      gs_prog-main_name = lv_program.       "main
      gs_prog-name = ls_inc_tmp.            "include
      gs_prog-type = '01'.                  "01-program, 02-function, 03-class
      READ REPORT ls_inc_tmp INTO lt_source.
      gs_prog-from = 1.
      gs_prog-to = lines( lt_source ).
      gs_prog-lines = lines( lt_source ).
      APPEND gs_prog TO gt_prog.
      CLEAR gs_prog.
    ENDLOOP.
*    APPEND LINES OF lt_inc_tmp TO gt_prog.

  ENDLOOP.

  SORT gt_prog BY main_name name.
  DELETE ADJACENT DUPLICATES FROM gt_prog COMPARING main_name name.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SEARCH_SOURCE_CALLFUNC
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM search_source_callfunc USING it_prog TYPE tt_prog
                            CHANGING ct_function TYPE tt_function
                                     ct_function_std TYPE tt_function
                                     ct_bapis TYPE tt_function .

  DATA: lt_source  TYPE abaptxt255_tab,
        lt_results TYPE match_result_tab.
  DATA: lt_function TYPE tt_function,
        lv_regex    TYPE string,
        lv_regex2   TYPE string.


  PERFORM frm_pattern_call_function USING 'CALL_FUNCTION'
                                    CHANGING lv_regex
                                             lv_regex2.

  LOOP AT it_prog INTO gs_prog.
    IF NOT ( sy-tabix >= gs_prog-from AND sy-tabix <= gs_prog-to ).
      EXIT.
    ENDIF.

    READ REPORT gs_prog-name INTO lt_source.
    IF sy-subrc <> 0.
      CONTINUE.
    ENDIF.

    FIND ALL OCCURRENCES OF REGEX lv_regex IN TABLE lt_source
      IN CHARACTER MODE
      IGNORING CASE
      RESULTS lt_results.

    IF lt_results[] IS NOT INITIAL.
*      lv_found = abap_true.
      LOOP AT lt_results INTO DATA(ls_results).

        READ TABLE lt_source INTO DATA(ls_source2) INDEX ls_results-line.
        IF sy-subrc = 0.
          "是注释行时 continue
          IF ls_source2-line(1) = '*'.
            CONTINUE.
          ENDIF.

          SEARCH ls_source2-line FOR '"'.
          IF sy-subrc = 0 AND sy-fdpos <= ls_results-offset.
            CONTINUE.
          ENDIF.
        ENDIF.


        PERFORM frm_get_hit_set USING lt_source
                                      gs_prog-name
                                      ls_results-line.

        PERFORM frm_get_fm_name USING lt_source
                                      lv_regex
                                      ls_results-line
                                      gs_prog-main_name
                                      gs_prog-name
                                CHANGING ct_function
                                         ct_function_std
                                         ct_bapis.

      ENDLOOP.
    ENDIF.






  ENDLOOP.



ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DEVC_CLASS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_devc_class .

  DATA: lt_wbcrossgt TYPE TABLE OF wbcrossgt,
        lt_class     TYPE tt_class.


  LOOP AT gt_result INTO gs_result.

    "逐个程序处理
    DATA(lt_prog) = gt_prog.
    DELETE lt_prog WHERE main_name NE gs_result-pgmna.


    WHILE lt_prog[] IS NOT INITIAL.
***Search source
      "程序里 找出 class
      PERFORM search_source_class USING lt_prog
                                  CHANGING lt_wbcrossgt.

      CLEAR lt_prog.
***class 找出 class程序名(到function)
      PERFORM get_class_obj USING gs_result-pgmna
                                  lt_wbcrossgt
                            CHANGING lt_prog
                                     lt_class.
    ENDWHILE.


    SORT lt_class BY main_name class_name.
    DELETE ADJACENT DUPLICATES FROM lt_class COMPARING main_name class_name.

    "拼接class
    LOOP AT lt_class INTO DATA(ls_class).
      gs_result-callclass =  ls_class-class_name && ',' && gs_result-callclass.
      CONDENSE gs_result-callclass.
      append_to_key_word: gs_result-pgmna
                          ls_class-class_name
                          ls_class-class_name
                          1
                          'CALLCLASS'.         "CALL_CLASS
    ENDLOOP.
    CLEAR lt_class.

    MODIFY gt_result FROM gs_result TRANSPORTING callclass.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DEVC_FUNC
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_devc_func .

  DATA: lt_function     TYPE tt_function,
        lt_function_std TYPE tt_function,
        lt_bapis        TYPE tt_function,
        lt_function_all TYPE tt_function,
        lt_bapis_all    TYPE tt_function.

  DATA: lt_wbcrossgt TYPE TABLE OF wbcrossgt,
        lt_class     TYPE tt_class.

  DATA: lt_prog_next       TYPE tt_prog,
        lv_start_from_se37.

  IF p_ck1 = abap_true.
    lv_start_from_se37 = abap_false.
  ELSE.
    lv_start_from_se37 = abap_true.
  ENDIF.

  LOOP AT gt_result INTO gs_result.

    "逐个程序处理
    DATA(lt_prog) = gt_prog.
    DELETE lt_prog WHERE main_name NE gs_result-pgmna.


    WHILE lt_prog[] IS NOT INITIAL.

      IF lv_start_from_se37 = abap_false.
***Search source
        "程序里 找出 function
        PERFORM search_source_callfunc USING lt_prog
                                       CHANGING lt_function
                                                lt_function_std
                                                lt_bapis.
        CLEAR lv_start_from_se37.
      ELSE.
        "初始 function
        lt_function = VALUE #(  FOR ls_prog2 IN lt_prog
                                  ( main_name = ls_prog2-main_name
                                    name = ls_prog2-name
                                    type = ls_prog2-type ) ).
      ENDIF.

***get function programs.
      IF p_fugr = abap_true.
        "function里找出程序名,  继续下一次程序找function
        PERFORM get_function_obj  USING gs_result-pgmna
                                        lt_function
                                  CHANGING lt_prog_next.    "call function IN call function.

      ENDIF.

      CLEAR lt_function.

***Search source
      "程序里 找出 class
      PERFORM search_source_class USING lt_prog
                                  CHANGING lt_wbcrossgt.

***get class programs.
      IF p_cinc = abap_true.
        "class 找出 class程序名(到function)
        PERFORM get_class_obj USING gs_result-pgmna
                                    lt_wbcrossgt
                              CHANGING lt_prog_next
                                       lt_class.
      ENDIF.

      lt_prog[] = lt_prog_next[].
      CLEAR: lt_prog_next,
             lt_wbcrossgt,
             lt_function,
             lt_function_std,
             lt_bapis.
    ENDWHILE.


*    SORT gt_function by type name.
    LOOP AT gt_function INTO gs_function WHERE main_name = gs_result-pgmna.
      "01-function, 02-BAPI, 03-STD.function
      IF gs_function-type = '01'.
        CONCATENATE gs_function-name gs_result-callfunc
        INTO gs_result-callfunc SEPARATED BY ','.
        CONDENSE gs_result-callfunc.
        "append to keyword.
        append_to_key_word: gs_result-pgmna
                            gs_function-pname
                            gs_function-name
                            gs_function-position
                            'CALLFUNC'.

      ELSEIF gs_function-type = '04'.
        CONCATENATE gs_function-name gs_result-callrfc
        INTO gs_result-callrfc SEPARATED BY ','.
        CONDENSE gs_result-callrfc.
        "append to keyword.
        append_to_key_word: gs_result-pgmna
                            gs_function-pname
                            gs_function-name
                            gs_function-position
                            'CALLRFC'.

      ELSE.
        CONCATENATE gs_function-name gs_result-callbapi
        INTO gs_result-callbapi SEPARATED BY ','.
        CONDENSE gs_result-callbapi.
        "append to keyword.
        append_to_key_word: gs_result-pgmna
                            gs_function-pname
                            gs_function-name
                            gs_function-position
                            'CALLBAPI'.

      ENDIF.
    ENDLOOP.


***CLASS
    SORT lt_class BY main_name class_name.
    DELETE ADJACENT DUPLICATES FROM lt_class COMPARING main_name class_name.
    APPEND LINES OF lt_class TO gt_class.

    "拼接class
    LOOP AT lt_class INTO DATA(ls_class) WHERE main_name = gs_result-pgmna.
      gs_result-callclass =  ls_class-class_name && ',' && gs_result-callclass.
      CONDENSE gs_result-callclass.
      "append to keyword.
      append_to_key_word: gs_result-pgmna
                          ls_class-class_name
                          ls_class-class_name
                          1
                          'CALLCLASS'.         "CALL_CLASS
    ENDLOOP.
    CLEAR lt_class.

*    MODIFY gt_result FROM gs_result TRANSPORTING callfunc callbapi callclass.
    MODIFY gt_result FROM gs_result TRANSPORTING callfunc callbapi callrfc callclass.
    CLEAR: gs_result.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_function_OBJ
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_function  text
*      <--P_GT_prog  text
*----------------------------------------------------------------------*
FORM get_function_obj  USING  iv_main_name TYPE program_id
                              it_function TYPE tt_function
                        CHANGING ct_prog TYPE tt_prog.

  DATA: lv_progname TYPE char100,
        ls_prog     TYPE ts_prog.
  DATA: lt_source  TYPE abaptxt255_tab.

  CHECK it_function[] IS NOT INITIAL.

  SELECT *
    FROM tfdir
    INTO TABLE @DATA(lt_tfdir)
    FOR ALL ENTRIES IN @it_function
    WHERE funcname = @it_function-name.
  IF sy-subrc = 0.

    LOOP AT lt_tfdir INTO DATA(ls_tfdir).

      CONCATENATE ls_tfdir-pname 'U' ls_tfdir-include INTO lv_progname.
      "SAPLXXX01--->SAPLXXX01,  /BMW/SAPLXXX02--->/BMW/LXXX02
      REPLACE 'SAP' IN lv_progname WITH space .
      CONDENSE lv_progname.

      "CHECK是未处理过的程序--避免相互调用造成的死循环
      READ TABLE gt_prog INTO gs_prog WITH KEY name = lv_progname
                                               from = 1
                                               to   = lines( lt_source ).
      IF sy-subrc NE 0.

        ls_prog-main_name = iv_main_name.
        ls_prog-name = lv_progname.
        ls_prog-type = '02'.
        READ REPORT lv_progname INTO lt_source.
        ls_prog-from = 1.
        ls_prog-to = lines( lt_source ).
        ls_prog-lines = lines( lt_source ).
        APPEND ls_prog TO ct_prog.
        APPEND ls_prog TO gt_prog.

        "遍历当前程序体里的PERFORM调用.
        PERFORM frm_search_source_form USING ls_prog
                                       CHANGING ct_prog .

        CLEAR ls_prog.
      ENDIF.


    ENDLOOP.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_HIT_SET
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_GT_SOURCE  text
*      -->P_gs_prog_NAME  text
*      -->P_LS_RESULTS_LINE  text
*----------------------------------------------------------------------*
FORM frm_get_hit_set  USING    it_abap TYPE abaptxt255_tab
                               iv_pgmna_name TYPE trdir-name
                               iv_tabix TYPE match_result-line.

  DATA: lv_end     TYPE i,
        lv_start   TYPE i,
        lv_xtabix  TYPE sy-tabix,
        lv_hitline TYPE xfeld.
  DATA: gv_hit_count TYPE i.

  DATA: ls_col LIKE LINE OF gs_alv_item-cell_color.

  FIELD-SYMBOLS:
    <lv_abap> TYPE any.

  lv_start = iv_tabix - 2 .
  lv_end   = iv_tabix + 2.

  IF lv_start < 1.
    lv_start = 1.
  ENDIF.

  WHILE lv_start <= lv_end.
    READ TABLE it_abap ASSIGNING <lv_abap> INDEX lv_start.
    IF sy-subrc IS NOT INITIAL.
      EXIT.
    ENDIF.

    lv_xtabix = sy-tabix.

    IF lv_start = iv_tabix.
      lv_hitline = 'X'.
    ELSE.
      CLEAR lv_hitline.
    ENDIF.

    ADD 1 TO lv_start.


    IF <lv_abap>(1) = '*'
    OR <lv_abap>(1) = '"'.
      CONTINUE.
    ENDIF.

    gs_alv_item-repname = iv_pgmna_name.
    gs_alv_item-line_no = lv_xtabix.
    gs_alv_item-text    = <lv_abap>.

    IF lv_hitline IS NOT INITIAL.
      gs_alv_item-hit = 'X'.
      ADD 1 TO gv_hit_count.
      ls_col-fname     = 'TEXT'.
      ls_col-color-col = '5'.
      APPEND ls_col TO gs_alv_item-cell_color.
    ENDIF.

    APPEND gs_alv_item TO gt_alv_item.

    CLEAR gs_alv_item.

  ENDWHILE.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_FM_NAME
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_SOURCE  text
*      -->P_LS_RESULTS_LINE  text
*      <--P_LT_function  text
*----------------------------------------------------------------------*
FORM frm_get_fm_name  USING    it_abap TYPE abaptxt255_tab
                               iv_regex TYPE string
                               iv_tabix TYPE match_result-line
                               iv_main_name  TYPE trdir-name
                               iv_pname  TYPE trdir-name
                      CHANGING ct_function TYPE tt_function
                               ct_function_std TYPE tt_function
                               ct_bapis TYPE tt_function .


  DATA: lv_exit,
        lv_character,
        lv_fname(30),
        lv_fdpos TYPE i.
  DATA: ls_function TYPE ts_function.

  CLEAR lv_exit.
  LOOP AT it_abap INTO DATA(ls_abap) FROM iv_tabix.

    DATA(lv_index) = iv_tabix.  "line

    FIND REGEX iv_regex IN ls_abap-line IGNORING CASE.
    IF sy-subrc = 0.

      DO 10 TIMES.  "search 10 lines at most

        READ TABLE it_abap INTO DATA(ls_abap_curr) INDEX lv_index.

        SEARCH ls_abap_curr-line FOR '''' .
        IF sy-subrc = 0.

          lv_fdpos = sy-fdpos.
          DO 30 TIMES.

            lv_fdpos = lv_fdpos + 1.
            lv_character = ls_abap_curr-line+lv_fdpos(1).
            IF lv_character = ''''.
              EXIT.
            ELSE.
              lv_fname = lv_fname && lv_character.
            ENDIF.
          ENDDO.

          CONDENSE lv_fname.
          ls_function-main_name = iv_main_name.
          ls_function-pname = iv_pname.   "function位置所在的程序
          ls_function-position = lv_index.   "function位置所在的程序行
          ls_function-name = lv_fname.
          SELECT SINGLE funcname INTO lv_fname FROM tfdir WHERE funcname = lv_fname.
          IF sy-subrc = 0.
            "是当前系统function.
            IF lv_fname(1) = 'Z' OR lv_fname(5) = '/BMW/'.
              ls_function-type = '01'.
              APPEND ls_function TO gt_function.
              APPEND ls_function TO ct_function.
            ELSEIF lv_fname(4) = 'BAPI'.
              ls_function-type = '02'.
              APPEND ls_function TO gt_function.
              APPEND ls_function TO ct_bapis.
            ELSE.
              ls_function-type = '03'.
              APPEND ls_function TO gt_function.
              APPEND ls_function TO ct_function_std.
            ENDIF.

          ELSE.
            "是destination系统

*            ZSCANNER_F01
            FIND REGEX 'DESTINATION' IN ls_abap-line IGNORING CASE.
            IF sy-subrc NE 0.

              DATA(lv_next) = iv_tabix + 1.
              LOOP AT it_abap INTO DATA(ls_abap_rfc) FROM lv_next.
                IF ls_abap_rfc(1) = '*' OR ls_abap_rfc IS INITIAL.
                  CONTINUE.
                ELSE.
                  "非注释行&非空行&非"DEST.行 --- 校验DESTINATION.
                  FIND REGEX 'DESTINATION' IN ls_abap_rfc-line IGNORING CASE.
                  IF sy-subrc = 0.
                    FIND REGEX '"\s+DESTINATION' IN ls_abap_rfc-line IGNORING CASE.
                    IF sy-subrc NE 0.
                      ls_function-type = '04'.      "RFC.
                      APPEND ls_function TO gt_function.
                    ENDIF.
                  ENDIF.
                  EXIT. "检测到非空行即跳出
                ENDIF.
              ENDLOOP.

            ELSE.
              ls_function-type = '04'.      "RFC.
              APPEND ls_function TO gt_function.
            ENDIF.



          ENDIF.

          lv_exit = abap_true.
          EXIT.
        ELSE.
          "next line
          lv_index = lv_index + 1.
          CONTINUE.

        ENDIF.
      ENDDO.

      IF lv_exit = abap_true..
        EXIT.
      ENDIF.

      CLEAR lv_fname.

    ELSE.
    ENDIF.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_PATTERN_CALL_FUNCTION
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_0183   text
*      <--P_LV_REGEX  text
*----------------------------------------------------------------------*
FORM frm_pattern_call_function  USING    iv_type TYPE char20
                                CHANGING cv_regex TYPE string
                                         cv_regex2 TYPE string.

  CASE iv_type.
    WHEN 'CALL_FUNCTION'.
      "Start with 'CALL', end with 'FUNCTION'
      cv_regex = '\<CALL\s+FUNCTION\>'.
      cv_regex2 = '"\s+\<CALL\s+FUNCTION\>'.

    WHEN 'CREATE_OBJECT'.

    WHEN OTHERS.
  ENDCASE.


ENDFORM.










*&---------------------------------------------------------------------*
*&      Form  FRM_ALV_prog
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_alv_list .

  CONSTANTS:
    lc_pf_status    TYPE slis_formname VALUE 'FRM_PF_STATUS',
    lc_user_command TYPE slis_formname VALUE 'FRM_USER_COMMAND'.

  DATA: lv_repid    TYPE sy-repid,
        ls_layout   TYPE lvc_s_layo,
        lt_fieldcat TYPE lvc_t_fcat.

  lv_repid = sy-repid.
  ls_layout-zebra = abap_true.
  ls_layout-box_fname = 'SEL'.
  PERFORM frm_set_fieldcat CHANGING lt_fieldcat.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = lv_repid
      is_layout_lvc           = ls_layout
*     i_grid_title            =
      it_fieldcat_lvc         = lt_fieldcat
*     i_callback_pf_status_set = lc_pf_status
      i_callback_user_command = lc_user_command
      i_save                  = 'X'
    TABLES
      t_outtab                = gt_result[]
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  .
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_SET_FIELDCAT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_LT_FIELDCAT  text
*----------------------------------------------------------------------*
FORM frm_set_fieldcat CHANGING ct_fieldcat TYPE lvc_t_fcat.

  DATA: ls_fieldcat TYPE lvc_s_fcat.

  DEFINE marco_fieldcat.

    CLEAR ls_fieldcat.
    ls_fieldcat-key        = &1.
    ls_fieldcat-fieldname  = &2.
    ls_fieldcat-coltext    = &3.
    ls_fieldcat-col_opt    = &4.
    ls_fieldcat-hotspot    = &5.
    ls_fieldcat-ref_field = &6.
    ls_fieldcat-ref_table = &7.
    APPEND ls_fieldcat TO ct_fieldcat.
  END-OF-DEFINITION.


  marco_fieldcat:
    'X'  'TCODE'      'T-code'     'X' ''  ''  '',
    'X'  'PGMNA'      'Program'    'X' ''  ''  '',
    ''   'INSTANCE'   'Instance'   'X' ''  ''  '',
    ''   'TITLE'      'Title'      'X' ''  ''  '',
    ''   'SPRAS'      'Language'   'X' ''  ''  '',
    ''   'CREATED_ON' 'Created on' 'X' ''  ''  '',
    ''   'CHANGED_ON' 'Changed on' 'X' ''  ''  '',
    ''   'DEVCLASS'   'Package'    'X' ''  ''  '',
    ''   'DEVCLASS_T' 'Package Desc.'      'X' ''  ''  '',
    ''   'COMPONENT'  'Package Component'  'X' ''  ''  '',
    ''   'SELECT'    'Select table'       'X' 'X'  ''  '',
    ''   'INSERT'    'Insert table'       'X' 'X'  ''  '',
    ''   'DELETE'    'Delete table'       'X' 'X'  ''  '',
    ''   'UPDATE'    'Update table'       'X' 'X'  ''  '',
    ''   'CALLFUNC'   'call Function'      'X' 'X'  ''  '',
    ''   'CALLBAPI'   'call Bapi'          'X' 'X'  ''  '',
    ''   'CALLRFC'    'call RFC'           'X' 'X'  ''  '',
    ''   'CALLCLASS'  'Class/Interface'    'X' 'X'  ''  '',
    ''   'CALLTRAN'   'call TRANSACTION'   'X' 'X'  ''  '',
    ''   'SUBMIT'    'Submit program'     'X' 'X'  ''  '',
    ''   'FORMS'      'Print Form'         'X' 'X'  ''  '',
    ''   'ISALV'      'ALV Display'        'X' ''  ''  '',
    ''   'LINES'      'Coding Line'        'X' ''  ''  '',
    ''   'BUTTON_T'   'Button text'        'X' 'X'  ''  ''.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SEARCH_SOURCE_CLASS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_PROG  text
*      <--P_LT_FUNCTION  text
*      <--P_LT_FUNCTION_STD  text
*      <--P_LT_BAPIS  text
*----------------------------------------------------------------------*
FORM search_source_class  USING    it_prog TYPE tt_prog
                          CHANGING ct_wbcrossgt TYPE wbcrossgtt.

  SELECT *
    FROM wbcrossgt
    INTO TABLE ct_wbcrossgt
    FOR ALL ENTRIES IN it_prog
    WHERE include = it_prog-name
      AND otype = 'ME' .     "METHOD
*      AND ( otype = 'TY'    "CLASS
*           OR otype = 'ME' ). "METHOD

  .

  "删除标准的CLASS.
  DELETE ct_wbcrossgt WHERE name(1) NE 'Z' AND name(5) NE '/BMW/'.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_CLASS_OBJ
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_WBCROSSGT  text
*      <--P_LT_PROG  text
*----------------------------------------------------------------------*
FORM get_class_obj  USING    iv_main_name TYPE program_id
                             it_wbcrossgt TYPE wbcrossgtt
                    CHANGING ct_prog TYPE tt_prog
                             ct_class TYPE tt_class.

  DATA: ls_prog  TYPE ts_prog,
        ls_tmdir TYPE tmdir,
        lt_tmdir TYPE TABLE OF tmdir.
  DATA: lv_suffix       TYPE c LENGTH 5,
        lv_progname(50),
        lv_flag(30).
  DATA: lt_source  TYPE abaptxt255_tab.

  LOOP AT it_wbcrossgt INTO DATA(ls_wbcrossgt) WHERE otype = 'ME'.

    SPLIT ls_wbcrossgt-name AT '\ME:' INTO ls_tmdir-classname ls_tmdir-methodname.

***CLASS name
    gs_class-main_name = iv_main_name.         "MAIN_NAME
    gs_class-class_name = ls_tmdir-classname.  "CLASS
    APPEND gs_class TO ct_class.
    CLEAR gs_class.


    SELECT * FROM tmdir INTO TABLE lt_tmdir
      WHERE classname = ls_tmdir-classname
        AND methodname = ls_tmdir-methodname.
    IF sy-subrc = 0.

      LOOP AT lt_tmdir INTO ls_tmdir.

        PERFORM convert_numc_35 USING ls_tmdir-methodindx
                                CHANGING lv_suffix.

        "/BMW/XXXXXX====MCNNN 总长度是35.
        DATA(lv_length) = 30 - strlen( ls_tmdir-classname ).

        DO lv_length TIMES.
          lv_flag = lv_flag && '='.
          CONDENSE lv_flag.
        ENDDO.
        lv_progname = ls_tmdir-classname && lv_flag && lv_suffix.

        "CHECK是未处理过的程序--避免相互调用造成的死循环
        READ TABLE gt_prog INTO gs_prog WITH KEY name = lv_progname.
        IF sy-subrc NE 0.
          ls_prog-main_name = iv_main_name.
          ls_prog-name = lv_progname.
          ls_prog-type = '03'.
          READ REPORT lv_progname INTO lt_source.
          ls_prog-from = 1.
          ls_prog-to = lines( lt_source ).
          ls_prog-lines = lines( lt_source ).
          APPEND ls_prog TO ct_prog.
          APPEND ls_prog TO gt_prog.
          CLEAR ls_prog.
        ENDIF.

        CLEAR lv_flag.
      ENDLOOP.
    ENDIF.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CONVERT_NUMC_35
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_TMDIR_METHODINDX  text
*      <--P_LV_SUFFIX  text
*----------------------------------------------------------------------*
FORM convert_numc_35  USING    iv_methodindx
                      CHANGING cv_suffix TYPE char5.

  CONSTANTS: lc_character TYPE c LENGTH 36 VALUE '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

  DATA: lv_mod TYPE numc2,
        lv_div TYPE numc2.

  lv_div = iv_methodindx DIV 36.
  lv_mod = iv_methodindx MOD 36.

  cv_suffix = 'CM' && lv_div && lc_character+lv_mod(1).

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_KEY_WORD_SCAN
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_key_word_scan .

  DATA: lv_subrc TYPE sy-subrc.
  DATA: lt_source  TYPE abaptxt255_tab.

  DATA: lt_keywrd_sel    TYPE abaptxt255_tab,
        lt_keywrd_ins    TYPE abaptxt255_tab,
        lt_keywrd_del    TYPE abaptxt255_tab,
        lt_keywrd_upd    TYPE abaptxt255_tab,
        lt_keywrd_submit TYPE abaptxt255_tab,
        lt_keywrd_call   TYPE abaptxt255_tab,
        lt_stoken        TYPE stoken_tab,
        lt_sstmnt        TYPE sstmnt_tab.

  DATA: lr_code_std TYPE RANGE OF rsmptexts-obj_code.

  lt_keywrd_sel[] = VALUE #( ( line = 'SELECT'  ) ).
  lt_keywrd_ins[] = VALUE #( ( line = 'INSERT'  ) ).
  lt_keywrd_del[] = VALUE #( ( line = 'DELETE'  ) ).
  lt_keywrd_upd[] = VALUE #( ( line = 'UPDATE'  ) ).
  lt_keywrd_submit[] = VALUE #( ( line = 'SUBMIT'  ) ).
  lt_keywrd_call[] = VALUE #( ( line = 'CALL'  ) ).

  LOOP AT gt_prog INTO gs_prog.

    READ REPORT gs_prog-name INTO lt_source.

***SELECT
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_sel
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.

    "select xxx from db.
    "select xxx from db-a join db-b xxxx
    LOOP AT lt_stoken INTO DATA(ls_stoken) WHERE ( str = 'FROM' OR str = 'JOIN' ).
      DATA(lv_index) = sy-tabix + 1.
      "FROM 下一行是表名称
      READ TABLE lt_stoken INTO DATA(ls_stoken1) INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'SELECT'.           "SELECT

        ENDIF.
      ENDIF.
    ENDLOOP.


***INSERT
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_ins
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "insert db from xxx.
    "insert into db values xxx.
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'INSERT' OR str = 'INTO' ).
      lv_index = sy-tabix + 1.
      "下一行是表名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'INSERT'.           "INSERT

        ENDIF.
      ENDIF.
    ENDLOOP.


***DELETE
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_del
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "delete db from itab xxxx
    "delete from db where xxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'DELETE' OR str = 'FROM' ).
      lv_index = sy-tabix + 1.
      "下一行是表名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'DELETE'.           "DELETE

        ENDIF.
      ENDIF.
    ENDLOOP.


***UPDATE
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_upd
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "delete db from xxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'UPDATE' ).
      lv_index = sy-tabix + 1.
      "下一行是表名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'UPDATE'.           "UPDATE

        ENDIF.
      ENDIF.
    ENDLOOP.

***SUBMIT.
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_submit
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "delete db from xxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'SUBMIT' ).
      lv_index = sy-tabix + 1.
      "下一行是程序名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_progname USING ls_stoken1-str
                               CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'SUBMIT'.           "UPDATE

        ENDIF.
      ENDIF.
    ENDLOOP.

***CALL TRANSACTION
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_call
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "call transaction xxxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'CALL' ).
      lv_index = sy-tabix + 1.
      "下一行是TRANSACTION.
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        TRANSLATE ls_stoken1-str TO UPPER CASE.
        CHECK ls_stoken1-str = 'TRANSACTION'.
        lv_index = lv_index + 1.
        "下一行是TCODE名称
        READ TABLE lt_stoken INTO DATA(ls_stoken2) INDEX lv_index.
        IF sy-subrc = 0.
          PERFORM check_tcode USING ls_stoken2-str
                                 CHANGING lv_subrc.
          IF lv_subrc = 0.
            append_to_key_word: gs_prog-main_name
                                gs_prog-name
                                ls_stoken2-str
                                ls_stoken2-row
                                'CALL_TRANSACTION'.         "CALL_TRANSACTION

          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDLOOP.


  SORT gt_key_word.
  DELETE ADJACENT DUPLICATES FROM gt_key_word COMPARING ALL FIELDS.

  "standard function-code
  PERFORM append_code_std CHANGING lr_code_std.

  "更新到result表
  LOOP AT gt_result INTO gs_result.

    LOOP AT gt_key_word INTO gs_key_word WHERE main_name = gs_result-pgmna.

      CASE gs_key_word-type.
        WHEN 'SELECT'.
          gs_result-select = gs_key_word-keyname && ',' && gs_result-select.
          CONDENSE gs_result-select.
        WHEN 'INSERT'.
          gs_result-insert = gs_key_word-keyname && ',' && gs_result-insert.
          CONDENSE gs_result-insert.
        WHEN 'DELETE'.
          gs_result-delete = gs_key_word-keyname && ',' && gs_result-delete.
          CONDENSE gs_result-delete.
        WHEN 'UPDATE'.
          gs_result-update = gs_key_word-keyname && ',' && gs_result-update.
          CONDENSE gs_result-update.
        WHEN 'SUBMIT'.
          gs_result-submit = gs_key_word-keyname && ',' && gs_result-submit.
          CONDENSE gs_result-submit.
        WHEN 'CALL_TRANSACTION'.
          gs_result-calltran = gs_key_word-keyname && ',' && gs_result-calltran.
          CONDENSE gs_result-calltran.

      ENDCASE.

    ENDLOOP.

***lines
    LOOP AT gt_prog INTO gs_prog WHERE main_name = gs_result-pgmna.
      gs_result-lines = gs_result-lines + ( gs_prog-to - gs_prog-from + 1 ).
    ENDLOOP.

***button
    SELECT * FROM rsmptexts
      INTO TABLE @DATA(lt_rsmptexts)
      WHERE progname = @gs_result-pgmna
        AND obj_type = 'F'
        AND texttype IN ('Q','M','I')  "I-icon info,  M-Object text, Q-quick info.
        AND obj_code NOT IN @lr_code_std.

    "优先取icon info,再取Object text, 最后取quick info.
    SORT lt_rsmptexts BY progname obj_code obj_type texttype.
    DELETE ADJACENT DUPLICATES FROM lt_rsmptexts COMPARING progname obj_code obj_type .
    LOOP AT lt_rsmptexts INTO DATA(ls_rsmptexts).
      gs_result-button_t = ls_rsmptexts-text && ',' && gs_result-button_t.
      CONDENSE gs_result-button_t.

      gs_key_word-main_name = gs_result-pgmna.
*      gs_key_word-keyname = ls_rsmptexts-obj_code.
      gs_key_word-keyname = ls_rsmptexts-text.
      gs_key_word-type = 'BUTTON_T'.    "插入到key_word表 用于双击分解?
      APPEND gs_key_word TO gt_key_word.
      CLEAR gs_key_word.
    ENDLOOP.


***Smartforms
    READ TABLE gt_function INTO gs_function WITH KEY type = '03'
                                                     name = 'SSF_FUNCTION_MODULE_NAME'.
    IF sy-subrc = 0.
      "存在 调smartforms.
      "----->如何找smartforms名称.
    ENDIF.

    MODIFY gt_result FROM gs_result.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_SEARCH_SOURCE_FORM
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_PROG  text
*----------------------------------------------------------------------*
FORM frm_search_source_form  USING  is_prog TYPE ts_prog
                             CHANGING ct_prog TYPE tt_prog.

  DATA: lt_source  TYPE abaptxt255_tab,
        lt_results TYPE match_result_tab.
  DATA: lt_function  TYPE tt_function,
        lv_regex     TYPE string,
        lv_regex2    TYPE string,
        lv_regex3    TYPE string,
        lv_regex4    TYPE string,
        lv_from_done,
        lv_to_done.

  DATA: lt_keywrd  TYPE abaptxt255_tab,
        lt_keywrd2 TYPE abaptxt255_tab,
        lt_stoken  TYPE stoken_tab,
        lt_sstmnt  TYPE sstmnt_tab.

  DATA: lv_program TYPE sy-repid,
        lt_inc_tmp TYPE TABLE OF tadir-obj_name.
  DATA: lt_prog_form TYPE tt_prog,
        lt_prog_next TYPE tt_prog.


  TYPES: BEGIN OF ts_form,
           str TYPE token_str,
         END OF ts_form.
  DATA: ls_form TYPE ts_form,
        lt_form TYPE TABLE OF ts_form.

  DATA: lv_index TYPE i,
        lv_from  TYPE i,
        lv_to    TYPE i.

  PERFORM frm_pattern_call_function USING 'PERFORM'
                                    CHANGING lv_regex
                                             lv_regex2.

*  READ REPORT is_prog-name INTO lt_source.

  lt_keywrd[] = VALUE #( ( line = 'PERFORM'  ) ).

  lt_prog_form = VALUE #( ( main_name = is_prog-main_name
                            name = is_prog-name
                            type = is_prog-type
                            from = is_prog-from
                            to = is_prog-to ) ).

  WHILE lt_prog_form[] IS NOT INITIAL.

    LOOP AT lt_prog_form INTO DATA(ls_prog_form).

***读取PERFORMS.
      READ REPORT ls_prog_form-name INTO lt_source.

      SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd
                                 TOKENS INTO lt_stoken
                                 STATEMENTS INTO lt_sstmnt.
      "删除范围外的mapping行
      DELETE lt_stoken WHERE row LT ls_prog_form-from OR row GT ls_prog_form-to.
      CHECK lt_stoken[] IS NOT INITIAL.

      CHECK lt_sstmnt[] IS NOT INITIAL.
      LOOP AT lt_stoken INTO DATA(ls_stoken) WHERE str = 'PERFORM'.
        lv_index = sy-tabix + 1.
        READ TABLE lt_stoken INTO ls_stoken INDEX lv_index.
        IF sy-subrc = 0.
          ls_form-str = ls_stoken-str.
          APPEND ls_form TO lt_form.
        ENDIF.
      ENDLOOP.
      CLEAR: lt_stoken, lt_sstmnt.

      "include程序--->main程序
      SELECT * FROM d010inc INTO TABLE @DATA(lt_d010inc) WHERE include = @is_prog-name.
      IF sy-subrc = 0.

        CHECK lines( lt_d010inc[] ) = 1.
        READ TABLE lt_d010inc INTO DATA(ls_d010inc) INDEX 1.

        "main程序--->所有程序
        lv_program = ls_d010inc-master.
        CALL FUNCTION 'RS_GET_ALL_INCLUDES'
          EXPORTING
            program    = lv_program
          TABLES
            includetab = lt_inc_tmp
          EXCEPTIONS
            OTHERS     = 0.

        "在所有including程序中找出FORM的开始行到结束行.
        LOOP AT lt_inc_tmp INTO DATA(ls_inc_tmp) .

          READ REPORT ls_inc_tmp INTO lt_source.
          "逐个perform进行查找.
          LOOP AT lt_form INTO ls_form.

            "开始行
            "FORM xxxxx .
            lv_regex = 'FORM\s+' && ls_form-str && '[\s.]'.       "开始行
            lv_regex2 = '"\s+FORM\s+' && ls_form-str && '[\s.]'.  "被注释的开始行
            lv_regex3 = 'ENDFORM' && '[\s.]'.               "结束行
            lv_regex4 = '"\s+ENDFORM' && '[\s.]'.           "被注释的结束行
            LOOP AT lt_source INTO DATA(ls_source).
              CHECK ls_source(1) NE '*'.    "注释行.

              IF lv_from_done = abap_false.
                "找开始行
                lv_from = sy-tabix.
                FIND REGEX lv_regex IN ls_source-line IGNORING CASE.
                IF sy-subrc = 0.
                  "check是否注释的
                  FIND REGEX lv_regex2 IN ls_source-line IGNORING CASE.
                  IF sy-subrc NE 0.
                    CONDENSE ls_source-line.
                    CHECK ls_source-line(4) = 'FORM'. "是FORM开头.
                    lv_from_done = abap_true.
                  ENDIF.
                ENDIF.

              ELSE.
                "找结束行.
                lv_to = sy-tabix.
                FIND REGEX lv_regex3 IN ls_source-line IGNORING CASE.
                IF sy-subrc = 0.
                  "check是否注释的
                  FIND REGEX lv_regex4 IN ls_source-line IGNORING CASE.
                  IF sy-subrc NE 0.
                    lv_to_done = abap_true.
                    EXIT.
                  ENDIF.
                ENDIF.
              ENDIF.

            ENDLOOP.


            IF lv_to_done = 'X'.

              "CHECK是未处理过的程序--避免相互调用造成的死循环
              READ TABLE gt_prog INTO gs_prog WITH KEY name = ls_inc_tmp
                                                       from = lv_from
                                                       to   = lv_to.
              IF sy-subrc NE 0.
                gs_prog_part-main_name = is_prog-main_name.
                gs_prog_part-name = ls_inc_tmp.
                gs_prog_part-type = '02'.   "including program
                gs_prog_part-from = lv_from.
                gs_prog_part-to = lv_to.
                APPEND gs_prog_part TO ct_prog.
                APPEND gs_prog_part TO gt_prog.
                APPEND gs_prog_part TO lt_prog_next. "下一个PERFORM.
              ENDIF.
            ENDIF.


            CLEAR: lv_from_done,
                   lv_to_done,
                   lv_from,
                   lv_to.

          ENDLOOP.
        ENDLOOP.
      ENDIF.
      CLEAR: lt_form.
    ENDLOOP.

    lt_prog_form[] = lt_prog_next[].
    CLEAR: lt_prog_next[].

  ENDWHILE.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHECK_TABNAME
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_STOKEN1_STR  text
*      <--P_LV_SUBRC  text
*----------------------------------------------------------------------*
FORM check_tabname  USING    iv_tabname TYPE char30
                    CHANGING cv_subrc TYPE syst-subrc.

  SELECT SINGLE tabname
    FROM dd02l
    INTO @DATA(lv_tname)
    WHERE tabname = @iv_tabname.

  cv_subrc = sy-subrc.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHECK_PROGNAME
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_STOKEN1_STR  text
*      <--P_LV_SUBRC  text
*----------------------------------------------------------------------*
FORM check_progname  USING    iv_progname TYPE char30
                    CHANGING cv_subrc TYPE syst-subrc.

  SELECT SINGLE progname
    FROM reposrc
    INTO @DATA(lv_progname)
    WHERE progname = @iv_progname.

  cv_subrc = sy-subrc.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHECK_TCODE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_STOKEN2_STR  text
*      <--P_LV_SUBRC  text
*----------------------------------------------------------------------*
FORM check_tcode  USING    iv_tcode TYPE char30
                  CHANGING cv_subrc TYPE syst-subrc.

  DATA: lv_tcode TYPE tstc-tcode.

  lv_tcode = iv_tcode.
  "去除引号   'FB03'-->FB03.
  SHIFT lv_tcode RIGHT DELETING TRAILING space.
  SHIFT lv_tcode RIGHT DELETING TRAILING ''''.
  CONDENSE lv_tcode.
  SHIFT lv_tcode LEFT DELETING LEADING ''''.

  SELECT SINGLE tcode
    FROM tstc
    INTO lv_tcode
    WHERE tcode = lv_tcode.

  cv_subrc = sy-subrc.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_USER_COMMAND
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_user_command USING iv_ucomm TYPE sy-ucomm
                            is_selfield  TYPE slis_selfield.


  CASE iv_ucomm.
    WHEN '&IC1'.

      READ TABLE gt_result INTO gs_result INDEX is_selfield-tabindex.
      IF sy-subrc = 0.

        CASE is_selfield-fieldname.
          WHEN 'SELECT' OR
               'DELETE' OR
               'UPDATE' OR
               'INSERT' OR
               'CALLFUNC' OR
               'CALLBAPI' OR
               'CALLRFC' OR
               'CALLCLASS' OR
               'CALLTRAN' OR
               'SUBMIT' OR
               'FORMS' OR
               'BUTTON_T'
                .

            PERFORM show_detail_sql USING is_selfield-fieldname
                                          gs_result.

          WHEN OTHERS.
        ENDCASE.

      ENDIF.

    WHEN OTHERS.
  ENDCASE.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SHOW_DETAIL_SQL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_GS_RESULT  text
*----------------------------------------------------------------------*
FORM show_detail_sql  USING iv_fname TYPE char30
                            is_result TYPE ts_result.

  DATA: lt_structure TYPE lvc_t_fcat,
        ls_structure TYPE lvc_s_fcat,
        ls_layout    TYPE lvc_s_layo.
  DATA: lv_title TYPE lvc_title.

  CONSTANTS:
    lc_user_command_sub TYPE slis_formname VALUE 'FRM_USER_COMMAND_SUB'.
***gt_key_word

  CLEAR lt_structure.

  IF iv_fname = 'SELECT' OR
     iv_fname = 'UPDATE' OR
     iv_fname = 'INSERT' OR
     iv_fname = 'DELETE' OR
     iv_fname = 'CALLFUNC' OR
     iv_fname = 'CALLBAPI' OR
     iv_fname = 'CALLRFC' OR
     iv_fname = 'CALLTRAN' OR
     iv_fname = 'SUBMIT'.

    ls_structure-fieldname = 'NAME'.
    ls_structure-coltext = 'Program'.
    ls_structure-col_pos = 1.
    ls_structure-ref_table = ''.
    ls_structure-ref_field = ''.
    APPEND ls_structure TO lt_structure.

    ls_structure-fieldname = 'POSITION'.
    ls_structure-coltext = 'Position'.
    ls_structure-hotspot = 'X'.
    ls_structure-col_pos = 3.
    ls_structure-datatype = 'INT4'.
    ls_structure-dd_outlen = '255'.
    APPEND ls_structure TO lt_structure.
    CLEAR ls_structure.

    IF iv_fname = 'SELECT' OR
       iv_fname = 'UPDATE' OR
       iv_fname = 'INSERT' OR
       iv_fname = 'DELETE'.

    ls_structure-fieldname = 'DDTEXT'.
    ls_structure-coltext = 'TableName'.
    ls_structure-col_pos = 4.
    ls_structure-REF_TABLE = 'DD02T'.
    ls_structure-REF_FIELD = 'DDTEXT'.
    APPEND ls_structure TO lt_structure.
    CLEAR ls_structure.
    ENDIF.
  ENDIF.

  CLEAR ls_structure.
  ls_structure-fieldname = 'KEYNAME'.
  ls_structure-coltext = 'Value'.
  ls_structure-col_pos = 2.
  ls_structure-datatype = 'CHAR'.
  ls_structure-dd_outlen = '40'.
  APPEND ls_structure TO lt_structure.
  CLEAR ls_structure.

****创建dyn_table
*  CALL METHOD cl_alv_table_create=>create_dynamic_table
*    EXPORTING
*      it_fieldcatalog           = lt_structure
*    IMPORTING
*      ep_table                  = dy_table
*    EXCEPTIONS
*      generate_subpool_dir_full = 1
*      OTHERS                    = 2.
*  IF sy-subrc = 0.
*    "table
*    ASSIGN dy_table->* TO <dyn_table>.
*  ENDIF.
*
****dyn_table 赋值
*  CREATE DATA dy_line LIKE LINE OF <dyn_table>.
*  ASSIGN dy_line->* TO <dyn_wa>.

  DATA: lt_sort TYPE lvc_t_sort.

  lt_sort = VALUE #( ( fieldname = 'KEYNAME'
                       up = 'X' ) ).

  gt_detail[] = gt_key_word[].
  DELETE gt_detail WHERE type <> iv_fname.
  CHECK gt_detail[] IS NOT INITIAL.

  LOOP AT gt_detail ASSIGNING FIELD-SYMBOL(<ls_detail>).

    SELECT SINGLE ddtext FROM dd02t INTO <ls_detail>-ddtext
      WHERE tabname = <ls_detail>-keyname
        AND ddlanguage = 'E'.
  ENDLOOP.




  lv_title = iv_fname.
  ls_layout-zebra = abap_true.
  ls_layout-cwidth_opt = abap_true.
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = sy-repid
      is_layout_lvc           = ls_layout
      it_fieldcat_lvc         = lt_structure
      it_sort_lvc             = lt_sort
      i_callback_user_command = lc_user_command_sub
      i_save                  = 'X'
      i_grid_title            = lv_title
    TABLES
      t_outtab                = gt_detail
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  .
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_BASIC_FUNC_INFO
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_basic_func_info .

  DATA: lr_pgmna TYPE RANGE OF trdir-name,
        lt_tstc  TYPE TABLE OF tstc.
  DATA: lv_progname(50),
        lt_source  TYPE abaptxt255_tab.

***GET programs
  SELECT
    tfdir~funcname,
    tfdir~pname,
    tfdir~include,
    tfdir~pname_main
    INTO TABLE @DATA(lt_tfdir)
    FROM tfdir
    WHERE tfdir~funcname IN @s_fname.
  IF sy-subrc <> 0.
    MESSAGE s001(00) WITH 'No functions found!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.


  LOOP AT lt_tfdir INTO DATA(ls_tfdir).

    APPEND INITIAL LINE TO gt_prog ASSIGNING FIELD-SYMBOL(<ls_prog>).
*    <ls_prog>-main_name = ls_tfdir-funcname.

    CONCATENATE ls_tfdir-pname 'U' ls_tfdir-include INTO lv_progname.
    "SAPLXXX01--->LXXX01,  /BMW/SAPLXXX02--->/BMW/LXXX02
    REPLACE 'SAP' IN lv_progname WITH space .
    CONDENSE lv_progname.

    <ls_prog>-main_name = lv_progname.                  "Function对应的程序名
    <ls_prog>-name      = ls_tfdir-funcname.            "Function name
    <ls_prog>-type      = '02'.
    READ REPORT lv_progname INTO lt_source.
    <ls_prog>-from = 1.
    <ls_prog>-to = lines( lt_source ).
    <ls_prog>-lines = lines( lt_source ).
    UNASSIGN <ls_prog>.

    APPEND INITIAL LINE TO gt_result ASSIGNING FIELD-SYMBOL(<ls_result>).

    "Program
    <ls_result>-pgmna = lv_progname.        "Function对应的程序名
    <ls_result>-fname = ls_tfdir-funcname.  "Function name
    "Language
    "Create_ON
    "Package
    DATA(lv_group) = ls_tfdir-pname.
    REPLACE 'SAPL' IN lv_group WITH space .
    CONDENSE lv_group.
    SELECT SINGLE devclass, masterlang, created_on
      INTO ( @<ls_result>-devclass,
             @<ls_result>-spras,
             @<ls_result>-created_on )
      FROM tadir
      WHERE pgmid = 'R3TR' AND object = 'FUGR' AND obj_name = @lv_group.

    "Title
    SELECT SINGLE stext INTO <ls_result>-title FROM tftit
      WHERE funcname = <ls_result>-pgmna AND spras = <ls_result>-spras.
    "Package Desc.
    SELECT SINGLE ctext INTO <ls_result>-devclass_t FROM tdevct
      WHERE devclass = <ls_result>-devclass AND spras = <ls_result>-spras.
    "Package Component
    SELECT SINGLE component FROM tdevc INTO <ls_result>-component
      WHERE devclass = <ls_result>-devclass.
    "Last changed
    SELECT SINGLE udat FROM trdir INTO <ls_result>-changed_on
      WHERE name = <ls_result>-pgmna.
    "Lines
    <ls_result>-lines = lines( lt_source ).

    UNASSIGN <ls_result>.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  APPEND_CODE_STD
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_LR_CODE_STD  text
*----------------------------------------------------------------------*
FORM append_code_std  CHANGING cr_code_std LIKE gr_code_std.

  DATA: ls_code_std LIKE LINE OF gr_code_std.

  ls_code_std(3) = 'IEQ'.
  ls_code_std-low = '%ML'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%PC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%SC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%SC+'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%SL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ABC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ALL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AQW'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AUF'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AVE'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AVR'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CDF'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CFI'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&COUNT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRB'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRE'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRB'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRR'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&DAU'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&DOF'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&DON'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&EB9'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ELP'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ERW'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ETA'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&F03'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&F12'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&F15'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&IC1'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ILD'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ILT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&KOM'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&LFO'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&LIS'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&MAX'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&MIN'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&NFO'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&NTE'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OAD'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ODN'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OL0'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OLX'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OMP'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OPT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OUP'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&RNT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&RNT_PREV'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&SAL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&SUM'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&UMC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&XML'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&XPA'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&XXL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P+'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P++'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P-'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P--'. APPEND ls_code_std TO cr_code_std.

ENDFORM.


INCLUDE zscanner_f02.

*&---------------------------------------------------------------------*
*&  Include           ZSCANNER_F01
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Form  FRM_MODIFY_SCREEN
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_modify_screen .

  LOOP AT SCREEN.

    IF p_ck1 = abap_true.

      IF screen-group1 = 'M1'.
        screen-input = 0.
      ENDIF.

      IF screen-group1 = 'M4'.
        screen-active = 0.
      ENDIF.

    ELSE.

      IF screen-group1 = 'M3'.
        screen-active = 0.
      ENDIF.

      IF screen-group1 = 'M1'.
        screen-active = 0.
      ENDIF.

      IF screen-group1 = 'M2'.
        screen-input = 0.
      ENDIF.

    ENDIF.

    MODIFY SCREEN.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_BASIC_INFO
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_basic_info .

  DATA: lr_pgmna TYPE RANGE OF trdir-name,
        lt_tstc  TYPE TABLE OF tstc.
  DATA: lt_source  TYPE abaptxt255_tab.


  IF s_tcode IS NOT INITIAL.

    SELECT * FROM tstc
      INTO TABLE lt_tstc
      WHERE tcode IN s_tcode.
    IF sy-subrc = 0.

      lr_pgmna = VALUE #( FOR ls_tstc IN lt_tstc
                          ( sign = 'I'
                            option = 'EQ'
                            low = ls_tstc-pgmna ) ).
    ENDIF.
  ENDIF.


***GET programs
  SELECT
    tadir~object,
    tadir~obj_name,
    tadir~devclass,
    tadir~masterlang,
    tadir~component,
    tadir~created_on,
    tstc~tcode,
    reposrc~cnam
    INTO TABLE @DATA(lt_tadir)
    FROM tadir
    INNER JOIN reposrc ON reposrc~progname = tadir~obj_name
    LEFT JOIN tstc ON tstc~pgmna = tadir~obj_name             "NO TCODE IN-CASE
    WHERE reposrc~subc EQ '1'     "Executable program
      AND obj_name IN @lr_pgmna
      AND obj_name IN @s_pgmna
      AND pgmid = 'R3TR'
      AND object = 'PROG'
    .
  IF sy-subrc <> 0.
    MESSAGE s001(00) WITH 'No program found!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.


  LOOP AT lt_tadir INTO DATA(ls_tadir).

    APPEND INITIAL LINE TO gt_prog ASSIGNING FIELD-SYMBOL(<ls_prog>).
    <ls_prog>-main_name = ls_tadir-obj_name.
    <ls_prog>-name      = ls_tadir-obj_name.
    <ls_prog>-type      = '01'.
    READ REPORT ls_tadir-obj_name INTO lt_source.
    <ls_prog>-from = 1.
    <ls_prog>-to = lines( lt_source ).
    <ls_prog>-lines = lines( lt_source ).
    UNASSIGN <ls_prog>.

    APPEND INITIAL LINE TO gt_result ASSIGNING FIELD-SYMBOL(<ls_result>).
    "T-code
    <ls_result>-tcode = ls_tadir-tcode.
    "Program
    <ls_result>-pgmna = ls_tadir-obj_name.
    "Language
    <ls_result>-spras = ls_tadir-masterlang.
    "Create_ON
    <ls_result>-created_on = ls_tadir-created_on.
    "Package
    <ls_result>-devclass = ls_tadir-devclass.
    "Title
    SELECT SINGLE text INTO <ls_result>-title FROM trdirt
      WHERE name = <ls_result>-pgmna AND sprsl = <ls_result>-spras.
    "Package Desc.
    SELECT SINGLE ctext INTO <ls_result>-devclass_t FROM tdevct
      WHERE devclass = <ls_result>-devclass AND spras = <ls_result>-spras.
    "Package Component
    SELECT SINGLE component FROM tdevc INTO <ls_result>-component
      WHERE devclass = <ls_result>-devclass.
    "Last changed
    SELECT SINGLE udat FROM trdir INTO <ls_result>-changed_on
      WHERE name = <ls_result>-pgmna.

    UNASSIGN <ls_result>.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DEVC_PGMNA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_devc_pgmna .

  DATA: lv_program TYPE sy-repid,
        lt_inc_tmp TYPE TABLE OF tadir-obj_name.
  DATA: lt_source  TYPE abaptxt255_tab.

***Get includes
  LOOP AT gt_prog INTO DATA(ls_pgmna).

    lv_program = ls_pgmna-name.
    CALL FUNCTION 'RS_GET_ALL_INCLUDES'
      EXPORTING
        program    = lv_program
      TABLES
        includetab = lt_inc_tmp
      EXCEPTIONS
        OTHERS     = 0.

    LOOP AT lt_inc_tmp INTO DATA(ls_inc_tmp).
      gs_prog-main_name = lv_program.       "main
      gs_prog-name = ls_inc_tmp.            "include
      gs_prog-type = '01'.                  "01-program, 02-function, 03-class
      READ REPORT ls_inc_tmp INTO lt_source.
      gs_prog-from = 1.
      gs_prog-to = lines( lt_source ).
      gs_prog-lines = lines( lt_source ).
      APPEND gs_prog TO gt_prog.
      CLEAR gs_prog.
    ENDLOOP.
*    APPEND LINES OF lt_inc_tmp TO gt_prog.

  ENDLOOP.

  SORT gt_prog BY main_name name.
  DELETE ADJACENT DUPLICATES FROM gt_prog COMPARING main_name name.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SEARCH_SOURCE_CALLFUNC
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM search_source_callfunc USING it_prog TYPE tt_prog
                            CHANGING ct_function TYPE tt_function
                                     ct_function_std TYPE tt_function
                                     ct_bapis TYPE tt_function .

  DATA: lt_source  TYPE abaptxt255_tab,
        lt_results TYPE match_result_tab.
  DATA: lt_function TYPE tt_function,
        lv_regex    TYPE string,
        lv_regex2   TYPE string.


  PERFORM frm_pattern_call_function USING 'CALL_FUNCTION'
                                    CHANGING lv_regex
                                             lv_regex2.

  LOOP AT it_prog INTO gs_prog.
    IF NOT ( sy-tabix >= gs_prog-from AND sy-tabix <= gs_prog-to ).
      EXIT.
    ENDIF.

    READ REPORT gs_prog-name INTO lt_source.
    IF sy-subrc <> 0.
      CONTINUE.
    ENDIF.

    FIND ALL OCCURRENCES OF REGEX lv_regex IN TABLE lt_source
      IN CHARACTER MODE
      IGNORING CASE
      RESULTS lt_results.

    IF lt_results[] IS NOT INITIAL.
*      lv_found = abap_true.
      LOOP AT lt_results INTO DATA(ls_results).

        READ TABLE lt_source INTO DATA(ls_source2) INDEX ls_results-line.
        IF sy-subrc = 0.
          "是注释行时 continue
          IF ls_source2-line(1) = '*'.
            CONTINUE.
          ENDIF.

          SEARCH ls_source2-line FOR '"'.
          IF sy-subrc = 0 AND sy-fdpos <= ls_results-offset.
            CONTINUE.
          ENDIF.
        ENDIF.


        PERFORM frm_get_hit_set USING lt_source
                                      gs_prog-name
                                      ls_results-line.

        PERFORM frm_get_fm_name USING lt_source
                                      lv_regex
                                      ls_results-line
                                      gs_prog-main_name
                                      gs_prog-name
                                CHANGING ct_function
                                         ct_function_std
                                         ct_bapis.

      ENDLOOP.
    ENDIF.






  ENDLOOP.



ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DEVC_CLASS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_devc_class .

  DATA: lt_wbcrossgt TYPE TABLE OF wbcrossgt,
        lt_class     TYPE tt_class.


  LOOP AT gt_result INTO gs_result.

    "逐个程序处理
    DATA(lt_prog) = gt_prog.
    DELETE lt_prog WHERE main_name NE gs_result-pgmna.


    WHILE lt_prog[] IS NOT INITIAL.
***Search source
      "程序里 找出 class
      PERFORM search_source_class USING lt_prog
                                  CHANGING lt_wbcrossgt.

      CLEAR lt_prog.
***class 找出 class程序名(到function)
      PERFORM get_class_obj USING gs_result-pgmna
                                  lt_wbcrossgt
                            CHANGING lt_prog
                                     lt_class.
    ENDWHILE.


    SORT lt_class BY main_name class_name.
    DELETE ADJACENT DUPLICATES FROM lt_class COMPARING main_name class_name.

    "拼接class
    LOOP AT lt_class INTO DATA(ls_class).
      gs_result-callclass =  ls_class-class_name && ',' && gs_result-callclass.
      CONDENSE gs_result-callclass.
      append_to_key_word: gs_result-pgmna
                          ls_class-class_name
                          ls_class-class_name
                          1
                          'CALLCLASS'.         "CALL_CLASS
    ENDLOOP.
    CLEAR lt_class.

    MODIFY gt_result FROM gs_result TRANSPORTING callclass.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DEVC_FUNC
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_devc_func .

  DATA: lt_function     TYPE tt_function,
        lt_function_std TYPE tt_function,
        lt_bapis        TYPE tt_function,
        lt_function_all TYPE tt_function,
        lt_bapis_all    TYPE tt_function.

  DATA: lt_wbcrossgt TYPE TABLE OF wbcrossgt,
        lt_class     TYPE tt_class.

  DATA: lt_prog_next       TYPE tt_prog,
        lv_start_from_se37.

  IF p_ck1 = abap_true.
    lv_start_from_se37 = abap_false.
  ELSE.
    lv_start_from_se37 = abap_true.
  ENDIF.

  LOOP AT gt_result INTO gs_result.

    "逐个程序处理
    DATA(lt_prog) = gt_prog.
    DELETE lt_prog WHERE main_name NE gs_result-pgmna.


    WHILE lt_prog[] IS NOT INITIAL.

      IF lv_start_from_se37 = abap_false.
***Search source
        "程序里 找出 function
        PERFORM search_source_callfunc USING lt_prog
                                       CHANGING lt_function
                                                lt_function_std
                                                lt_bapis.
        CLEAR lv_start_from_se37.
      ELSE.
        "初始 function
        lt_function = VALUE #(  FOR ls_prog2 IN lt_prog
                                  ( main_name = ls_prog2-main_name
                                    name = ls_prog2-name
                                    type = ls_prog2-type ) ).
      ENDIF.

***get function programs.
      IF p_fugr = abap_true.
        "function里找出程序名,  继续下一次程序找function
        PERFORM get_function_obj  USING gs_result-pgmna
                                        lt_function
                                  CHANGING lt_prog_next.    "call function IN call function.

      ENDIF.

      CLEAR lt_function.

***Search source
      "程序里 找出 class
      PERFORM search_source_class USING lt_prog
                                  CHANGING lt_wbcrossgt.

***get class programs.
      IF p_cinc = abap_true.
        "class 找出 class程序名(到function)
        PERFORM get_class_obj USING gs_result-pgmna
                                    lt_wbcrossgt
                              CHANGING lt_prog_next
                                       lt_class.
      ENDIF.

      lt_prog[] = lt_prog_next[].
      CLEAR: lt_prog_next,
             lt_wbcrossgt,
             lt_function,
             lt_function_std,
             lt_bapis.
    ENDWHILE.


*    SORT gt_function by type name.
    LOOP AT gt_function INTO gs_function WHERE main_name = gs_result-pgmna.
      "01-function, 02-BAPI, 03-STD.function
      IF gs_function-type = '01'.
        CONCATENATE gs_function-name gs_result-callfunc
        INTO gs_result-callfunc SEPARATED BY ','.
        CONDENSE gs_result-callfunc.
        "append to keyword.
        append_to_key_word: gs_result-pgmna
                            gs_function-pname
                            gs_function-name
                            gs_function-position
                            'CALLFUNC'.

      ELSEIF gs_function-type = '04'.
        CONCATENATE gs_function-name gs_result-callrfc
        INTO gs_result-callrfc SEPARATED BY ','.
        CONDENSE gs_result-callrfc.
        "append to keyword.
        append_to_key_word: gs_result-pgmna
                            gs_function-pname
                            gs_function-name
                            gs_function-position
                            'CALLRFC'.

      ELSE.
        CONCATENATE gs_function-name gs_result-callbapi
        INTO gs_result-callbapi SEPARATED BY ','.
        CONDENSE gs_result-callbapi.
        "append to keyword.
        append_to_key_word: gs_result-pgmna
                            gs_function-pname
                            gs_function-name
                            gs_function-position
                            'CALLBAPI'.

      ENDIF.
    ENDLOOP.


***CLASS
    SORT lt_class BY main_name class_name.
    DELETE ADJACENT DUPLICATES FROM lt_class COMPARING main_name class_name.
    APPEND LINES OF lt_class TO gt_class.

    "拼接class
    LOOP AT lt_class INTO DATA(ls_class) WHERE main_name = gs_result-pgmna.
      gs_result-callclass =  ls_class-class_name && ',' && gs_result-callclass.
      CONDENSE gs_result-callclass.
      "append to keyword.
      append_to_key_word: gs_result-pgmna
                          ls_class-class_name
                          ls_class-class_name
                          1
                          'CALLCLASS'.         "CALL_CLASS
    ENDLOOP.
    CLEAR lt_class.

*    MODIFY gt_result FROM gs_result TRANSPORTING callfunc callbapi callclass.
    MODIFY gt_result FROM gs_result TRANSPORTING callfunc callbapi callrfc callclass.
    CLEAR: gs_result.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_function_OBJ
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_function  text
*      <--P_GT_prog  text
*----------------------------------------------------------------------*
FORM get_function_obj  USING  iv_main_name TYPE program_id
                              it_function TYPE tt_function
                        CHANGING ct_prog TYPE tt_prog.

  DATA: lv_progname TYPE char100,
        ls_prog     TYPE ts_prog.
  DATA: lt_source  TYPE abaptxt255_tab.

  CHECK it_function[] IS NOT INITIAL.

  SELECT *
    FROM tfdir
    INTO TABLE @DATA(lt_tfdir)
    FOR ALL ENTRIES IN @it_function
    WHERE funcname = @it_function-name.
  IF sy-subrc = 0.

    LOOP AT lt_tfdir INTO DATA(ls_tfdir).

      CONCATENATE ls_tfdir-pname 'U' ls_tfdir-include INTO lv_progname.
      "SAPLXXX01--->SAPLXXX01,  /BMW/SAPLXXX02--->/BMW/LXXX02
      REPLACE 'SAP' IN lv_progname WITH space .
      CONDENSE lv_progname.

      "CHECK是未处理过的程序--避免相互调用造成的死循环
      READ TABLE gt_prog INTO gs_prog WITH KEY name = lv_progname
                                               from = 1
                                               to   = lines( lt_source ).
      IF sy-subrc NE 0.

        ls_prog-main_name = iv_main_name.
        ls_prog-name = lv_progname.
        ls_prog-type = '02'.
        READ REPORT lv_progname INTO lt_source.
        ls_prog-from = 1.
        ls_prog-to = lines( lt_source ).
        ls_prog-lines = lines( lt_source ).
        APPEND ls_prog TO ct_prog.
        APPEND ls_prog TO gt_prog.

        "遍历当前程序体里的PERFORM调用.
        PERFORM frm_search_source_form USING ls_prog
                                       CHANGING ct_prog .

        CLEAR ls_prog.
      ENDIF.


    ENDLOOP.

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_HIT_SET
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_GT_SOURCE  text
*      -->P_gs_prog_NAME  text
*      -->P_LS_RESULTS_LINE  text
*----------------------------------------------------------------------*
FORM frm_get_hit_set  USING    it_abap TYPE abaptxt255_tab
                               iv_pgmna_name TYPE trdir-name
                               iv_tabix TYPE match_result-line.

  DATA: lv_end     TYPE i,
        lv_start   TYPE i,
        lv_xtabix  TYPE sy-tabix,
        lv_hitline TYPE xfeld.
  DATA: gv_hit_count TYPE i.

  DATA: ls_col LIKE LINE OF gs_alv_item-cell_color.

  FIELD-SYMBOLS:
    <lv_abap> TYPE any.

  lv_start = iv_tabix - 2 .
  lv_end   = iv_tabix + 2.

  IF lv_start < 1.
    lv_start = 1.
  ENDIF.

  WHILE lv_start <= lv_end.
    READ TABLE it_abap ASSIGNING <lv_abap> INDEX lv_start.
    IF sy-subrc IS NOT INITIAL.
      EXIT.
    ENDIF.

    lv_xtabix = sy-tabix.

    IF lv_start = iv_tabix.
      lv_hitline = 'X'.
    ELSE.
      CLEAR lv_hitline.
    ENDIF.

    ADD 1 TO lv_start.


    IF <lv_abap>(1) = '*'
    OR <lv_abap>(1) = '"'.
      CONTINUE.
    ENDIF.

    gs_alv_item-repname = iv_pgmna_name.
    gs_alv_item-line_no = lv_xtabix.
    gs_alv_item-text    = <lv_abap>.

    IF lv_hitline IS NOT INITIAL.
      gs_alv_item-hit = 'X'.
      ADD 1 TO gv_hit_count.
      ls_col-fname     = 'TEXT'.
      ls_col-color-col = '5'.
      APPEND ls_col TO gs_alv_item-cell_color.
    ENDIF.

    APPEND gs_alv_item TO gt_alv_item.

    CLEAR gs_alv_item.

  ENDWHILE.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_FM_NAME
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_SOURCE  text
*      -->P_LS_RESULTS_LINE  text
*      <--P_LT_function  text
*----------------------------------------------------------------------*
FORM frm_get_fm_name  USING    it_abap TYPE abaptxt255_tab
                               iv_regex TYPE string
                               iv_tabix TYPE match_result-line
                               iv_main_name  TYPE trdir-name
                               iv_pname  TYPE trdir-name
                      CHANGING ct_function TYPE tt_function
                               ct_function_std TYPE tt_function
                               ct_bapis TYPE tt_function .


  DATA: lv_exit,
        lv_character,
        lv_fname(30),
        lv_fdpos TYPE i.
  DATA: ls_function TYPE ts_function.

  CLEAR lv_exit.
  LOOP AT it_abap INTO DATA(ls_abap) FROM iv_tabix.

    DATA(lv_index) = iv_tabix.  "line

    FIND REGEX iv_regex IN ls_abap-line IGNORING CASE.
    IF sy-subrc = 0.

      DO 10 TIMES.  "search 10 lines at most

        READ TABLE it_abap INTO DATA(ls_abap_curr) INDEX lv_index.

        SEARCH ls_abap_curr-line FOR '''' .
        IF sy-subrc = 0.

          lv_fdpos = sy-fdpos.
          DO 30 TIMES.

            lv_fdpos = lv_fdpos + 1.
            lv_character = ls_abap_curr-line+lv_fdpos(1).
            IF lv_character = ''''.
              EXIT.
            ELSE.
              lv_fname = lv_fname && lv_character.
            ENDIF.
          ENDDO.

          CONDENSE lv_fname.
          ls_function-main_name = iv_main_name.
          ls_function-pname = iv_pname.   "function位置所在的程序
          ls_function-position = lv_index.   "function位置所在的程序行
          ls_function-name = lv_fname.
          SELECT SINGLE funcname INTO lv_fname FROM tfdir WHERE funcname = lv_fname.
          IF sy-subrc = 0.
            "是当前系统function.
            IF lv_fname(1) = 'Z' OR lv_fname(5) = '/BMW/'.
              ls_function-type = '01'.
              APPEND ls_function TO gt_function.
              APPEND ls_function TO ct_function.
            ELSEIF lv_fname(4) = 'BAPI'.
              ls_function-type = '02'.
              APPEND ls_function TO gt_function.
              APPEND ls_function TO ct_bapis.
            ELSE.
              ls_function-type = '03'.
              APPEND ls_function TO gt_function.
              APPEND ls_function TO ct_function_std.
            ENDIF.

          ELSE.
            "是destination系统

*            ZSCANNER_F01
            FIND REGEX 'DESTINATION' IN ls_abap-line IGNORING CASE.
            IF sy-subrc NE 0.

              DATA(lv_next) = iv_tabix + 1.
              LOOP AT it_abap INTO DATA(ls_abap_rfc) FROM lv_next.
                IF ls_abap_rfc(1) = '*' OR ls_abap_rfc IS INITIAL.
                  CONTINUE.
                ELSE.
                  "非注释行&非空行&非"DEST.行 --- 校验DESTINATION.
                  FIND REGEX 'DESTINATION' IN ls_abap_rfc-line IGNORING CASE.
                  IF sy-subrc = 0.
                    FIND REGEX '"\s+DESTINATION' IN ls_abap_rfc-line IGNORING CASE.
                    IF sy-subrc NE 0.
                      ls_function-type = '04'.      "RFC.
                      APPEND ls_function TO gt_function.
                    ENDIF.
                  ENDIF.
                  EXIT. "检测到非空行即跳出
                ENDIF.
              ENDLOOP.

            ELSE.
              ls_function-type = '04'.      "RFC.
              APPEND ls_function TO gt_function.
            ENDIF.



          ENDIF.

          lv_exit = abap_true.
          EXIT.
        ELSE.
          "next line
          lv_index = lv_index + 1.
          CONTINUE.

        ENDIF.
      ENDDO.

      IF lv_exit = abap_true..
        EXIT.
      ENDIF.

      CLEAR lv_fname.

    ELSE.
    ENDIF.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_PATTERN_CALL_FUNCTION
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_0183   text
*      <--P_LV_REGEX  text
*----------------------------------------------------------------------*
FORM frm_pattern_call_function  USING    iv_type TYPE char20
                                CHANGING cv_regex TYPE string
                                         cv_regex2 TYPE string.

  CASE iv_type.
    WHEN 'CALL_FUNCTION'.
      "Start with 'CALL', end with 'FUNCTION'
      cv_regex = '\<CALL\s+FUNCTION\>'.
      cv_regex2 = '"\s+\<CALL\s+FUNCTION\>'.

    WHEN 'CREATE_OBJECT'.

    WHEN OTHERS.
  ENDCASE.


ENDFORM.










*&---------------------------------------------------------------------*
*&      Form  FRM_ALV_prog
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_alv_list .

  CONSTANTS:
    lc_pf_status    TYPE slis_formname VALUE 'FRM_PF_STATUS',
    lc_user_command TYPE slis_formname VALUE 'FRM_USER_COMMAND'.

  DATA: lv_repid    TYPE sy-repid,
        ls_layout   TYPE lvc_s_layo,
        lt_fieldcat TYPE lvc_t_fcat.

  lv_repid = sy-repid.
  ls_layout-zebra = abap_true.
  ls_layout-box_fname = 'SEL'.
  PERFORM frm_set_fieldcat CHANGING lt_fieldcat.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = lv_repid
      is_layout_lvc           = ls_layout
*     i_grid_title            =
      it_fieldcat_lvc         = lt_fieldcat
*     i_callback_pf_status_set = lc_pf_status
      i_callback_user_command = lc_user_command
      i_save                  = 'X'
    TABLES
      t_outtab                = gt_result[]
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  .
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_SET_FIELDCAT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_LT_FIELDCAT  text
*----------------------------------------------------------------------*
FORM frm_set_fieldcat CHANGING ct_fieldcat TYPE lvc_t_fcat.

  DATA: ls_fieldcat TYPE lvc_s_fcat.

  DEFINE marco_fieldcat.

    CLEAR ls_fieldcat.
    ls_fieldcat-key        = &1.
    ls_fieldcat-fieldname  = &2.
    ls_fieldcat-coltext    = &3.
    ls_fieldcat-col_opt    = &4.
    ls_fieldcat-hotspot    = &5.
    ls_fieldcat-ref_field = &6.
    ls_fieldcat-ref_table = &7.
    APPEND ls_fieldcat TO ct_fieldcat.
  END-OF-DEFINITION.


  marco_fieldcat:
    'X'  'TCODE'      'T-code'     'X' ''  ''  '',
    'X'  'PGMNA'      'Program'    'X' ''  ''  '',
    ''   'INSTANCE'   'Instance'   'X' ''  ''  '',
    ''   'TITLE'      'Title'      'X' ''  ''  '',
    ''   'SPRAS'      'Language'   'X' ''  ''  '',
    ''   'CREATED_ON' 'Created on' 'X' ''  ''  '',
    ''   'CHANGED_ON' 'Changed on' 'X' ''  ''  '',
    ''   'DEVCLASS'   'Package'    'X' ''  ''  '',
    ''   'DEVCLASS_T' 'Package Desc.'      'X' ''  ''  '',
    ''   'COMPONENT'  'Package Component'  'X' ''  ''  '',
    ''   'SELECT'    'Select table'       'X' 'X'  ''  '',
    ''   'INSERT'    'Insert table'       'X' 'X'  ''  '',
    ''   'DELETE'    'Delete table'       'X' 'X'  ''  '',
    ''   'UPDATE'    'Update table'       'X' 'X'  ''  '',
    ''   'CALLFUNC'   'call Function'      'X' 'X'  ''  '',
    ''   'CALLBAPI'   'call Bapi'          'X' 'X'  ''  '',
    ''   'CALLRFC'    'call RFC'           'X' 'X'  ''  '',
    ''   'CALLCLASS'  'Class/Interface'    'X' 'X'  ''  '',
    ''   'CALLTRAN'   'call TRANSACTION'   'X' 'X'  ''  '',
    ''   'SUBMIT'    'Submit program'     'X' 'X'  ''  '',
    ''   'FORMS'      'Print Form'         'X' 'X'  ''  '',
    ''   'ISALV'      'ALV Display'        'X' ''  ''  '',
    ''   'LINES'      'Coding Line'        'X' ''  ''  '',
    ''   'BUTTON_T'   'Button text'        'X' 'X'  ''  ''.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SEARCH_SOURCE_CLASS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_PROG  text
*      <--P_LT_FUNCTION  text
*      <--P_LT_FUNCTION_STD  text
*      <--P_LT_BAPIS  text
*----------------------------------------------------------------------*
FORM search_source_class  USING    it_prog TYPE tt_prog
                          CHANGING ct_wbcrossgt TYPE wbcrossgtt.

  SELECT *
    FROM wbcrossgt
    INTO TABLE ct_wbcrossgt
    FOR ALL ENTRIES IN it_prog
    WHERE include = it_prog-name
      AND otype = 'ME' .     "METHOD
*      AND ( otype = 'TY'    "CLASS
*           OR otype = 'ME' ). "METHOD

  .

  "删除标准的CLASS.
  DELETE ct_wbcrossgt WHERE name(1) NE 'Z' AND name(5) NE '/BMW/'.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_CLASS_OBJ
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_WBCROSSGT  text
*      <--P_LT_PROG  text
*----------------------------------------------------------------------*
FORM get_class_obj  USING    iv_main_name TYPE program_id
                             it_wbcrossgt TYPE wbcrossgtt
                    CHANGING ct_prog TYPE tt_prog
                             ct_class TYPE tt_class.

  DATA: ls_prog  TYPE ts_prog,
        ls_tmdir TYPE tmdir,
        lt_tmdir TYPE TABLE OF tmdir.
  DATA: lv_suffix       TYPE c LENGTH 5,
        lv_progname(50),
        lv_flag(30).
  DATA: lt_source  TYPE abaptxt255_tab.

  LOOP AT it_wbcrossgt INTO DATA(ls_wbcrossgt) WHERE otype = 'ME'.

    SPLIT ls_wbcrossgt-name AT '\ME:' INTO ls_tmdir-classname ls_tmdir-methodname.

***CLASS name
    gs_class-main_name = iv_main_name.         "MAIN_NAME
    gs_class-class_name = ls_tmdir-classname.  "CLASS
    APPEND gs_class TO ct_class.
    CLEAR gs_class.


    SELECT * FROM tmdir INTO TABLE lt_tmdir
      WHERE classname = ls_tmdir-classname
        AND methodname = ls_tmdir-methodname.
    IF sy-subrc = 0.

      LOOP AT lt_tmdir INTO ls_tmdir.

        PERFORM convert_numc_35 USING ls_tmdir-methodindx
                                CHANGING lv_suffix.

        "/BMW/XXXXXX====MCNNN 总长度是35.
        DATA(lv_length) = 30 - strlen( ls_tmdir-classname ).

        DO lv_length TIMES.
          lv_flag = lv_flag && '='.
          CONDENSE lv_flag.
        ENDDO.
        lv_progname = ls_tmdir-classname && lv_flag && lv_suffix.

        "CHECK是未处理过的程序--避免相互调用造成的死循环
        READ TABLE gt_prog INTO gs_prog WITH KEY name = lv_progname.
        IF sy-subrc NE 0.
          ls_prog-main_name = iv_main_name.
          ls_prog-name = lv_progname.
          ls_prog-type = '03'.
          READ REPORT lv_progname INTO lt_source.
          ls_prog-from = 1.
          ls_prog-to = lines( lt_source ).
          ls_prog-lines = lines( lt_source ).
          APPEND ls_prog TO ct_prog.
          APPEND ls_prog TO gt_prog.
          CLEAR ls_prog.
        ENDIF.

        CLEAR lv_flag.
      ENDLOOP.
    ENDIF.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CONVERT_NUMC_35
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_TMDIR_METHODINDX  text
*      <--P_LV_SUFFIX  text
*----------------------------------------------------------------------*
FORM convert_numc_35  USING    iv_methodindx
                      CHANGING cv_suffix TYPE char5.

  CONSTANTS: lc_character TYPE c LENGTH 36 VALUE '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

  DATA: lv_mod TYPE numc2,
        lv_div TYPE numc2.

  lv_div = iv_methodindx DIV 36.
  lv_mod = iv_methodindx MOD 36.

  cv_suffix = 'CM' && lv_div && lc_character+lv_mod(1).

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_KEY_WORD_SCAN
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_key_word_scan .

  DATA: lv_subrc TYPE sy-subrc.
  DATA: lt_source  TYPE abaptxt255_tab.

  DATA: lt_keywrd_sel    TYPE abaptxt255_tab,
        lt_keywrd_ins    TYPE abaptxt255_tab,
        lt_keywrd_del    TYPE abaptxt255_tab,
        lt_keywrd_upd    TYPE abaptxt255_tab,
        lt_keywrd_submit TYPE abaptxt255_tab,
        lt_keywrd_call   TYPE abaptxt255_tab,
        lt_stoken        TYPE stoken_tab,
        lt_sstmnt        TYPE sstmnt_tab.

  DATA: lr_code_std TYPE RANGE OF rsmptexts-obj_code.

  lt_keywrd_sel[] = VALUE #( ( line = 'SELECT'  ) ).
  lt_keywrd_ins[] = VALUE #( ( line = 'INSERT'  ) ).
  lt_keywrd_del[] = VALUE #( ( line = 'DELETE'  ) ).
  lt_keywrd_upd[] = VALUE #( ( line = 'UPDATE'  ) ).
  lt_keywrd_submit[] = VALUE #( ( line = 'SUBMIT'  ) ).
  lt_keywrd_call[] = VALUE #( ( line = 'CALL'  ) ).

  LOOP AT gt_prog INTO gs_prog.

    READ REPORT gs_prog-name INTO lt_source.

***SELECT
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_sel
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.

    "select xxx from db.
    "select xxx from db-a join db-b xxxx
    LOOP AT lt_stoken INTO DATA(ls_stoken) WHERE ( str = 'FROM' OR str = 'JOIN' ).
      DATA(lv_index) = sy-tabix + 1.
      "FROM 下一行是表名称
      READ TABLE lt_stoken INTO DATA(ls_stoken1) INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'SELECT'.           "SELECT

        ENDIF.
      ENDIF.
    ENDLOOP.


***INSERT
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_ins
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "insert db from xxx.
    "insert into db values xxx.
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'INSERT' OR str = 'INTO' ).
      lv_index = sy-tabix + 1.
      "下一行是表名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'INSERT'.           "INSERT

        ENDIF.
      ENDIF.
    ENDLOOP.


***DELETE
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_del
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "delete db from itab xxxx
    "delete from db where xxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'DELETE' OR str = 'FROM' ).
      lv_index = sy-tabix + 1.
      "下一行是表名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'DELETE'.           "DELETE

        ENDIF.
      ENDIF.
    ENDLOOP.


***UPDATE
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_upd
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "delete db from xxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'UPDATE' ).
      lv_index = sy-tabix + 1.
      "下一行是表名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_tabname USING ls_stoken1-str
                              CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'UPDATE'.           "UPDATE

        ENDIF.
      ENDIF.
    ENDLOOP.

***SUBMIT.
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_submit
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "delete db from xxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'SUBMIT' ).
      lv_index = sy-tabix + 1.
      "下一行是程序名称
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        PERFORM check_progname USING ls_stoken1-str
                               CHANGING lv_subrc.
        IF lv_subrc = 0.
          append_to_key_word: gs_prog-main_name
                              gs_prog-name
                              ls_stoken1-str
                              ls_stoken1-row
                              'SUBMIT'.           "UPDATE

        ENDIF.
      ENDIF.
    ENDLOOP.

***CALL TRANSACTION
    SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd_call
                               TOKENS INTO lt_stoken
                               STATEMENTS INTO lt_sstmnt.
    "call transaction xxxxx
    LOOP AT lt_stoken INTO ls_stoken WHERE ( str = 'CALL' ).
      lv_index = sy-tabix + 1.
      "下一行是TRANSACTION.
      READ TABLE lt_stoken INTO ls_stoken1 INDEX lv_index.
      IF sy-subrc = 0.
        TRANSLATE ls_stoken1-str TO UPPER CASE.
        CHECK ls_stoken1-str = 'TRANSACTION'.
        lv_index = lv_index + 1.
        "下一行是TCODE名称
        READ TABLE lt_stoken INTO DATA(ls_stoken2) INDEX lv_index.
        IF sy-subrc = 0.
          PERFORM check_tcode USING ls_stoken2-str
                                 CHANGING lv_subrc.
          IF lv_subrc = 0.
            append_to_key_word: gs_prog-main_name
                                gs_prog-name
                                ls_stoken2-str
                                ls_stoken2-row
                                'CALL_TRANSACTION'.         "CALL_TRANSACTION

          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDLOOP.


  SORT gt_key_word.
  DELETE ADJACENT DUPLICATES FROM gt_key_word COMPARING ALL FIELDS.

  "standard function-code
  PERFORM append_code_std CHANGING lr_code_std.

  "更新到result表
  LOOP AT gt_result INTO gs_result.

    LOOP AT gt_key_word INTO gs_key_word WHERE main_name = gs_result-pgmna.

      CASE gs_key_word-type.
        WHEN 'SELECT'.
          gs_result-select = gs_key_word-keyname && ',' && gs_result-select.
          CONDENSE gs_result-select.
        WHEN 'INSERT'.
          gs_result-insert = gs_key_word-keyname && ',' && gs_result-insert.
          CONDENSE gs_result-insert.
        WHEN 'DELETE'.
          gs_result-delete = gs_key_word-keyname && ',' && gs_result-delete.
          CONDENSE gs_result-delete.
        WHEN 'UPDATE'.
          gs_result-update = gs_key_word-keyname && ',' && gs_result-update.
          CONDENSE gs_result-update.
        WHEN 'SUBMIT'.
          gs_result-submit = gs_key_word-keyname && ',' && gs_result-submit.
          CONDENSE gs_result-submit.
        WHEN 'CALL_TRANSACTION'.
          gs_result-calltran = gs_key_word-keyname && ',' && gs_result-calltran.
          CONDENSE gs_result-calltran.

      ENDCASE.

    ENDLOOP.

***lines
    LOOP AT gt_prog INTO gs_prog WHERE main_name = gs_result-pgmna.
      gs_result-lines = gs_result-lines + ( gs_prog-to - gs_prog-from + 1 ).
    ENDLOOP.

***button
    SELECT * FROM rsmptexts
      INTO TABLE @DATA(lt_rsmptexts)
      WHERE progname = @gs_result-pgmna
        AND obj_type = 'F'
        AND texttype IN ('Q','M','I')  "I-icon info,  M-Object text, Q-quick info.
        AND obj_code NOT IN @lr_code_std.

    "优先取icon info,再取Object text, 最后取quick info.
    SORT lt_rsmptexts BY progname obj_code obj_type texttype.
    DELETE ADJACENT DUPLICATES FROM lt_rsmptexts COMPARING progname obj_code obj_type .
    LOOP AT lt_rsmptexts INTO DATA(ls_rsmptexts).
      gs_result-button_t = ls_rsmptexts-text && ',' && gs_result-button_t.
      CONDENSE gs_result-button_t.

      gs_key_word-main_name = gs_result-pgmna.
*      gs_key_word-keyname = ls_rsmptexts-obj_code.
      gs_key_word-keyname = ls_rsmptexts-text.
      gs_key_word-type = 'BUTTON_T'.    "插入到key_word表 用于双击分解?
      APPEND gs_key_word TO gt_key_word.
      CLEAR gs_key_word.
    ENDLOOP.


***Smartforms
    READ TABLE gt_function INTO gs_function WITH KEY type = '03'
                                                     name = 'SSF_FUNCTION_MODULE_NAME'.
    IF sy-subrc = 0.
      "存在 调smartforms.
      "----->如何找smartforms名称.
    ENDIF.

    MODIFY gt_result FROM gs_result.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_SEARCH_SOURCE_FORM
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_PROG  text
*----------------------------------------------------------------------*
FORM frm_search_source_form  USING  is_prog TYPE ts_prog
                             CHANGING ct_prog TYPE tt_prog.

  DATA: lt_source  TYPE abaptxt255_tab,
        lt_results TYPE match_result_tab.
  DATA: lt_function  TYPE tt_function,
        lv_regex     TYPE string,
        lv_regex2    TYPE string,
        lv_regex3    TYPE string,
        lv_regex4    TYPE string,
        lv_from_done,
        lv_to_done.

  DATA: lt_keywrd  TYPE abaptxt255_tab,
        lt_keywrd2 TYPE abaptxt255_tab,
        lt_stoken  TYPE stoken_tab,
        lt_sstmnt  TYPE sstmnt_tab.

  DATA: lv_program TYPE sy-repid,
        lt_inc_tmp TYPE TABLE OF tadir-obj_name.
  DATA: lt_prog_form TYPE tt_prog,
        lt_prog_next TYPE tt_prog.


  TYPES: BEGIN OF ts_form,
           str TYPE token_str,
         END OF ts_form.
  DATA: ls_form TYPE ts_form,
        lt_form TYPE TABLE OF ts_form.

  DATA: lv_index TYPE i,
        lv_from  TYPE i,
        lv_to    TYPE i.

  PERFORM frm_pattern_call_function USING 'PERFORM'
                                    CHANGING lv_regex
                                             lv_regex2.

*  READ REPORT is_prog-name INTO lt_source.

  lt_keywrd[] = VALUE #( ( line = 'PERFORM'  ) ).

  lt_prog_form = VALUE #( ( main_name = is_prog-main_name
                            name = is_prog-name
                            type = is_prog-type
                            from = is_prog-from
                            to = is_prog-to ) ).

  WHILE lt_prog_form[] IS NOT INITIAL.

    LOOP AT lt_prog_form INTO DATA(ls_prog_form).

***读取PERFORMS.
      READ REPORT ls_prog_form-name INTO lt_source.

      SCAN ABAP-SOURCE lt_source KEYWORDS FROM lt_keywrd
                                 TOKENS INTO lt_stoken
                                 STATEMENTS INTO lt_sstmnt.
      "删除范围外的mapping行
      DELETE lt_stoken WHERE row LT ls_prog_form-from OR row GT ls_prog_form-to.
      CHECK lt_stoken[] IS NOT INITIAL.

      CHECK lt_sstmnt[] IS NOT INITIAL.
      LOOP AT lt_stoken INTO DATA(ls_stoken) WHERE str = 'PERFORM'.
        lv_index = sy-tabix + 1.
        READ TABLE lt_stoken INTO ls_stoken INDEX lv_index.
        IF sy-subrc = 0.
          ls_form-str = ls_stoken-str.
          APPEND ls_form TO lt_form.
        ENDIF.
      ENDLOOP.
      CLEAR: lt_stoken, lt_sstmnt.

      "include程序--->main程序
      SELECT * FROM d010inc INTO TABLE @DATA(lt_d010inc) WHERE include = @is_prog-name.
      IF sy-subrc = 0.

        CHECK lines( lt_d010inc[] ) = 1.
        READ TABLE lt_d010inc INTO DATA(ls_d010inc) INDEX 1.

        "main程序--->所有程序
        lv_program = ls_d010inc-master.
        CALL FUNCTION 'RS_GET_ALL_INCLUDES'
          EXPORTING
            program    = lv_program
          TABLES
            includetab = lt_inc_tmp
          EXCEPTIONS
            OTHERS     = 0.

        "在所有including程序中找出FORM的开始行到结束行.
        LOOP AT lt_inc_tmp INTO DATA(ls_inc_tmp) .

          READ REPORT ls_inc_tmp INTO lt_source.
          "逐个perform进行查找.
          LOOP AT lt_form INTO ls_form.

            "开始行
            "FORM xxxxx .
            lv_regex = 'FORM\s+' && ls_form-str && '[\s.]'.       "开始行
            lv_regex2 = '"\s+FORM\s+' && ls_form-str && '[\s.]'.  "被注释的开始行
            lv_regex3 = 'ENDFORM' && '[\s.]'.               "结束行
            lv_regex4 = '"\s+ENDFORM' && '[\s.]'.           "被注释的结束行
            LOOP AT lt_source INTO DATA(ls_source).
              CHECK ls_source(1) NE '*'.    "注释行.

              IF lv_from_done = abap_false.
                "找开始行
                lv_from = sy-tabix.
                FIND REGEX lv_regex IN ls_source-line IGNORING CASE.
                IF sy-subrc = 0.
                  "check是否注释的
                  FIND REGEX lv_regex2 IN ls_source-line IGNORING CASE.
                  IF sy-subrc NE 0.
                    CONDENSE ls_source-line.
                    CHECK ls_source-line(4) = 'FORM'. "是FORM开头.
                    lv_from_done = abap_true.
                  ENDIF.
                ENDIF.

              ELSE.
                "找结束行.
                lv_to = sy-tabix.
                FIND REGEX lv_regex3 IN ls_source-line IGNORING CASE.
                IF sy-subrc = 0.
                  "check是否注释的
                  FIND REGEX lv_regex4 IN ls_source-line IGNORING CASE.
                  IF sy-subrc NE 0.
                    lv_to_done = abap_true.
                    EXIT.
                  ENDIF.
                ENDIF.
              ENDIF.

            ENDLOOP.


            IF lv_to_done = 'X'.

              "CHECK是未处理过的程序--避免相互调用造成的死循环
              READ TABLE gt_prog INTO gs_prog WITH KEY name = ls_inc_tmp
                                                       from = lv_from
                                                       to   = lv_to.
              IF sy-subrc NE 0.
                gs_prog_part-main_name = is_prog-main_name.
                gs_prog_part-name = ls_inc_tmp.
                gs_prog_part-type = '02'.   "including program
                gs_prog_part-from = lv_from.
                gs_prog_part-to = lv_to.
                APPEND gs_prog_part TO ct_prog.
                APPEND gs_prog_part TO gt_prog.
                APPEND gs_prog_part TO lt_prog_next. "下一个PERFORM.
              ENDIF.
            ENDIF.


            CLEAR: lv_from_done,
                   lv_to_done,
                   lv_from,
                   lv_to.

          ENDLOOP.
        ENDLOOP.
      ENDIF.
      CLEAR: lt_form.
    ENDLOOP.

    lt_prog_form[] = lt_prog_next[].
    CLEAR: lt_prog_next[].

  ENDWHILE.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHECK_TABNAME
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_STOKEN1_STR  text
*      <--P_LV_SUBRC  text
*----------------------------------------------------------------------*
FORM check_tabname  USING    iv_tabname TYPE char30
                    CHANGING cv_subrc TYPE syst-subrc.

  SELECT SINGLE tabname
    FROM dd02l
    INTO @DATA(lv_tname)
    WHERE tabname = @iv_tabname.

  cv_subrc = sy-subrc.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHECK_PROGNAME
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_STOKEN1_STR  text
*      <--P_LV_SUBRC  text
*----------------------------------------------------------------------*
FORM check_progname  USING    iv_progname TYPE char30
                    CHANGING cv_subrc TYPE syst-subrc.

  SELECT SINGLE progname
    FROM reposrc
    INTO @DATA(lv_progname)
    WHERE progname = @iv_progname.

  cv_subrc = sy-subrc.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHECK_TCODE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LS_STOKEN2_STR  text
*      <--P_LV_SUBRC  text
*----------------------------------------------------------------------*
FORM check_tcode  USING    iv_tcode TYPE char30
                  CHANGING cv_subrc TYPE syst-subrc.

  DATA: lv_tcode TYPE tstc-tcode.

  lv_tcode = iv_tcode.
  "去除引号   'FB03'-->FB03.
  SHIFT lv_tcode RIGHT DELETING TRAILING space.
  SHIFT lv_tcode RIGHT DELETING TRAILING ''''.
  CONDENSE lv_tcode.
  SHIFT lv_tcode LEFT DELETING LEADING ''''.

  SELECT SINGLE tcode
    FROM tstc
    INTO lv_tcode
    WHERE tcode = lv_tcode.

  cv_subrc = sy-subrc.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_USER_COMMAND
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_user_command USING iv_ucomm TYPE sy-ucomm
                            is_selfield  TYPE slis_selfield.


  CASE iv_ucomm.
    WHEN '&IC1'.

      READ TABLE gt_result INTO gs_result INDEX is_selfield-tabindex.
      IF sy-subrc = 0.

        CASE is_selfield-fieldname.
          WHEN 'SELECT' OR
               'DELETE' OR
               'UPDATE' OR
               'INSERT' OR
               'CALLFUNC' OR
               'CALLBAPI' OR
               'CALLRFC' OR
               'CALLCLASS' OR
               'CALLTRAN' OR
               'SUBMIT' OR
               'FORMS' OR
               'BUTTON_T'
                .

            PERFORM show_detail_sql USING is_selfield-fieldname
                                          gs_result.

          WHEN OTHERS.
        ENDCASE.

      ENDIF.

    WHEN OTHERS.
  ENDCASE.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SHOW_DETAIL_SQL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_GS_RESULT  text
*----------------------------------------------------------------------*
FORM show_detail_sql  USING iv_fname TYPE char30
                            is_result TYPE ts_result.

  DATA: lt_structure TYPE lvc_t_fcat,
        ls_structure TYPE lvc_s_fcat,
        ls_layout    TYPE lvc_s_layo.
  DATA: lv_title TYPE lvc_title.

  CONSTANTS:
    lc_user_command_sub TYPE slis_formname VALUE 'FRM_USER_COMMAND_SUB'.
***gt_key_word

  CLEAR lt_structure.

  IF iv_fname = 'SELECT' OR
     iv_fname = 'UPDATE' OR
     iv_fname = 'INSERT' OR
     iv_fname = 'DELETE' OR
     iv_fname = 'CALLFUNC' OR
     iv_fname = 'CALLBAPI' OR
     iv_fname = 'CALLRFC' OR
     iv_fname = 'CALLTRAN' OR
     iv_fname = 'SUBMIT'.

    ls_structure-fieldname = 'NAME'.
    ls_structure-coltext = 'Program'.
    ls_structure-col_pos = 1.
    ls_structure-ref_table = ''.
    ls_structure-ref_field = ''.
    APPEND ls_structure TO lt_structure.

    ls_structure-fieldname = 'POSITION'.
    ls_structure-coltext = 'Position'.
    ls_structure-hotspot = 'X'.
    ls_structure-col_pos = 3.
    ls_structure-datatype = 'INT4'.
    ls_structure-dd_outlen = '255'.
    APPEND ls_structure TO lt_structure.
    CLEAR ls_structure.

    IF iv_fname = 'SELECT' OR
       iv_fname = 'UPDATE' OR
       iv_fname = 'INSERT' OR
       iv_fname = 'DELETE'.

    ls_structure-fieldname = 'DDTEXT'.
    ls_structure-coltext = 'TableName'.
    ls_structure-col_pos = 4.
    ls_structure-REF_TABLE = 'DD02T'.
    ls_structure-REF_FIELD = 'DDTEXT'.
    APPEND ls_structure TO lt_structure.
    CLEAR ls_structure.
    ENDIF.
  ENDIF.

  CLEAR ls_structure.
  ls_structure-fieldname = 'KEYNAME'.
  ls_structure-coltext = 'Value'.
  ls_structure-col_pos = 2.
  ls_structure-datatype = 'CHAR'.
  ls_structure-dd_outlen = '40'.
  APPEND ls_structure TO lt_structure.
  CLEAR ls_structure.

****创建dyn_table
*  CALL METHOD cl_alv_table_create=>create_dynamic_table
*    EXPORTING
*      it_fieldcatalog           = lt_structure
*    IMPORTING
*      ep_table                  = dy_table
*    EXCEPTIONS
*      generate_subpool_dir_full = 1
*      OTHERS                    = 2.
*  IF sy-subrc = 0.
*    "table
*    ASSIGN dy_table->* TO <dyn_table>.
*  ENDIF.
*
****dyn_table 赋值
*  CREATE DATA dy_line LIKE LINE OF <dyn_table>.
*  ASSIGN dy_line->* TO <dyn_wa>.

  DATA: lt_sort TYPE lvc_t_sort.

  lt_sort = VALUE #( ( fieldname = 'KEYNAME'
                       up = 'X' ) ).

  gt_detail[] = gt_key_word[].
  DELETE gt_detail WHERE type <> iv_fname.
  CHECK gt_detail[] IS NOT INITIAL.

  LOOP AT gt_detail ASSIGNING FIELD-SYMBOL(<ls_detail>).

    SELECT SINGLE ddtext FROM dd02t INTO <ls_detail>-ddtext
      WHERE tabname = <ls_detail>-keyname
        AND ddlanguage = 'E'.
  ENDLOOP.




  lv_title = iv_fname.
  ls_layout-zebra = abap_true.
  ls_layout-cwidth_opt = abap_true.
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = sy-repid
      is_layout_lvc           = ls_layout
      it_fieldcat_lvc         = lt_structure
      it_sort_lvc             = lt_sort
      i_callback_user_command = lc_user_command_sub
      i_save                  = 'X'
      i_grid_title            = lv_title
    TABLES
      t_outtab                = gt_detail
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  .
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_BASIC_FUNC_INFO
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_get_basic_func_info .

  DATA: lr_pgmna TYPE RANGE OF trdir-name,
        lt_tstc  TYPE TABLE OF tstc.
  DATA: lv_progname(50),
        lt_source  TYPE abaptxt255_tab.

***GET programs
  SELECT
    tfdir~funcname,
    tfdir~pname,
    tfdir~include,
    tfdir~pname_main
    INTO TABLE @DATA(lt_tfdir)
    FROM tfdir
    WHERE tfdir~funcname IN @s_fname.
  IF sy-subrc <> 0.
    MESSAGE s001(00) WITH 'No functions found!' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.


  LOOP AT lt_tfdir INTO DATA(ls_tfdir).

    APPEND INITIAL LINE TO gt_prog ASSIGNING FIELD-SYMBOL(<ls_prog>).
*    <ls_prog>-main_name = ls_tfdir-funcname.

    CONCATENATE ls_tfdir-pname 'U' ls_tfdir-include INTO lv_progname.
    "SAPLXXX01--->LXXX01,  /BMW/SAPLXXX02--->/BMW/LXXX02
    REPLACE 'SAP' IN lv_progname WITH space .
    CONDENSE lv_progname.

    <ls_prog>-main_name = lv_progname.                  "Function对应的程序名
    <ls_prog>-name      = ls_tfdir-funcname.            "Function name
    <ls_prog>-type      = '02'.
    READ REPORT lv_progname INTO lt_source.
    <ls_prog>-from = 1.
    <ls_prog>-to = lines( lt_source ).
    <ls_prog>-lines = lines( lt_source ).
    UNASSIGN <ls_prog>.

    APPEND INITIAL LINE TO gt_result ASSIGNING FIELD-SYMBOL(<ls_result>).

    "Program
    <ls_result>-pgmna = lv_progname.        "Function对应的程序名
    <ls_result>-fname = ls_tfdir-funcname.  "Function name
    "Language
    "Create_ON
    "Package
    DATA(lv_group) = ls_tfdir-pname.
    REPLACE 'SAPL' IN lv_group WITH space .
    CONDENSE lv_group.
    SELECT SINGLE devclass, masterlang, created_on
      INTO ( @<ls_result>-devclass,
             @<ls_result>-spras,
             @<ls_result>-created_on )
      FROM tadir
      WHERE pgmid = 'R3TR' AND object = 'FUGR' AND obj_name = @lv_group.

    "Title
    SELECT SINGLE stext INTO <ls_result>-title FROM tftit
      WHERE funcname = <ls_result>-pgmna AND spras = <ls_result>-spras.
    "Package Desc.
    SELECT SINGLE ctext INTO <ls_result>-devclass_t FROM tdevct
      WHERE devclass = <ls_result>-devclass AND spras = <ls_result>-spras.
    "Package Component
    SELECT SINGLE component FROM tdevc INTO <ls_result>-component
      WHERE devclass = <ls_result>-devclass.
    "Last changed
    SELECT SINGLE udat FROM trdir INTO <ls_result>-changed_on
      WHERE name = <ls_result>-pgmna.
    "Lines
    <ls_result>-lines = lines( lt_source ).

    UNASSIGN <ls_result>.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  APPEND_CODE_STD
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_LR_CODE_STD  text
*----------------------------------------------------------------------*
FORM append_code_std  CHANGING cr_code_std LIKE gr_code_std.

  DATA: ls_code_std LIKE LINE OF gr_code_std.

  ls_code_std(3) = 'IEQ'.
  ls_code_std-low = '%ML'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%PC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%SC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%SC+'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '%SL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ABC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ALL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AQW'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AUF'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AVE'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&AVR'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CDF'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CFI'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&COUNT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRB'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRE'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRB'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&CRR'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&DAU'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&DOF'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&DON'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&EB9'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ELP'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ERW'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ETA'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&F03'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&F12'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&F15'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&IC1'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ILD'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ILT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&KOM'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&LFO'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&LIS'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&MAX'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&MIN'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&NFO'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&NTE'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OAD'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&ODN'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OL0'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OLX'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OMP'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OPT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&OUP'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&RNT'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&RNT_PREV'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&SAL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&SUM'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&UMC'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&XML'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&XPA'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = '&XXL'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P+'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P++'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P-'. APPEND ls_code_std TO cr_code_std.
  ls_code_std-low = 'P--'. APPEND ls_code_std TO cr_code_std.

ENDFORM.

000    Scanning type
001    Search Criteria
002    Objects to Be Scanned

P_CINC    Class/Interface
P_CK1    Program
P_CK2    Function
P_FUGR    Function
P_PROG    Program
S_FNAME    Function Module
S_PGMNA    Program
S_TCODE    Tcode

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973850.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

el-table树状表格,默认展开第一个节点的每一层

效果如图 <template><el-table:data"tableData"style"width: 100%":tree-props"{ children: children, hasChildren: hasChildren }":expand-row-keys"expandRowKeys"row-key"id"expand-change"handleExpan…

以ChatGPT为例解析大模型背后的技术

目录 1、大模型分类 2、为什么自然语言处理可计算&#xff1f; 2.1、One-hot分类编码&#xff08;传统词表示方法&#xff09; 2.2、词向量 3、Transformer架构 3.1、何为注意力机制&#xff1f; 3.2、注意力机制在 Transformer 模型中有何意义&#xff1f; 3.3、位置编…

I2C实践开发 ---【STM32-I2C-HDC1080温湿度采集系统】

I2C实践开发 — STM32-I2C-HDC1080温湿度采集系统 目录 I2C实践开发 --- STM32-I2C-HDC1080温湿度采集系统1. 引言2. 系统架构2.1 硬件架构2.2 软件架构 3. 代码分析3.1 I2C驱动文件 (i2c.h 和 i2c.c)3.2 HDC1080传感器驱动文件 (hdc1080.h 和 hdc1080.c) 4. 功能总结【HDC1080…

java毕业设计之医院门诊挂号系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的医院门诊挂号系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 医院门诊挂号系统的主要使用者…

[笔记.AI]大模型的蒸馏、剪枝、量化 | 模型压缩 | 作用与意义

上周简单整理了《deepseek-r1的不同版本&#xff08;满血版、蒸馏版、量化&#xff09;》&#xff0c;这次继续完善对其的认知——补充“剪枝”&#xff0c;并进一步整理蒸馏、剪枝、量化的作用与意义。 以下摘自与DeepSeek-R1在线联网版的对话 蒸馏、剪枝、量化是当前主流的三…

VMware按照的MacOS升级后无法联网

背景 3年前公司使用Flutter开发了一款app&#xff0c;现在app有微小改动需要重新发布到AppStore 问题 问题是原来的Vmware搭建的开发环境发布App失败了 提示&#xff1a;App需要使用xcode15IOS 17 SDK重新构建&#xff0c;这样的话MacOS至少需要升级到13.5 Xcode - 支持 - Ap…

量子计算的基本运算:Hadamard 门、CNOT 门、Pauli 门详解

量子计算是现代计算科学的前沿领域,它与经典计算机在处理信息的方式上有着本质的区别。量子计算机利用量子比特(qubit)的叠加态和量子纠缠等特性来进行计算,从而在某些特定任务上超越传统计算机。量子计算的核心运算单元是量子门,它们通过作用于量子比特来操控量子状态。本…

go http Client net/http

框架推荐 net/http go的内置http工具&#xff0c;可以构建client和server。 Slf4j Controller RequestMapping("/rest") public class RestTestController {GetMapping("/get")ResponseBodypublic String get(RequestBody SSHConnectParam param) throws…

Pycharm中断点使用技巧

1. 打开项目并准备代码 首先&#xff0c;打开 PyCharm 并加载你的 Python 项目&#xff0c;确保你已经有想要调试的 Python 代码文件。如&#xff1a; def add_numbers(a, b):result a breturn resultnum1 5 num2 3 sum_result add_numbers(num1, num2) print(f"Th…

【数据库系统概论】第第12章 并发控制

12.1 并发控制概述 并发控制是指数据库管理系统&#xff08;DBMS&#xff09;通过控制多个事务同时执行&#xff0c;保证数据的一致性和隔离性&#xff0c;避免事务间的相互干扰。 事务串行执行不能充分利用系统资源 并发执行的优点&#xff1a;能够减少处理机的空闲 时间&a…

阿里云通过docker安装skywalking及elasticsearch操作流程

系统 本文使用系统为 Alibaba Cloud Linux 3.2104 LTS 64位 配置为 4核8G PS&#xff1a;最低配置应为2核4G&#xff0c;配置过低无法启动 安装docker 1.卸载旧版本docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-…

【分治法】循环赛日程表问题 C\C++(附代码、实例)

问题描述 设计一个满足以下要求的比赛日程表&#xff1a; 每位选手必须与其他n-1个选手各赛一次每位选手一天只能赛一次循环赛一个进行n-1天选手人数 n 2 k n2^k n2k 问题分析 下图是一种日程表的安排方式 观察上图&#xff0c;我们发现日程表左上角的四行四列和右下角的四…

【第一节】C++设计模式(创建型模式)-工厂模式

目录 前言 一、面向对象的两类对象创建问题 二、解决问题 三、工厂模式代码示例 四、工厂模式的核心功能 五、工厂模式的应用场景 六、工厂模式的实现与结构 七、工厂模式的优缺点 八、工厂模式的扩展与优化 九、总结 前言 在面向对象系统设计中&#xff0c;开发者常…

基于windows的docker-desktop安装kubenetes以及dashboard

我们需要k8s环境做各种小实验可以本地安装一个&#xff0c;这里介绍win11如何通过docker-desktop安装k8s以及通过helm安装dashboard。 下载docker-desktop地址https://www.docker.com/get-started/打开【控制面板】->打开【启用和关闭windows功能】->分别勾选【hyper-v】…

vmware虚拟机Ubuntu Desktop系统怎么和我的电脑相互复制文件、内容

1、先安装vmware workstation 17 player&#xff0c;然后再安装Ubuntu Desktop虚拟机&#xff0c;然后再安装vmware tools&#xff0c;具体可以参考如下视频&#xff1a; VMware虚拟机与主机实现文件共享&#xff0c;其实一点也不难_哔哩哔哩_bilibili 2、本人亲自试过了&…

AIGC视频扩散模型新星:SVD——稳定扩散的Video模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍慕尼黑大学携手 NVIDIA 等共同推出视频生成模型 Video LDMs。NVIDIA 在 AI 领域的卓越成就家喻户晓&#xff0c;而慕尼黑大学同样不容小觑&#xff0c;…

llama-factory部署微调方法(wsl-Ubuntu Windows)

llama-factory项目GitHub地址&#xff1a;GitHub - hiyouga/LLaMA-Factory: Unified Efficient Fine-Tuning of 100 LLMs & VLMs (ACL 2024) wsl-Ubuntu&#xff1a; 1.获取项目 git clone https://github.com/hiyouga/LLaMA-Factory.gitcd LLaMA-Factory/ 2.安装环境…

数据结构之【顺序表简介】

1.顺序表的概念 顺序表 是 用一段物理地址连续的存储单元 依次 存储数据元素的线性结构 一般情况下采用数组存储 2.顺序表的结构 既然顺序表可以用来存储数据元素&#xff0c; 那就少不了 增删查改 的操作 此时&#xff0c;单一地只创建数组满足不了上述操作 创建相应的结构…

基于Spring Boot的农产品智慧物流系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

具有整合各亚专科医学领域知识能力的AI智能体开发纲要(2025版)

整合各亚专科医学领域知识能力的AI代理的开发与研究 一、引言 1.1 研究背景 在科技飞速发展的当下,人工智能(AI)已成为推动各行业变革的关键力量,医疗领域也不例外。近年来,AI 在医疗行业的应用取得了显著进展,从医学影像诊断到疾病预测,从药物研发到个性化医疗,AI 技…