PROCEDURE dum$display_mf_allocation_table, display_mf_allocation_table, dismat (
  avt_index, ai: any of
      integer 0..65536
      key
        all
      keyend
    anyend = all
  output, o: file = $output
  help, h: file = $null
  display_option, do: key
      (brief, b)
      (full, f)
    keyend = brief
  verify_mat, vm: boolean = false
  status)

  WHEN any_fault DO
    putl ' entered dismat condition handler - enter commands or exit_proc to abort'
    disv osv$status
    include_file command
  WHENEND

  IF $specified(help) THEN
COLLECT_TEXT o=$value(help) until='HELPEND'
DISPLAY_MF_ALLOCATION_TABLE or DISMAT

  This procedure will display the mainframe allocation table for a mass
storage device and describe the contents of selected fields of the table.
This procedure assumes the user has previously selected the correct exchange
package by available analyze_dump commands.

PARAMETERS:

AVT_INDEX, AI: integer 1..50 or key all
  This parameter selects the active volume table index of the individual
entry to be displayed if an integer is entered.  All entries will be dis-
played if the keyword "all" is entered.  This parameter defaults to "all".

OUTPUT, O: file
  This parameter selects the file name to receive the data.  This para-
meter is defaulted to $output.  If a file name other than $output is
entered the data will be formated correctly for printer disposition and
will be sent to the file  "$asis".

DISPLAY_OPTIONS, DO: key full, f, brief, b
  This parameter selects the option of displaying the contents of memory
and the description of the selected fields (full), or the brief mode of
the descriptions only.  This parameter defaults to brief.

VERIFY_MAT, VM: boolean
  This option, if set to true, will verify the MAT chains for correct
linkage and display the results. This parameter defaults to false.

STATUS

WARNINGS/KNOWN DEFICIENCIES:
  None.

ERROR HANDLER
  When any fatal error is encountered a condition handler is invoked and
the following message will appear:
 "entered dismat condition handler - enter commands or exit_proc to abort".
This will be followed by the error status.  To exit the handler enter:
 "exit_proc".

HELPEND
    EXIT_PROC
  IFEND

  create_variable name=output_file kind=string
  create_variable name=blank_line kind=string value='                                                    '
  create_variable name=type_index_a kind=integer value=0
  create_variable name=type_index_b kind=integer value=1
  create_variable name=alloc_offset_count kind=integer value=0
  create_variable name=style_offset_count kind=integer value=0
  create_variable name=line_first_part kind=string
  create_variable name=line_secnd_part kind=string
  create_variable name=blank_fill_count kind=integer
  create_variable name=column_two_num kind=integer value=40
  create_variable name=column_2_num kind=integer value=15
  create_variable name=column_3_num kind=integer value=43
  create_variable name=column_4_num kind=integer value=53
  create_variable name=ls kind=status

  IF $file($value(output) open_position) = '$BOI' THEN
    output_file = $string($value(output))//'.$asis'
  ELSE
    output_file = $string($value(output))
  IFEND

  avte = 'AVTE'
  pavt = $symbol_address(dmv$p_active_volume_table)
  avt = $memory(pavt)
  avt_size = $memory(pavt+6 4)
  lowest_avt_ordinal = $memory(pavt+10 4)
  avt_entry_size = $memory(pavt+14 4)
  number_of_avt_entries = avt_size/avt_entry_size
  highest_avt_ordinal = lowest_avt_ordinal+number_of_avt_entries-1

" AVT offsets "

  avte_offset = 0b(16)
  mat_pointer_offset = 64(16)
  recorded_vsn_offset = 88(16)

" MAT offsets "

  bytes_per_dau_offset = 2
  bytes_per_mau_offset = 4
  mau_per_dau_offset = 6
  dau_per_position_offset = 7
  positions_per_device_offset = 8
  default_allocation_size_offset = 0a(16)
  default_transfer_size_offset = 0d(16)
  starting_position_offset = 10(16)
  start_search_offset = 12(16)
  avail_alloc_unit_offset = 1e(16)
  allocation_chains_offset = 3c(16)
  minimum_space_offset = 50(16)
  maximum_space_offset = 53(16)
  available_space_offset = 56(16)
  leftover_space_offset = 59(16)
  allocated_space_offset = 5c(16)
  mat_too_full_offset = 77(16)
  available_dat_space_offset = 78(16)
  dat_threshold_offset = 7b(16)
  recovery_threshold_offset = 7e(16)
  warning_threshold_offset = 81(16)
  p_mat_bit_map_offset = 84(16)
  mat_entry_array_offset = 96(16)

