PROCEDURE dum$display_catalog_file, display_catalog_file, discf (
  catalog_file, cf: file = $required
  output, o: file = $output
  status)

  " This PROC displays a permanent file catalog.  This proc assumes you
  " are using analyze_system, and that pfm$r2_request_processor has
  " been added as a debug table.
  " When used in conjunction with analyze_dump use the copy_memory command
  " to copy the open catalog to a file that may be input to this procedure.

  VAR
    local_status: status
    ignore_status: status
    hold_file : file = $fname($unique)
    object_size: integer = 262
    cycle_size: integer = 189
    permit_size: integer = 167
    mainframe_entry_size: integer = 16
    archive_entry_size: integer = 186
    checksum_size: integer = 8
  VAREND

  set_file_attributes file=hold_file page_format=continuous
  current = $default_module
  chadm pfm$r2_request_processor

  catalog_address = $file_pva(catalog_file)
  object_count = $pv(?catalog_address.pft$catalog_file.physical_catalog_header.catalog_header..
.object_list_locator.object_count)
  object_list_adr = $pv(^?catalog_address.pft$catalog_file.physical_catalog_header.catalog_header..
.object_list_locator.relative_cell_pointer)
  object_list_adr = $mem(object_list_adr, 4)

  display_program_value name=?catalog_address.pft$catalog_file o=hold_file.$eoi

  FOR object = 1 TO object_count DO
    put_line line=(' ', ' ') o=hold_file.$eoi

    object_adr = catalog_address + object_list_adr + ((object - 1)* object_size)
    object_type = $pv(?object_adr.pft$physical_object.object_entry.object_type)
    object_name = $pv(?object_adr.pft$physical_object.object_entry.external_object_name)

    IF object_type = 'PFC$FREE_OBJECT' THEN
      put_line ' '//$strrep(object_adr, 16)//' =  '//object_type o=hold_file.$eoi
    ELSEIF (object_type = 'PFC$FILE_OBJECT') OR (object_type = 'PFC$PURGED_FILE_OBJECT') THEN
      put_line ' FILE:  '//object_name o=hold_file.$eoi
      display_program_value name=?object_adr.pft$physical_object o=hold_file.$eoi

      permit_count = $pv(?object_adr.pft$physical_object.object_entry.permit_list_locator.permit_count)
      permit_list_adr = $pv(..
            ^?object_adr.pft$physical_object.object_entry.permit_list_locator.relative_cell_pointer)
      permit_list_adr = $mem(permit_list_adr, 4)
      IF permit_count > 0 THEN
        put_line (' ', ' Permit list for file: '//object_name) o=hold_file.$eoi
        FOR permit = 1 TO permit_count DO
          permit_adr = catalog_address + permit_list_adr + ((permit - 1)* permit_size)
          display_program_value name=?permit_adr.pft$physical_permit o=hold_file.$eoi
          put_line '  ' o=hold_file.$eoi
        FOREND
      IFEND

      put_line (' ', ' === Cycle list for file: '//$trim(object_name)//' ===') o=hold_file.$eoi
      cycle_count = $pv(?object_adr.pft$physical_object.object_entry.cycle_list_locator.cycle_count)
      cycle_list_adr = $pv(..
            ^?object_adr.pft$physical_object.object_entry.cycle_list_locator.relative_cell_pointer)
      cycle_list_adr = $mem(cycle_list_adr, 4)
      FOR cycle = 1 TO cycle_count DO
        cycle_adr = catalog_address + cycle_list_adr + ((cycle - 1)* cycle_size)
        cycle_type = $pv(?cycle_adr.pft$physical_cycle.cycle_entry.entry_type)
        IF cycle_type = 'PFC$FREE_CYCLE_ENTRY' THEN
          put_line (' ', ' '//$strrep(cycle_adr, 16)//' =  PFC$FREE_CYCLE_ENTRY') o=hold_file.$eoi
        ELSE
          cycle_number = $pv(?cycle_adr.pft$physical_cycle.cycle_entry.cycle_number)
          put_line ' CYCLE: '//$trim(object_name)//'.'//$strrep(cycle_number, 10) o=hold_file.$eoi
          display_program_value name=?cycle_adr.pft$physical_cycle o=hold_file.$eoi

          fmd_size = $pv(?cycle_adr.pft$physical_cycle.cycle_entry.fmd_locator.fmd_size)
          fmd_adr = $pv(^?cycle_adr.pft$physical_cycle.cycle_entry.fmd_locator.relative_cell_pointer)
          fmd_adr = catalog_address + $mem(fmd_adr, 4)
          IF fmd_size > 0 THEN
            put_line ' ' o=hold_file.$eoi
            display_physical_fmd fmd_adr o=hold_file.$eoi
          IFEND


          IF $pv(?cycle_adr.pft$physical_cycle.cycle_entry.file_label_locator.file_label_size) > 0 THEN
            physical_label_addr = catalog_address + ..
                  $mem($pv(..
                  ^?cycle_adr.pft$physical_cycle.cycle_entry.file_label_locator.relative_cell_pointer), 4)
            put_line ' ' o=hold_file.$eoi
            dispv ?physical_label_addr.pft$physical_file_label o=hold_file.$eoi
            label_addr = physical_label_addr + checksum_size
            dispv ?label_addr.fmt$static_label_header o=hold_file.$eoi
          ELSE
            put_line 'Unable to locate file label' o=hold_file.$eoi
          IFEND

          archive_entry_count = $pv(..
                ?cycle_adr.pft$physical_cycle.cycle_entry.archive_list_locator.archive_count)
          archive_entry_addr = $pv(..
                ^?cycle_adr.pft$physical_cycle.cycle_entry.archive_list_locator.relative_cell_pointer)
          archive_entry_addr = catalog_address + $mem(archive_entry_addr, 4)
          FOR archive_entry = 1 TO archive_entry_count DO
            archive_entry_addr = archive_entry_addr + ((archive_entry-1)*archive_entry_size)
            dispv ?archive_entry_addr.pft$physical_archive o=hold_file.$eoi
          FOREND

          mainframe_addr = $pv(^?cycle_adr.pft$physical_cycle.cycle_entry.mainframe_usage_list_locator..
.relative_cell_pointer)
          mainframe_addr = catalog_address + $mem(mainframe_addr, 4)
          mainframe_count = $pv(..
                ?cycle_adr.pft$physical_cycle.cycle_entry.mainframe_usage_list_locator.mainframe_count)
          FOR mainframe = 1 TO mainframe_count DO
            mainframe_addr = mainframe_addr + ((mainframe-1)*mainframe_entry_size)
            dispv ?mainframe_addr.pft$physical_mainframe_usage o=hold_file.$eoi
          FOREND

        IFEND
      FOREND
    ELSE
      catalog_type = $pv(?object_adr.pft$physical_object.object_entry.catalog_object_locator.catalog_type)
      object_name = $pv(?object_adr.pft$physical_object.object_entry.external_object_name)

      IF catalog_type = 'PFC$EXTERNAL_CATALOG' THEN
        put_line ' EXTERNAL CATALOG: '//object_name o=hold_file.$eoi
        display_program_value name=?object_adr.pft$physical_object o=hold_file.$eoi

        permit_count = $pv(?object_adr.pft$physical_object.object_entry.permit_list_locator.permit_count)
        permit_list_adr = $pv(..
              ^?object_adr.pft$physical_object.object_entry.permit_list_locator.relative_cell_pointer)
        permit_list_adr = $mem(permit_list_adr, 4)
        IF permit_count > 0 THEN
          put_line (' ', ' Permit list for catalog: '//object_name) o=hold_file.$eoi
          FOR permit = 1 TO permit_count DO
            permit_adr = catalog_address + permit_list_adr + ((permit - 1)* permit_size)
            display_program_value name=?permit_adr.pft$physical_permit o=hold_file.$eoi
            put_line '  ' o=hold_file.$eoi
          FOREND
        IFEND

        fmd_size = $pv(..
              ?object_adr.pft$physical_object.object_entry.catalog_object_locator.fmd_locator.fmd_size)
        fmd_adr = $pv(^?object_adr.pft$physical_object.object_entry.catalog_object_locator.fmd_locator..
.relative_cell_pointer)
        fmd_adr = catalog_address + $mem(fmd_adr, 4)
        IF fmd_size > 0 THEN
          put_line ' ' o=hold_file.$eoi
          display_physical_fmd fmd_adr o=hold_file.$eoi
        IFEND

      ELSE
        put_line ' INTERNAL CATALOG (FAMILY): '//object_name o=hold_file.$eoi
        display_program_value name=?object_adr.pft$physical_object o=hold_file.$eoi

        ic_object_count = $pv(?object_adr.pft$physical_object.object_entry.catalog_object_locator..
.object_list_locator.object_count)
        ic_object_list_adr = $pv(^?object_adr.pft$physical_object.object_entry.catalog_object_locator..
.object_list_locator.relative_cell_pointer)
        ic_object_list_adr = $mem(ic_object_list_adr, 4)

        FOR ic_object = 1 TO ic_object_count DO
          put_line line=(' ', ' ') o=hold_file.$eoi

          ic_object_adr = catalog_address + ic_object_list_adr + ((ic_object - 1)* object_size)
          object_type = $pv(?ic_object_adr.pft$physical_object.object_entry.object_type)
          object_name = $pv(?ic_object_adr.pft$physical_object.object_entry.external_object_name)

          IF object_type = 'PFC$FREE_OBJECT' THEN
            put_line ' '//$strrep(ic_object_adr, 16)//' =  '//object_type o=hold_file.$eoi
          ELSEIF (object_type = 'PFC$FILE_OBJECT') OR (object_type = 'PFC$PURGED_FILE_OBJECT') THEN
            put_line ' '//$strrep(object_adr, 16)//' =  '//object_type o=hold_file.$eoi
          ELSE
            object_name = $pv(?ic_object_adr.pft$physical_object.object_entry.external_object_name)
            put_line ' INTERNAL CATALOG (MASTER CATALOG): '//object_name o=hold_file.$eoi

            display_program_value name=?ic_object_adr.pft$physical_object o=hold_file.$eoi

            permit_count = $pv(..
                  ?ic_object_adr.pft$physical_object.object_entry.permit_list_locator.permit_count)
            permit_list_adr = $pv(^?ic_object_adr.pft$physical_object.object_entry.permit_list_locator..
.relative_cell_pointer)
            permit_list_adr = $mem(permit_list_adr, 4)
            IF permit_count > 0 THEN
              put_line (' ', '    Permit list for catalog: '//object_name) o=hold_file.$eoi
              FOR permit = 1 TO permit_count DO
                permit_adr = catalog_address + permit_list_adr + ((permit - 1)* permit_size)
                display_program_value name=?permit_adr.pft$physical_permit o=hold_file.$eoi
                put_line '  ' o=hold_file.$eoi
              FOREND
            IFEND

            fmd_size = $pv(?ic_object_adr.pft$physical_object.object_entry.catalog_object_locator..
.fmd_locator.fmd_size)
            fmd_adr = $pv(^?ic_object_adr.pft$physical_object.object_entry.catalog_object_locator..
.fmd_locator.relative_cell_pointer)
            fmd_adr = catalog_address + $mem(fmd_adr, 4)
            IF fmd_size > 0 THEN
              put_line ' ' o=hold_file.$eoi
              display_physical_fmd fmd_adr o=hold_file.$eoi
            IFEND

          IFEND
        FOREND
      IFEND
    IFEND
  FOREND

  copy_file input=hold_file output=output
  close_file file=catalog_file
  change_default_module module=$name(current)

PROCEND dum$display_catalog_file
