PROCEDURE (ram$delec) delete_extra_cycles, delec (
  catalog, c: file = $working_catalog
  retain, r: integer 0..999 = 1
  depth, d: any of
      key
        all
      keyend
      integer 1..$max_integer
    anyend = 2
  delete_empty_subcatalogs, delete_empty_subcatalog, des: boolean = false
  exclude_catalog, exclude_catalogs, ec: (BY_NAME, ADVANCED) list 0..$max_list of string = (' $')
  exclude_file, exclude_files, ef: (BY_NAME, ADVANCED) list 0..$max_list of string = (' $')
  include_catalog, ic: (BY_NAME, ADVANCED) list 0..$max_list of string = ()
  include_file, if: (BY_NAME, ADVANCED) list 0..$max_list of string = ()
  status)

" PURPOSE:
"   Delete the extra cycles from a catalog.
" DESIGN:
"   Delete all files meeting the criteria selected by parameter values. String values for INCLUDE or EXCLUDE
"   parameters are processed as substrings of the file or catalog names, allowing similarly named files or
"   catalogs to be selected or excluded. The depth parameter limits the number of subcatalogs processed.
" NOTES:
"   String values for INCLUDE or EXCLUDE parameters are processed as substrings of the file/catalog name.
"   A leading or trailing blank constrains the substring match to the beginning or end of a file name.

  VAR
    cycles : list of file
    delete_status : status
    files : list 0..$max_list of file = ()
    subcatalogs : list 0..$max_list of file = ()
  VAREND

" Either select all files in the catalog, or iteratively select those files whose names contain the specified
" include_file strings. Use the $union function to accumulate the list of non-duplicated file names.
  IF $nil(include_file) THEN
    files=$catalog_contents(catalog, include_files, paths)
  ELSE
    FOR EACH included_file IN include_file DO
      files=$union(files, $select($catalog_contents(catalog, include_files, paths), ..
            $scan_string($translate(ltu, included_file), ' '//$path(x, last)//' ')<>0))
    FOREND
  IFEND

" Exclude those files whose names do not contain the exclude_file strings.
  FOR EACH excluded_file IN exclude_file DO
    files=$select(files, $scan_string($translate(ltu, excluded_file), ' '//$path(x, last)//' ')=0)
  FOREND

" Remove the extra cycles of every file name in the list of files.
  FOR EACH filename IN files DO
    cycles=$reverse($file_cycles(filename, paths))
    FOR low_cycle = 1 TO ($size(cycles) - retain) DO
      delete_file file=cycles(low_cycle) status=delete_status
      IF delete_status.normal THEN
        put_line line='   DELETED FILE    '//cycles(low_cycle) output=$response
      IFEND
    FOREND
  FOREND

" Exit this procedure if the appropriate subcatalog level, otherwise decrement the depth counter and recurse.
  IF $generic_type(depth)= integer THEN
    EXIT_PROC WHEN depth <= 2
    depth=depth - 1
  IFEND

" Either select all subcatalogs, or iteratively select the subcatalogs whose names contain the specified
" include_catalog strings. Use the $union function to accumulate the list of non-duplicated catalog names.
  IF $nil(include_catalog) THEN
    subcatalogs=$catalog_contents(catalog, include_catalogs, paths)
  ELSE
    FOR EACH included_catalog IN include_catalog DO
      subcatalogs=$union(subcatalogs, $select($catalog_contents(catalog, include_catalogs, paths), ..
            $scan_string($translate(ltu, included_catalog), ' '//$path(x, last)//' ')<>0))
    FOREND
  IFEND

" Exclude those subcatalogs whose names do not contain the exclude_catalog strings.
  FOR EACH excluded_catalog IN exclude_catalog DO
    subcatalogs=$select(subcatalogs, ..
          $scan_string($translate(ltu, excluded_catalog), ' '//$path(x, last)//' ')=0)
  FOREND

" Recurse to process the files in each subcatalog.
  FOR EACH subcatalog IN subcatalogs DO
    $source.delete_extra_cycles catalog=subcatalog retain=retain depth=depth ec=exclude_catalog ..
          ef=exclude_file ic=include_catalog if=include_file des=delete_empty_subcatalogs
  FOREND

" Delete empty subcatalogs when directed to do so, otherwise exit the procedure.
  EXIT_PROC WHEN NOT delete_empty_subcatalogs
  delete_catalog catalog status=delete_status
  IF delete_status.normal THEN
    put_line line='   DELETED CATALOG '//catalog output=$response
  IFEND

PROCEND delete_extra_cycles
