Code listing for: ZDTI_SYNTAXCHECK_SUB

Description: Subroutines

***********************************************************************************************************************
*
* Author          : Copyright (C) 2006 E.G.Mellodew
* program contact : www.dalestech.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
***********************************************************************************************************************
* ZDTI_SYNTAXCHECK_SEL... Selection screen routines
*----------------------------------------------------------------------------------------------------------------------
* Version  Correction Number  Date Changed  Changed By        Description
* ---------------------------------------------------------------------------------------------------------------------
* 1.0                                       Ed Mellodew       Original version
*
***********************************************************************************************************************

*----------------------------------------------------------------------------------------------------------------------
* findPrograms... find a list of programs which match our selection criteria
*----------------------------------------------------------------------------------------------------------------------
form findPrograms using value(soLocProg) like soProg[]
                              iLocProgramNames like iProgramNames[]
                        value(maxNumberToGet)
                        value(soLocPackage) like soPack[]
                        value(soLocCreatedBy) like soAuth[]
                        value(soLocChangedBy) like soChange[]
                        value(ignoreLocalObjects) type flag
                        value(ignoreGenerated) type flag.

data: waLocPackage like line of soLocPackage.
data: iGenerated type range of genflag with header line.

  if not ignoreLocalObjects is initial.
    waLocPackage-sign = 'E'.
    waLocPackage-option = 'EQ'.
    waLocPackage-low = '$TMP'.
    append waLocPackage to soLocPackage.
  endif.

  if not ignoreGenerated is initial.
    iGenerated-sign = 'E'.
    iGenerated-option = 'EQ'.
    iGenerated-low = 'X'.
    append iGenerated.
  endif.

  if pTrans is initial.
    select a~progName
           from reposrc as a
           inner join tadir as b
           on a~progName = b~obj_name
           up to maxNumberToGet rows
           into table iLocProgramNames
           where progName in soLocProg[]
             and ( a~subc = '1' or a~subc = 'M' )
             and a~cnam in soLocCreatedBy
             and a~unam in soLocChangedBy
             and b~pgmid = 'R3TR'
             and b~object = 'PROG'
             and b~devclass in soLocPackage[]
             and b~genflag in iGenerated[].
  else.
    select a~progName
           from reposrc as a
           inner join tadir as b
             on a~progName = b~obj_name
           inner join tstc as c
             on a~progNAme = c~pgmna
           up to maxNumberToGet rows
           into table iLocProgramNames
           where progName in soLocProg[]
             and ( a~subc = '1' or a~subc = 'M' )
             and a~cnam in soLocCreatedBy
             and a~unam in soLocChangedBy
             and b~pgmid = 'R3TR'
             and b~object = 'PROG'
             and b~devclass in soLocPackage[]
             and b~genflag in iGenerated[]
             and c~tcode <> ''.

*   Remove any duplocates
    sort iLocProgramNames ascending.
    delete adjacent duplicates from iLocProgramNames.
  endif.
endform.

*----------------------------------------------------------------------------------------------------------------------
* findFunc... find a list of functions or function groups which match our selection criteria
*----------------------------------------------------------------------------------------------------------------------
form findFuncs using value(soLocFGroup) like soFGroup[]
                           iLocProgramNames like iProgramNames[]
                     value(maxNumberToGet)
                     value(soLocPackage) like soPack[]
                     value(soLocCreatedBy) like soAuth[]
                     value(ignoreLocalObjects) type flag
                     value(ignoreGenerated) type flag.

data: iTadir type standard table of tadir with header line.
data: waLocPackage like line of soLocPackage.
data: Progname type programm.
data: iGenerated type range of genflag with header line.

  if not ignoreLocalObjects is initial.
    waLocPackage-sign = 'E'.
    waLocPackage-option = 'EQ'.
    waLocPackage-low = '$TMP'.
    append waLocPackage to soLocPackage.
  endif.

  if not ignoreGenerated is initial.
    iGenerated-sign = 'E'.
    iGenerated-option = 'EQ'.
    iGenerated-low = 'X'.
    append iGenerated.
  endif.

  select object
         obj_name
         from tadir
         into corresponding fields of table iTadir
         where pgmid = 'R3TR'
           and ( object = 'FUGR' or object = 'FUGS' )
           and obj_name in soLocFGroup[]
           and devclass in soLocPackage[]
           and genFlag in iGenerated[]
           and author in soLocCreatedBy[].

  loop at iTadir.
