PROCEDURE (ram$discfa) display_catalog_file_attribute, display_catalog_file_attributes, discfa (
  catalog, c: file = $working_catalog
  output, o: file = $output
  display_option, do: list of name = (ai fc fo fp fs rt ra size ui)
  depth, d: any of
      key
        all
      keyend
      integer 1..$max_integer
    anyend = 2
  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:
"   Display the attributes of files in a catalog.
" DESIGN:
"   Display 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. Display option parameter values select the type of information to be
"   displayed for each file. The depth parameter limits the number of subcatalogs displayed.

  VAR
    attributes_list : list 0..$max_list of string
    delete_status : status
    file_attributes : file = $unique(:$local)
    files : list 0..$max_list of file = ()
    subcatalogs : list 0..$max_list of file = ()
  VAREND

  IF $nil(include_file) THEN " select the list of all files "
    files=$catalog_contents(catalog, include_files, paths)
  ELSE " accumulate a list of files with the include_file strings present "
    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

  FOR EACH excluded_file IN exclude_file DO " select only those files missing the exclude_file string "
    files=$select(files, $scan_string($translate(ltu, excluded_file), ' '//$path(x, last)//' ')=0)
  FOREND

  set_file_attributes file_attributes page_format=continuous file_contents=legible
  put_line (' ', ' CATALOG: '//catalog) output=output.$eoi

  FOR EACH filename IN files DO " process the list of file names "
    FOR EACH cycle IN $file_cycles(filename, paths) DO
      IF $string(catalog)= ':$LOCAL' THEN
        put_line ('    FILE: '//$path(cycle, last)) output=output.$eoi
      ELSE
        put_line ('    FILE: '//cycle) output=output.$eoi
      IFEND
      $system.display_file_attributes cycle output=file_attributes.$boi do=$apply(display_option, x)
      get_lines variable=attributes_list input=file_attributes.$boi
      put_line $apply(attributes_list, '          '//x) output=output.$eoi
    FOREND
  FOREND

  delete_file file_attributes

  IF $generic_type(depth)= 'INTEGER' THEN " decrement depth counter, to limit recursion"
    EXIT_PROC WHEN depth <= 2
    depth=depth - 1
  IFEND

  IF $nil(include_catalog) THEN " select the list of all catalogs "
    subcatalogs=$catalog_contents(catalog, include_catalogs, paths)
  ELSE " accumulate a list of catalogs with the include_catalog strings present "
    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

  FOR EACH excluded_catalog IN exclude_catalog DO " select catalogs missing the exclude_catalog string "
    subcatalogs=$select(subcatalogs, ..
          $scan_string($translate(ltu, excluded_catalog), ' '//$path(x, last)//' ')=0)
  FOREND

  FOR EACH subcatalog IN subcatalogs DO " recurse to process each subcatalog "
    $source.discfa catalog=subcatalog o=output d=depth do=display_option ec=exclude_catalog ef=exclude_file ..
          ic=include_catalog if=include_file
  FOREND

PROCEND display_catalog_file_attribute