" MAT array entry offsets "

  allocation_style_offset = 0
  forward_link_offset = 4
  mat_entry_size = 6

  max_allocation_style = 9
  max_device_position = 1629
  nil_link = max_device_position + 1

  IF $value_kind(avt_index) = 'INTEGER' THEN
    avt_ordinal = $value(avt_index)

    IF (avt_ordinal<lowest_avt_ordinal) OR (avt_ordinal>highest_avt_ordinal) THEN
      put_line 'avt_ordinal '//$strrep(avt_ordinal)//' is out of range'
      EXIT_PROC
    IFEND

    lowest_avt_ordinal = avt_ordinal
    highest_avt_ordinal = avt_ordinal

  IFEND

search_avt: ..
  FOR avt_ordinal = lowest_avt_ordinal TO highest_avt_ordinal DO

    avt_entry = avt+(avt_ordinal-1)*avt_entry_size
    entry_in_use = ($memory_string(avt_entry+avte_offset, 4) = avte)

    IF NOT entry_in_use THEN
      put_line ' avt entry'//$strrep(avt_ordinal)//' not in use' o=$fname(output_file)
    ELSE
      mat = $memory(avt_entry+mat_pointer_offset)

      IF $strrep($value(output)) = '$OUTPUT' THEN
        put_line '1                         MAT FOR '//$memory_string(avt_entry+recorded_vsn_offset, 6) ..
              o=$fname(output_file)
      IFEND

      IF display_option = 'FULL' THEN
        display_memory mat b=mat_entry_array_offset ..
              title='MAT FOR '//$memory_string(avt_entry+recorded_vsn_offset, 6) o=$fname(output_file)
      IFEND

      put_line '                          avt index= '//$strrep($memory(mat, 2)) o=$fname(output_file)
      line_first_part = ' bytes per dau = '//$strrep($memory(mat+bytes_per_dau_offset, 2))
      line_secnd_part = ' bytes per mau = '//$strrep($memory(mat+bytes_per_mau_offset, 2))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' daus per cylinder = '//$strrep($memory(mat+dau_per_position_offset, 1))
      line_secnd_part = ' mau per dau = '//$strrep($memory(mat+mau_per_dau_offset, 1))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' cylinders per device = '//$strrep($memory(mat+positions_per_device_offset, 2))
      line_secnd_part = ' starting cylinder = '//$strrep($memory(mat+starting_position_offset, 2))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' default allocation size = '//$strrep($memory(mat+default_allocation_size_offset, 3))
      line_secnd_part = ' default transfer size = '//$strrep($memory(mat+default_transfer_size_offset, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' start search cylinder = '//$strrep($memory(mat+start_search_offset, 2))
      line_secnd_part = ' available DAU bit map = '//$strrep($memory(mat+p_mat_bit_map_offset), 16)//'(16)'
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' minimum MAT space = '//$strrep($memory(mat+minimum_space_offset, 3))
      line_secnd_part = ' maximum MAT space = '//$strrep($memory(mat+maximum_space_offset, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' available MAT space = '//$strrep($memory(mat+available_space_offset, 3))
      line_secnd_part = ' leftover MAT space = '//$strrep($memory(mat+leftover_space_offset, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      total_space = $memory(mat+available_space_offset, 3)+$memory(mat+available_dat_space_offset, 3)
      line_first_part = ' total space = '//$strrep(total_space)
      IF ($memory(mat+mat_too_full_offset, 1) = 1) THEN
        line_secnd_part = ' MAT too full = TRUE'
      ELSE
        line_secnd_part = ' MAT too full = FALSE'
      IFEND
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' available DAT space = '//$strrep($memory(mat+available_dat_space_offset, 3))
      line_secnd_part = ' DAT threshold = '//$strrep($memory(mat+dat_threshold_offset, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = ' recovery threshold = '//$strrep($memory(mat+recovery_threshold_offset, 3))
      line_secnd_part = ' warning threshold = '//$strrep($memory(mat+warning_threshold_offset, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      put_line ' ALLOCATED SPACE:                        ALLOCATED SPACE:' o=$fname(output_file)

      line_first_part = '   permanent = '//$strrep($memory(mat+allocated_space_offset, 3))
      line_secnd_part = '  job named = '//$strrep($memory(mat+allocated_space_offset+15, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = '   catalog = '//$strrep($memory(mat+allocated_space_offset+12, 3))
      line_secnd_part = '  job unnamed = '//$strrep($memory(mat+allocated_space_offset+18, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      line_first_part = '   device = '//$strrep($memory(mat+allocated_space_offset+3, 3))
      line_secnd_part = '  global unnamed = '//$strrep($memory(mat+allocated_space_offset+21, 3))
      blank_fill_count = (column_two_num)-($strlen(line_first_part))
      put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
            o=$fname(output_file)

      put_line ' AVAILABLE ALLOCATION UNITS:             ALLOCATION CHAINS:' o=$fname(output_file)

      type_index_a = 0
      type_index_b = 1
      alloc_offset_count = 0
      style_offset_count = 0

      FOR index = 1 TO 5 DO