*   We now have the object name of the function group.  Lets turn this into a proper programname
    call function  'RS_TADIR_TO_PROGNAME' exporting object = iTadir-object
                                                    obj_name = iTadir-obj_name
                                          importing progname = progname.
    append progname to iLocProgramNames.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
* findClasses... find a list of classes which match our selection criteria
*----------------------------------------------------------------------------------------------------------------------
form findClasses using value(soLocClasses) like soClass[]
                           iLocProgramNames like iProgramNames[]
                     value(maxNumberToGet)
                     value(soLocPackage) like soPack[]
                     value(soLocCreatedBy) like soAuth[]
                     value(ignoreLocalObjects) type flag
                     value(ignoreGenerated) type flag.

data: iTadir type standard table of tadir with header line.
data: waLocPackage like line of soLocPackage.
data: Progname type programm.
data: iGenerated type range of genflag with header line.

  if not ignoreLocalObjects is initial.
    waLocPackage-sign = 'E'.
    waLocPackage-option = 'EQ'.
    waLocPackage-low = '$TMP'.
    append waLocPackage to soLocPackage.
  endif.

  if not ignoreGenerated is initial.
    iGenerated-sign = 'E'.
    iGenerated-option = 'EQ'.
    iGenerated-low = 'X'.
    append iGenerated.
  endif.

  select object
         obj_name
         from tadir
         into corresponding fields of table iTadir
         where pgmid = 'R3TR'
           and ( object = 'CLAS' )
           and obj_name in soLocClasses[]
           and devclass in soLocPackage[]
           and genFlag in iGenerated[]
           and author in soLocCreatedBy[].

  loop at iTadir.
*   We now have the object name of the function group.  Lets turn this into a proper programname
    call function  'RS_TADIR_TO_PROGNAME' exporting object = iTadir-object
                                                  obj_name = iTadir-obj_name
                                          importing progname = progname.
    append progname to iLocProgramNames.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
* syntaxCheckPrograms... syntax check a list of programs
*----------------------------------------------------------------------------------------------------------------------
form syntaxCheckPrograms using value(iLocProgramNames) like iProgramNames[]
                                     iLocMessages like iMessages[]
                               value(unicodeCheck)
                               value(obsoleteCheck)
                               value(errorsOnly)
                               value(warningsOnly).

data: waTrdir type trdir.
data: iSource type standard table of string.
data: errorMessage type trmsg.
data: myLine type string.
data: myWord type string.
data: iErrorMessages type synt_errors.
data: iWarningMessages type synt_errors.
data: waSyntaxMessage like line of iErrorMessages.
data: waMessage like line of iMessages.
data: waProgram like line of iProgramNames.
data: linesInTable type i.
data: charLinesInTable(6) type n.
data: percent type i.
data: statusMessage type string.
data: myTabix(6) type n.

  linesInTable = lines( iLocProgramNames[] ).

  loop at iLocProgramNames into waProgram.
*   Give a process message
    percent = 100 * sy-tabix / linesInTable.
    concatenate text-022 waProgram-programName into statusMessage separated by space.
    myTabix = sy-tabix.
    charLinesInTable = linesInTable.
    replace: '&1' with myTabix into statusMessage.
    replace  '&2' with charLinesInTable into statusMessage.
    call function 'SAPGUI_PROGRESS_INDICATOR' exporting percentage = percent
                                                        text = statusMessage.

    select single * from trdir into waTrdir where name = waProgram-programName.

    if not unicodeCheck is initial.
      waTrdir-uccheck = 'X'.
    endif.

    read report waProgram-programName into iSource.
    if sy-subrc = 0.
      syntax-check for iSource message errorMessage
                                  line myLine
                                  word myWord
                                  program waProgram-programName
                                  directory entry waTrdir
                                  ID 'ERR' table iErrorMessages
                                  ID 'MSG' table iWarningMessages.

      if warningsOnly is initial.
        loop at iErrorMessages into waSyntaxMessage.
          waMessage-alvStatus = 1.
          waMessage-programName = waProgram-programName.
          waMessage-intProgName = waProgram-programName.
          waMessage-messageType = 'Error'(005).
          move-corresponding waSyntaxMessage to waMessage.
          append waMessage to iLocMessages.
        endloop.
      endif.

      if errorsOnly is initial.
        loop at iWarningMessages into waSyntaxMessage.
          waMessage-alvStatus = 2.
          waMessage-programName = waProgram-programName.
          waMessage-intProgName = waProgram-programName.
            waMessage-messageType = 'Warning'(006).
          move-corresponding waSyntaxMessage to waMessage.
          append waMessage to iLocMessages.
        endloop.
      endif.

      clear iErrorMessages[].
      clear iWarningMessages[].

      if not obsoleteCheck is initial.
        perform checkForObsolete using waProgram-programName
                                       iSource[]
                                       iLocMessages[]
                                       unicodeCheck.
      endif.

      free iSource.
    endif.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
* checkForObsolete... check for obsolete functions
*----------------------------------------------------------------------------------------------------------------------
form checkForObsolete using programName
                            iLocSource like dum_iSource[]
                            iLocMessages like iMessages[]
                            value(unicodeCheck).

data: iTokens type table of stokes.
data: iStmnt type table of sstmnt.
data: iLevel type table of slevel.
data: iScanMessages type unt_appl.
data: waScanMessage like line of iScanMessages.
data: waMessage like line of iLocMessages.

 scan abap-source iLocSource tokens into iTokens
                             statements into iStmnt
                             levels into iLevel
                             with includes
                             program from programName.
 if sy-subrc = 0.
   call function 'GUI_FB_USAGE' exporting token = iTokens
                                          stmnt = iStmnt
                                          level = iLevel
                                importing appl_err = iScanMessages[].

   loop at iScanMessages into waScanMessage.
     waMessage-programName = programName.
     waMessage-intProgName = programName.  "added in version 1.1
     waMessage-message  = waScanMessage-message.
     if not unicodeCheck is initial.
*      If we are running as a unicode check we need some messages as errors.
       case waScanMessage-category.
         when 'E'.
           waMessage-alvStatus = 1.
           waMessage-messageType = text-005.
         when 'W'.
           waMessage-alvStatus = 2.
           waMessage-messageType = text-006.
       endcase.
     else.
*      Display as a warning
       waMessage-alvStatus = 2.
       waMessage-messageType = text-006.
     endif.
     waMessage-incname = waScanMessage-include.
     waMessage-line = waScanMessage-line.
     waMessage-keyword = waScanMessage-code.
     append waMessage to iLocMessages.
   endloop.
  endif.
endform.

*----------------------------------------------------------------------------------------------------------------------
* findDomainTexts... Find all the value texts for a domain
*----------------------------------------------------------------------------------------------------------------------
form findDomainTexts using iLocDomainTexts like dum_iDomainTexts[]
                           value(domainName).

  CALL FUNCTION 'DDIF_DOMA_GET'
    EXPORTING
      NAME                = domainName
      STATE               = 'A'
      LANGU               = sy-langu
    TABLES
      DD07V_TAB           = iLocDomainTexts
    EXCEPTIONS
      ILLEGAL_INPUT       = 1
      OTHERS              = 2.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  getFieldCatalogue... merge the field catalogue
*----------------------------------------------------------------------------------------------------------------------
form getFieldCatalogue using iLocFieldCatalogue like dum_iFieldCatalogue[]
                             value(structureName).

  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