" Display available allocation units"
        line_first_part = '   A'//$strrep(type_index_a)//'='// $strrep(..
              $memory(mat+avail_alloc_unit_offset+alloc_offset_count, 3))
        alloc_offset_count = alloc_offset_count+3
        IF type_index_b < 9 THEN
          line_secnd_part = 'A'//..
$strrep(type_index_b)//'='//$strrep($memory(mat+avail_alloc_unit_offset+alloc_offset_count, 3))
        ELSE
          line_secnd_part = 'ACYL'//'='//$strrep($memory(mat+avail_alloc_unit_offset+alloc_offset_count, 3))
        IFEND
        blank_fill_count = (column_2_num)-($strlen(line_first_part))
        line_first_part = line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part

" Display allocation unit chains"
        line_secnd_part = 'A'//..
$strrep(type_index_a)//'='//$strrep($memory(mat+allocation_chains_offset+style_offset_count, 2))
        style_offset_count = style_offset_count + 2
        blank_fill_count = (column_3_num)-($strlen(line_first_part))
        line_first_part = line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part
        IF type_index_b < 9 THEN
          line_secnd_part = 'A'//..
$strrep(type_index_b)//'='//$strrep($memory(mat+allocation_chains_offset+style_offset_count, 2))
        ELSE
          line_secnd_part = 'ACYL'//'='//$strrep($memory(mat+allocation_chains_offset+style_offset_count, 2))
        IFEND
        blank_fill_count = (column_4_num)-($strlen(line_first_part))
        put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
              o=$fname(output_file)
        type_index_a = type_index_a + 2
        type_index_b = type_index_b + 2
        alloc_offset_count = alloc_offset_count + 3
        style_offset_count = style_offset_count + 2
      FOREND

      IF $value(verify_mat) THEN
        put_line '  '
        put_line '                                  VERIFYING MAT' o=$fname(output_file)
        mat = $memory(avt_entry+mat_pointer_offset)
        allocation_chain_link = mat + allocation_chains_offset
        mat_entry_array = mat + mat_entry_array_offset
      verify_chains: ..
        FOR allocation_style = 0 TO max_allocation_style DO
          IF allocation_style < 9 THEN
            line_first_part = ' verifying chain for style a'//$strrep(allocation_style)
          ELSE
            line_first_part = ' verifying chain for style acyl'
          IFEND

          link = $memory((allocation_style)*2+allocation_chain_link, 2)
          IF link = nil_link THEN
            line_secnd_part = ' this chain is nil'
            blank_fill_count = (column_two_num)-($strlen(line_first_part))
            put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
                  o=$fname(output_file)
            CYCLE verify_chains
          IFEND
          delete_variable links status=ls
          create_variable links k=boolean d=0..nil_link value=false
          message_sent = false
          crossed_links = 0
        verify_chain: ..
          BLOCK
            FOR entry = 0 TO max_device_position DO
              mat_entry = mat_entry_array + link * mat_entry_size
              forward_link = $memory(mat_entry+forward_link_offset, 2)
              style = $memory(mat_entry+allocation_style_offset, 1)
              IF links(forward_link) THEN
                line_secnd_part = '    *** circular linkage detected:'
                blank_fill_count = (column_two_num)-($strlen(line_first_part))
                put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
                      o=$fname(output_file)
                dism a=mat_entry b=mat_entry_size o=$fname(output_file)
                CYCLE verify_chains
              ELSEIF (style <> allocation_style) AND (allocation_style <= max_allocation_style) THEN
                IF NOT message_sent THEN
                  line_secnd_part = '    *** crossed linkage detected:'
                  blank_fill_count = (column_two_num)-($strlen(line_first_part))
                  put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
                        o=$fname(output_file)
                  dism a=mat_entry b=mat_entry_size o=$fname(output_file)
                  put_line '    further display of crossed linkage entries suppressed' o=$fname(output_file)
                  message_sent = true
                IFEND
                crossed_links = crossed_links + 1
              IFEND
              EXIT verify_chain WHEN forward_link = nil_link
              links(forward_link) = true
              link = forward_link
            FOREND
            put_line '    *** possible circular linkage:' o=$fname(output_file)
            put_line '    The maximum number of links has been exceeded.' o=$fname(output_file)
          BLOCKEND verify_chain
          IF crossed_links > 0 THEN
            put_line '    '//$strrep(crossed_links)//' crossed links detected.' o=$fname(output_file)
          IFEND
          line_secnd_part = ' '//$strrep(entry+1)//' entries verified'
          blank_fill_count = (column_two_num)-($strlen(line_first_part))
          put_line line_first_part//$substr(blank_line, 1, blank_fill_count)//line_secnd_part ..
                o=$fname(output_file)
        FOREND verify_chains
      IFEND
    IFEND
  FOREND search_avt

PROCEND dum$display_mf_allocation_table