*     I_BUFFER_ACTIVE              =
      I_STRUCTURE_NAME             = structureName
*     I_CLIENT_NEVER_DISPLAY       = 'X'
*     I_BYPASSING_BUFFER           =
*      I_INTERNAL_TABNAME           =
    CHANGING
      CT_FIELDCAT                  = iLocFieldCatalogue
    EXCEPTIONS
      INCONSISTENT_INTERFACE       = 1
      PROGRAM_ERROR                = 2
      OTHERS                       = 3.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  modifyProgCatalogue... Modify the field catalogue for the programs grid
*----------------------------------------------------------------------------------------------------------------------
form modifyProgCatalogue using iLocFieldCatalogue like dum_iFieldCatalogue[].

data waCat like line of iLocFieldCatalogue.

  loop at iLocFieldCatalogue into waCat.
    if waCat-fieldName = 'PROGRAMNAME'.
      waCat-key = 'X'.
      waCat-hotspot = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'GENERATED'.
      waCat-colText = 'Auto Gen'(015).
      waCat-tooltip = 'Auto generated'(016).
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'LDBNAME'.
      waCat-tooltip = 'Logical database name'(017).
      modify iLocFieldCatalogue from waCat.
    endif.


    if waCat-fieldName = 'ERRORSEXIST'.
      waCat-no_out = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'WARNINGSEXIST'.
      waCat-no_out = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'EDITICON'.
      waCat-icon = 'X'.
      waCat-colText = 'Code'(014).
      waCat-hotspot = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  modifyFuncCatalogue... Modify the field catalogue for the functions grid
*----------------------------------------------------------------------------------------------------------------------
form modifyFuncCatalogue using iLocFieldCatalogue like dum_iFieldCatalogue[].

data waCat like line of iLocFieldCatalogue.

  loop at iLocFieldCatalogue into waCat.
    if waCat-fieldName = 'GENERATED'.
      waCat-colText = 'Auto Gen'(015).
      waCat-tooltip = 'Auto generated'(016).
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'FUNCNAME'.
      waCat-key = 'X'.
      waCat-hotspot = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  modifyClassCatalogue... Modify the field catalogue for the class grid
*----------------------------------------------------------------------------------------------------------------------
form modifyClassCatalogue using iLocFieldCatalogue like dum_iFieldCatalogue[].

data waCat like line of iLocFieldCatalogue.

  loop at iLocFieldCatalogue into waCat.
    if waCat-fieldName = 'CLASSNAME'.
      waCat-key = 'X'.
      waCat-hotspot = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  modifyMessCatalogue... Modify the field catalogue for the messages grid
*----------------------------------------------------------------------------------------------------------------------
form modifyMessCatalogue using iLocFieldCatalogue like dum_iFieldCatalogue[].

data waCat like line of iLocFieldCatalogue.

  loop at iLocFieldCatalogue into waCat.
    if waCat-fieldName = 'PROGRAMNAME'.
      waCat-key = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'MESSAGETYPE'.
      waCat-no_out = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.

    if waCat-fieldName = 'INTPROGNAME'.
      waCat-no_out = 'X'.
      modify iLocFieldCatalogue from waCat.
    endif.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  prepareProgDataforALV... Prepare the data for output in our ALV format
*----------------------------------------------------------------------------------------------------------------------
form prepareProgDataforALV using iLocProgramNames like iProgramNames[]
                                 iLocMessages like iMessages[]
                                 iLocProgramDetails like iProgramDetails[]
                                 value(onlyFailures).

data: waProgramName like line of iProgramNames.
* List of texts for the field subc
data: iDomainTexts type standard table of dd07v.
data: waDomainText like line of iDomainTexts.
data: waProgram like line of iProgramDetails.

* Find the domain text for program types
  perform findDomainTexts using iDomainTexts[]
                                'SUBC'.

  loop at iLocProgramNames into waProgramName.
    waProgram-programName = waProgramName-programName.

*   Determine if there were any warning messages
    read table iMessages transporting no fields with key programName = waProgramName-programName
                                                          messageType = text-006.
    if sy-subrc = 0.
      noWithWarnings = noWithWarnings + 1.
      waProgram-alvStatus = '2'.
      waProgram-warningsExist = 'Yes'(007).
    else.
      waProgram-alvStatus = '3'.
      waProgram-warningsExist = 'No'(008).
    endif.

*   Determine if the program compiles
    read table iMessages transporting no fields with key programName = waProgramName-programName
                                                         messageType = text-005.
    if sy-subrc = 0.
      noWithErrors = noWithErrors + 1.
      waProgram-errorsExist = 'Yes'(007).
      waProgram-alvStatus = '1'.
    else.
      waProgram-errorsExist = 'No'(008).
    endif.

    if not onlyFailures is initial.
*     We don't want to see records which compiled successfully
      if waProgram-alvStatus = 3.
        continue.
      endif.
    endif.

*   Find the extra program info.
    select single subc
                  cnam
                  cdat
                  unam
                  udat
                  uccheck
                  occurs
                  ldbName
                  from reposrc
                  into (subc, waProgram-createdBy, waProgram-createdOn,
                              waProgram-changedBy, waProgram-changedOn,
                              waProgram-unicode, waProgram-generated,
                              waProgram-ldbname)
                  where progname = waProgram-programName.

*   Find the devclass
    select single devclass
                  from tadir
                  into waProgram-package
                  where pgmid = 'R3TR'
                    and object = 'PROG'
                    and obj_name = waProgram-programName.

*   Find the transaction code
    select single tcode
                  from tstc
                  into waProgram-transaction
                  where pgmna = waProgram-programName.

    read table iDomainTexts into waDomainText with key domValue_l = subc.
    if sy-subrc = 0.
      waProgram-subc = waDomainText-ddText.
    else.
      waProgram-subc = subc.
    endif.

*   Find the program description
    select single text from trdirt
                       into waProgram-titleText
                       where name = waProgram-programName
                         and sprsl = sy-langu.

    translate waProgram-createdBy to lower case.
    translate waProgram-changedBy to lower case.
    translate waProgram-package to lower case.
    translate waProgram-transaction to lower case.

*   Add the editor icon
    waProgram-editIcon = icon_abap.

    append waProgram to iLocProgramDetails.
    clear waProgram.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  prepareFuncDataforALV... Prepare the data for output in our ALV format
*----------------------------------------------------------------------------------------------------------------------
form prepareFuncDataforALV using iLocProgramNames like iProgramNames[]
                                 iLocMessages like iMessages[]
                                 iLocFuncDetails like iFuncDetails[]
                                 value(onlyFailures).

data: waProgramName like line of iProgramNames.
* List of texts for the field subc
data: iDomainTexts type standard table of dd07v.
data: waDomainText like line of iDomainTexts.
data: functionGroupName type rs38l_area.
data: waFuncDetail like line of iLocFuncDetails.

  loop at iLocProgramNames into waProgramName.
    call function 'RS_PROGNAME_SPLIT' exporting progname_with_namespace = waProgramName-programName
                                      importing fugr_group = functionGroupName
                                      exceptions delimiter_error = 1
                                      others = 2.
    waFuncDetail-funcName = functionGroupName.

*   Determine if there were any warning messages
    read table iMessages transporting no fields with key programName = waProgramName-programName
                                                         messageType = text-006.
    if sy-subrc = 0.
      noWithWarnings = noWithWarnings + 1.
      waFuncDetail-alvStatus = '2'.
      waFuncDetail-warningsExist = 'Yes'(007).
    else.
      waFuncDetail-alvStatus = '3'.
      waFuncDetail-warningsExist = 'No'(008).
    endif.

*   Determine if the program compiles
    read table iMessages transporting no fields with key programName = waProgramName-programName
                                                         messageType = text-005.
    if sy-subrc = 0.
      noWithErrors = noWithErrors + 1.
      waFuncDetail-errorsExist = 'Yes'(007).
      waFuncDetail-alvStatus = '1'.
    else.
      waFuncDetail-errorsExist = 'No'(008).
    endif.

    if not onlyFailures is initial.
*     We don't want to see records which compiled successfully
      if waFuncDetail-alvStatus = 3.
        continue.
      endif.
    endif.

*   Find the function group description
    select single areat from tlibt
                       into waFuncDetail-titleText
                       where area = waFuncDetail-funcName
                         and spras = sy-langu.

*   Find the package and person responsible
    select single author
                  devclass
                  genFlag
                  from tadir
                  into (waFuncDetail-createdBy, waFuncDetail-package, waFuncDetail-generated)
                  where pgmid = 'R3TR'
                    and object = 'FUGR'
                    and obj_name = waFuncDetail-funcName.

    translate waFuncDetail-createdBy to lower case.
    translate waFuncDetail-package to lower case.

    append waFuncDetail to iLocFuncDetails.
    clear waFuncDetail.
  endloop.
endform.

*----------------------------------------------------------------------------------------------------------------------
*  prepareClassDataforALV... Prepare the data for output in our ALV format
*----------------------------------------------------------------------------------------------------------------------
form prepareClassDataforALV using iLocProgramNames like iProgramNames[]
                                  iLocMessages like iMessages[]
                                  iLocClassDetails like iClassDetails[]
                                  value(onlyFailures).

data: waProgramName like line of iProgramNames.
* List of texts for the field subc
data: iDomainTexts type standard table of dd07v.
data: waDomainText like line of iDomainTexts.
data: waClassDetail like line of iLocClassDetails.
data: waMessage like line of iLocMessages.

  loop at iLocProgramNames into waProgramName.
    call function 'RS_PROGNAME_SPLIT' exporting progname_with_namespace = waProgramName-programName
                                      importing class_name = waClassDetail-className
                                      exceptions delimiter_error = 1
                                      others = 2.

*   Determine if there were any warning messages
    read table iMessages transporting no fields with key programName = waProgramName-programName
                                                         messageType = text-006.
    if sy-subrc = 0.
      noWithWarnings = noWithWarnings + 1.
      waClassDetail-alvStatus = '2'.
      waClassDetail-warningsExist = 'Yes'(007).
    else.
      waClassDetail-alvStatus = '3'.
      waClassDetail-warningsExist = 'No'(008).
    endif.

*   Determine if the program compiles
    read table iMessages transporting no fields with key programName = waProgramName-programName
                                                         messageType = text-005.
    if sy-subrc = 0.
      noWithErrors = noWithErrors + 1.
      waClassDetail-errorsExist = 'Yes'(007).
      waClassDetail-alvStatus = '1'.
    else.
      waClassDetail-errorsExist = 'No'(008).
    endif.

    if not onlyFailures is initial.
*     We don't want to see records which compiled successfully
      if waClassDetail-alvStatus = 3.
        continue.
      endif.
    endif.

*   Find the class description
    select single descript
                  category
                  exposure
                  state
                  author
                  createdOn
                  changedOn
                  changedBy
                  unicode
                  r3Release
                  from vseoclass
                  into corresponding fields of waClassDetail
                  where clsname = waClassDetail-classname.

*   Find the package and person responsible
    select single devclass
                  from tadir
                  into waClassDetail-package
                  where pgmid = 'R3TR'
                    and object = 'CLAS'
                    and obj_name = waClassDetail-className.

    translate waClassDetail-author to lower case.
    translate waClassDetail-changedBy to lower case.
    translate waClassDetail-package to lower case.

    append waClassDetail to iLocClassDetails.

*   Need to add the normal classname into the messages table
    loop at iLocMessages into waMessage where intProgName = waProgramName-programName.
      waMessage-programName = waClassDetail-classname.
      modify iLocMessages from waMessage.
    endloop.

    clear waClassDetail.
  endloop.
endform.