?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE : VEL Link Map Generator' ??
MODULE ocm$link_map_generator;

{  PURPOSE:
{    This module handles output to the LINK MAP generated by the
{  virtual environment linker.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc fsc$file_contents
*copyc fst$file_reference
*copyc llt$load_module
*copyc llt$object_module
*copyc loe$map_malfunction
*copyc lot$load_map_data
*copyc lot$loader_options
*copyc lot$loader_type_definitions
?? POP ??
*copyc amp$store
*copyc clp$close_display
*copyc clp$convert_integer_to_rjstring
*copyc clp$convert_string_to_file
*copyc clp$new_display_line
*copyc clp$new_display_page
*copyc clp$open_display_file
*copyc clp$put_display
*copyc clp$put_partial_display
*copyc clp$reset_for_next_display_page
*copyc osp$format_message
*copyc osp$set_status_abnormal
*copyc pmp$cause_condition
*copyc pmp$get_last_path_name
*copyc pmp$get_legible_date_time
*copyc pmp$get_os_version
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    start_of_accumulation_line = 8;

  TYPE
    oct$lm_header = (occ$lm_section_header, occ$lm_entry_header, occ$lm_xref_header, occ$lm_segment_header),
    oct$lines_per_header_text = array [oct$lm_header] of 0 .. 15,
    oct$lines_per_detail_text = array [lot$lm_code] of 0 .. 15;

  VAR
    accumulation_line_position: [STATIC] start_of_accumulation_line .. 135,
    continuous_form: [STATIC] boolean,
    display_control: [STATIC] clt$display_control,
    entry_detail_header_listed: [STATIC] boolean,
    lines_per_detail_text: [STATIC] ^oct$lines_per_detail_text,
    lines_per_header_text: [STATIC] ^oct$lines_per_header_text,
    narrow_format: [STATIC] boolean,
    section_detail_header_listed: [STATIC] boolean,
    segment_header_listed: [STATIC] boolean,
    xref_header_listed: [STATIC] boolean;

  VAR
    continuous_increments: [READ] oct$lines_per_detail_text := [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    non_cont_wide_increments: [READ] oct$lines_per_detail_text :=
          [4, 1, 2, 1, 2, 2, 4, 1, 1, 1, 1, 8, 0, 0, 0],
    non_cont_narrow_increments: [READ] oct$lines_per_detail_text :=
          [5, 2, 3, 1, 3, 2, 4, 1, 1, 1, 1, 8, 0, 0, 0];

  VAR
    continuous_header_increments: [READ] oct$lines_per_header_text := [0, 0, 0, 0],
    non_cont_wide_header_increments: [READ] oct$lines_per_header_text := [4, 5, 6, 6],
    non_cont_narrow_header_incremts: [READ] oct$lines_per_header_text := [5, 5, 7, 6];

  VAR
    page_header: [STATIC] string (72) := '                         LINK MAP.                            PAGE';

  VAR
    privilege_table: [READ] array [ost$execute_privilege] of string (6) := ['      ', '      ', 'LOCAL ',
          'GLOBAL '],
    section_kind_table: [READ] array [llt$section_kind] of string (26) := ['CODE                      ',
          'BINDING                   ', 'WORKING_STORAGE           ', 'COMMON_BLOCK              ',
          'EXTENSIBLE_WORKING_STORAGE', 'EXTENSIBLE_COMMON_BLOCK   ', 'LINE_ADDRESS_TABLE        '];



  VAR
    skeleton_module_detail_1: [STATIC] string (194) := 'MODULE:                                    FROM      '
          CAT '  :                                    LOADED RING:       CALL BRACKET:       GLOBAL KEY/L' CAT
          'OCK:    ' CAT '   LOCAL KEY/LOCK:       PRIVILEGE:       ',
    skeleton_module_detail_2: [STATIC] string (127) := '   DATE:             GENERATOR:                      '
          CAT '                       COMMENTS:                                         ',
    section_detail_header: [READ] string (104) := '   SECTION TYPE                    ACCESS ATTRIBUTES   LOA'
          CAT 'DED ADDRESS    (16) LENGTH (10)  SECTION NAME',
    skeleton_section_detail: [STATIC] string (123) := '                                                      '
          CAT '                                                                  ',
    entry_detail_header: [READ] string (48) := '   ENTRY POINT NAME                     ADDRESS',
    skeleton_entry_detail: [STATIC] string (101) := '                                                    ' CAT
          '                                                ',
    xref_header: [READ] string (146) := 'ENTRY POINT CROSS REFERENCE MAP    ENTRY POINT NAME                 '
          CAT '    ADDRESS                      DEFINING MODULE        REFERENCING MODULE(S)',
    segment_detail_header: [READ] string (138) := 'ALLOCATED SEGMENT MAP    SEGMENT                          '
          CAT '  GLOBAL&LOCAL    NUMBER       (16) LENGTH (10)    R1/R2     ACCESS ATTRIBUTES',
    skeleton_segment_detail: [STATIC] string (71) :=
          '                                   (  ,  )                            ',
    skeleton_transfer_detail: [STATIC] string (83) :=
          'TRANSFER SYMBOL :                                 TRANSFER ADDRESS:               ',
    skeleton_accumulate_names: [STATIC] string (135) := '                                                    '
          CAT '                                                                                        ',
    skeleton_asis_text: [STATIC] string (132) := ' ',
    diagnostic_summary_header: [READ] string (21) := 'DIAGNOSTIC SUMMARY: ',
    header_data_divider: [READ] string (123) := '   ---------------------------------------------------------'
          CAT '--------------------------------------------------------------';

?? OLDTITLE ??
?? NEWTITLE := '    NEW_PAGE_PROCEDURE', EJECT ??

  PROCEDURE new_page_procedure
    (VAR display_control: clt$display_control;
         new_page_number: integer;
     VAR status: ost$status);


    VAR
      l: integer;


    clp$reset_for_next_display_page (display_control, status);

    page_header (67, 5) := '     ';

    STRINGREP (page_header (67, * ), l, display_control.page_number);
    clp$put_display (display_control, page_header, clc$trim, status);

    clp$new_display_line (display_control, 2, status);


  PROCEND new_page_procedure;
?? OLDTITLE ??
?? NEWTITLE := '  LINK_MAP_ERROR_EXIT_PROCEDURE', EJECT ??

  PROCEDURE link_map_error_exit_procedure
    (    file_identifier: amt$file_identifier;
     VAR status {input} : ost$status);


    VAR
      dummy: ost$status;


    pmp$cause_condition (loe$map_malfunction, ^status, dummy);


  PROCEND link_map_error_exit_procedure;
?? OLDTITLE ??
?? NEWTITLE := '  OCP$INITIALIZE_LINK_MAP', EJECT ??

  PROCEDURE [XDCL] ocp$initialize_link_map
    (    map_file: fst$file_reference;
         build_level: pmt$os_name;
     VAR status: ost$status);


    CONST
      wide_format_threshold = 126;

    VAR
      of_execution: boolean,
      date: ost$date,
      time: ost$time,

      file: clt$file,
      default_rings: amt$ring_attributes,
      file_attributes: array [1 .. 1] of amt$store_item;


    status.normal := TRUE;

    clp$convert_string_to_file (map_file, file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    default_rings.r1 := #RING (^of_execution);
    default_rings.r2 := #RING (^of_execution);
    default_rings.r3 := #RING (^of_execution);

    clp$open_display_file (file, ^new_page_procedure, fsc$list, default_rings, display_control, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF display_control.page_width > 132 THEN
      display_control.page_width := 132;
    IFEND;


    file_attributes [1].key := amc$error_exit_procedure;
    file_attributes [1].error_exit_procedure := ^link_map_error_exit_procedure;

    amp$store (display_control.file_id, file_attributes, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
?? EJECT ??


    narrow_format := display_control.page_width < wide_format_threshold;

    IF display_control.page_format = amc$continuous_form THEN
      continuous_form := TRUE;
      lines_per_detail_text := ^continuous_increments;
      lines_per_header_text := ^continuous_header_increments;
    ELSE
      continuous_form := FALSE;
      IF narrow_format THEN
        lines_per_detail_text := ^non_cont_narrow_increments;
        lines_per_header_text := ^non_cont_narrow_header_incremts;
      ELSE
        lines_per_detail_text := ^non_cont_wide_increments;
        lines_per_header_text := ^non_cont_wide_header_increments;
      IFEND;
    IFEND;


    page_header (1, 22) := build_level;

    pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    page_header (40, 8) := date.mdy;
    page_header (50, 8) := time.hms;


    xref_header_listed := FALSE;
    segment_header_listed := FALSE;
    accumulation_line_position := start_of_accumulation_line;


  PROCEND ocp$initialize_link_map;
?? OLDTITLE ??
?? NEWTITLE := '  OCP$GENERATE_LINK_MAP_TEXT', EJECT ??

  PROCEDURE [XDCL] ocp$generate_link_map_text
    (    link_map_data: lot$load_map_data);


    VAR
      status: ost$status,
      window_position: 35 .. 72,
      name_length: 1 .. 32,
      message_content: ost$status_message,
      message: ^ost$status_message,
      diagnostic_line_count: ^ost$status_message_line_count,
      diagnostic_line_index: ost$status_message_line_count,
      diagnostic_line_size: ^ost$status_message_line_size,
      diagnostic_line: ^ost$status_message_line,
      severity: ost$status_severity,
      diagnostic_header_generated: boolean,
      diagnostic_summary_detail: string (38),
      converted_number: string (7),
      conversion_length: integer,
      last_character: 0 .. 41;


    CASE link_map_data.code OF
    = loc$lm_module_detail_1 =
      skeleton_module_detail_1 (9, 31) := link_map_data.module_name;
      skeleton_module_detail_1 (49, 7) := link_map_data.file_type;
      pmp$get_last_path_name (link_map_data.file_name, skeleton_module_detail_1 (58, 31), status);
      clp$convert_integer_to_rjstring (link_map_data.loaded_ring, 16, FALSE, ' ',
            skeleton_module_detail_1 (106, 2), status);
      clp$convert_integer_to_rjstring (link_map_data.call_bracket, 16, FALSE, ' ',
            skeleton_module_detail_1 (126, 2), status);
      clp$convert_integer_to_rjstring (link_map_data.module_global_key_lock, 16, FALSE, ' ',
            skeleton_module_detail_1 (149, 2), status);
      clp$convert_integer_to_rjstring (link_map_data.module_local_key_lock, 16, FALSE, ' ',
            skeleton_module_detail_1 (171, 2), status);
      skeleton_module_detail_1 (188, 6) := privilege_table [link_map_data.execute_privilege];

      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_module_detail_1]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      clp$new_display_line (display_control, 2, status);
      IF narrow_format THEN
        clp$put_display (display_control, skeleton_module_detail_1 (1, 39), clc$trim, status);
        clp$put_display (display_control, skeleton_module_detail_1 (41, 49), clc$trim, status);
      ELSE
        clp$put_display (display_control, skeleton_module_detail_1 (1, 88), clc$trim, status);
      IFEND;
      clp$put_display (display_control, skeleton_module_detail_1 (90, 39), clc$trim, status);
      clp$put_display (display_control, skeleton_module_detail_1 (129, 66), clc$trim, status);
      section_detail_header_listed := FALSE;
      entry_detail_header_listed := FALSE;
?? EJECT ??

    = loc$lm_module_detail_2 =
      skeleton_module_detail_2 (10, 10) := link_map_data.date;
      skeleton_module_detail_2 (33, 40) := link_map_data.generator;
      skeleton_module_detail_2 (87, 40) := link_map_data.commentary;
      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_module_detail_2]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      IF narrow_format THEN
        clp$put_display (display_control, skeleton_module_detail_2 (1, 72), clc$trim, status);
        clp$put_display (display_control, skeleton_module_detail_2 (74, 54), clc$trim, status);
      ELSE
        clp$put_display (display_control, skeleton_module_detail_2, clc$trim, status);
      IFEND;


    = loc$lm_section_detail =
      IF NOT section_detail_header_listed THEN
        section_detail_header_listed := TRUE;
        IF (display_control.line_number + lines_per_header_text^ [occ$lm_section_header] +
              lines_per_detail_text^ [loc$lm_section_detail]) > display_control.page_length THEN
          clp$new_display_page (display_control, status);
        IFEND;
        clp$new_display_line (display_control, 2, status);
        IF narrow_format THEN
          clp$put_display (display_control, section_detail_header (1, 53), clc$trim, status);
          clp$put_display (display_control, section_detail_header (55, 50), clc$trim, status);
          clp$put_display (display_control, header_data_divider (1, 68), clc$trim, status);
        ELSE
          clp$put_display (display_control, section_detail_header, clc$trim, status);
          clp$put_display (display_control, header_data_divider, clc$trim, status);
        IFEND;
      IFEND;
?? EJECT ??

      skeleton_section_detail (4, 26) := section_kind_table [link_map_data.section_kind];
      window_position := 36;
      skeleton_section_detail (window_position, 26) := '';
      IF llc$binding IN link_map_data.section_access_attributes THEN
        skeleton_section_detail (window_position, 7) := 'BINDING';
        window_position := window_position + 8;
      IFEND;
      IF llc$execute IN link_map_data.section_access_attributes THEN
        skeleton_section_detail (window_position, 7) := 'EXECUTE';
        window_position := window_position + 8;
      IFEND;
      IF llc$read IN link_map_data.section_access_attributes THEN
        skeleton_section_detail (window_position, 4) := 'READ';
        window_position := window_position + 5;
      IFEND;
      IF llc$write IN link_map_data.section_access_attributes THEN
        skeleton_section_detail (window_position, 5) := 'WRITE';
      IFEND;
      clp$convert_integer_to_rjstring (link_map_data.section_address.segment, 16, FALSE, ' ',
            skeleton_section_detail (58, 3), status);
      clp$convert_integer_to_rjstring (link_map_data.section_address.offset, 16, FALSE, ' ',
            skeleton_section_detail (62, 8), status);
      clp$convert_integer_to_rjstring (link_map_data.section_length, 16, FALSE, ' ',
            skeleton_section_detail (71, 8), status);
      clp$convert_integer_to_rjstring (link_map_data.section_length, 10, FALSE, ' ',
            skeleton_section_detail (80, 10), status);
      skeleton_section_detail (92, 31) := link_map_data.section_name;

      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_section_detail]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      clp$new_display_line (display_control, 1, status);
      IF narrow_format THEN
        clp$put_display (display_control, skeleton_section_detail (1, 53), clc$trim, status);
        clp$put_display (display_control, skeleton_section_detail (55, 67), clc$trim, status);
      ELSE
        clp$put_display (display_control, skeleton_section_detail, clc$trim, status);
      IFEND;
?? EJECT ??

    = loc$lm_entry_detail =
      IF NOT entry_detail_header_listed THEN
        entry_detail_header_listed := TRUE;
        IF (display_control.line_number + lines_per_header_text^ [occ$lm_entry_header] +
              lines_per_detail_text^ [loc$lm_entry_detail]) > display_control.page_length THEN
          clp$new_display_page (display_control, status);
        IFEND;
        clp$new_display_line (display_control, 2, status);
        clp$put_display (display_control, entry_detail_header, clc$trim, status);
        clp$put_display (display_control, header_data_divider (1, 66), clc$trim, status);
        clp$put_display (display_control, ' ', clc$trim, status);
      IFEND;

      skeleton_entry_detail (4, 31) := link_map_data.entry_name;
      clp$convert_integer_to_rjstring (link_map_data.entry_address.segment, 16, FALSE, ' ',
            skeleton_entry_detail (41, 3), status);
      clp$convert_integer_to_rjstring (link_map_data.entry_address.offset, 16, FALSE, ' ',
            skeleton_entry_detail (45, 8), status);
      skeleton_entry_detail (59, 5) := link_map_data.entry_attribute;
      skeleton_entry_detail (65, 8) := link_map_data.deferred;

      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_entry_detail]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      clp$put_display (display_control, skeleton_entry_detail (1, 72), clc$trim, status);
?? EJECT ??

    = loc$lm_xref_detail =
      IF NOT xref_header_listed THEN
        xref_header_listed := TRUE;
        clp$new_display_page (display_control, status);
        clp$new_display_line (display_control, 2, status);
        IF narrow_format THEN
          clp$put_display (display_control, xref_header (1, 31), clc$trim, status);
          clp$put_display (display_control, xref_header (33, 64), clc$trim, status);
          clp$put_display (display_control, xref_header (97, 21), clc$trim, status);
          clp$put_display (display_control, xref_header (118, 29), clc$trim, status);
          clp$put_display (display_control, header_data_divider (1, 66), clc$trim, status);
        ELSE
          clp$put_display (display_control, xref_header (1, 31), clc$trim, status);
          clp$put_display (display_control, xref_header (33, 85), clc$trim, status);
          clp$put_display (display_control, xref_header (118, 29), clc$trim, status);
          clp$put_display (display_control, header_data_divider (1, 120), clc$trim, status);
        IFEND;
      IFEND;

      skeleton_entry_detail (4, 31) := link_map_data.entry_name;
      clp$convert_integer_to_rjstring (link_map_data.entry_address.segment, 16, FALSE, ' ',
            skeleton_entry_detail (41, 3), status);
      clp$convert_integer_to_rjstring (link_map_data.entry_address.offset, 16, FALSE, ' ',
            skeleton_entry_detail (45, 8), status);
      skeleton_entry_detail (59, 5) := link_map_data.entry_attribute;
      skeleton_entry_detail (70, 31) := link_map_data.defining_module;

      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_xref_detail]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      IF narrow_format THEN
        clp$put_display (display_control, skeleton_entry_detail (1, 63), clc$trim, status);
        clp$put_display (display_control, skeleton_entry_detail (65, 37), clc$trim, status);
      ELSE
        clp$put_display (display_control, skeleton_entry_detail, clc$trim, status);
      IFEND;
?? EJECT ??

    = loc$lm_segment_detail =
      IF NOT segment_header_listed THEN
        segment_header_listed := TRUE;
        clp$new_display_page (display_control, status);
        clp$new_display_line (display_control, 2, status);
        clp$put_display (display_control, segment_detail_header (1, 21), clc$trim, status);
        clp$put_display (display_control, segment_detail_header (23, 11), clc$trim, status);
        clp$put_display (display_control, segment_detail_header (74, 64), clc$trim, status);
        clp$put_display (display_control, header_data_divider (1, 71), clc$trim, status);
      IFEND;

      clp$new_display_line (display_control, 1, status);
      clp$convert_integer_to_rjstring (link_map_data.segment, 16, FALSE, ' ', skeleton_segment_detail (4, 3),
            status);
      clp$convert_integer_to_rjstring (link_map_data.segment_length, 16, FALSE, ' ',
            skeleton_segment_detail (13, 8), status);
      clp$convert_integer_to_rjstring (link_map_data.segment_length, 10, FALSE, ' ',
            skeleton_segment_detail (23, 10), status);
      clp$convert_integer_to_rjstring (link_map_data.r1, 16, FALSE, ' ', skeleton_segment_detail (37, 2),
            status);
      clp$convert_integer_to_rjstring (link_map_data.r2, 16, FALSE, ' ', skeleton_segment_detail (40, 2),
            status);
      clp$convert_integer_to_rjstring (link_map_data.segment_global_key_lock, 16, FALSE, ' ',
            skeleton_segment_detail (49, 2), status);
      clp$convert_integer_to_rjstring (link_map_data.segment_local_key_lock, 16, FALSE, ' ',
            skeleton_segment_detail (52, 2), status);
      window_position := 47;
      skeleton_segment_detail (window_position, 24) := '';
      IF link_map_data.stack_segment THEN
        skeleton_segment_detail (window_position, 16) := 'STACK READ WRITE';
      ELSE
        IF link_map_data.segment_access_attributes.execute_privilege <> osc$non_executable THEN
          skeleton_segment_detail (window_position, 7) := 'EXECUTE';
          window_position := window_position + 8;
        IFEND;
        CASE link_map_data.segment_access_attributes.read_privilege OF
        = osc$read_key_lock_controlled =
          skeleton_segment_detail (window_position, 7) := 'READ_KL';
          window_position := window_position + 8;
        = osc$read_uncontrolled =
          skeleton_segment_detail (window_position, 4) := 'READ';
          window_position := window_position + 5;
        = osc$binding_segment =
          skeleton_segment_detail (window_position, 7) := 'BINDING';
          window_position := window_position + 8;
        ELSE
        CASEND;
        CASE link_map_data.segment_access_attributes.write_privilege OF
        = osc$write_key_lock_controlled =
          skeleton_segment_detail (window_position, 8) := 'WRITE_KL';
        = osc$write_uncontrolled =
          skeleton_segment_detail (window_position, 5) := 'WRITE';
        ELSE
        CASEND;
      IFEND;

      clp$put_display (display_control, skeleton_segment_detail, clc$trim, status);
?? EJECT ??

    = loc$lm_transfer_detail =
      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_transfer_detail]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;

      clp$convert_integer_to_rjstring (link_map_data.transfer_address.ring, 16, FALSE, ' ',
            skeleton_transfer_detail (69, 1), status);
      clp$convert_integer_to_rjstring (link_map_data.transfer_address.segment, 16, FALSE, ' ',
            skeleton_transfer_detail (71, 3), status);
      clp$convert_integer_to_rjstring (link_map_data.transfer_address.offset, 16, FALSE, ' ',
            skeleton_transfer_detail (75, 8), status);
      skeleton_transfer_detail (19, 31) := link_map_data.transfer_symbol;

      clp$new_display_line (display_control, 2, status);
      clp$put_display (display_control, skeleton_transfer_detail (1, 49), clc$trim, status);
      clp$put_display (display_control, skeleton_transfer_detail (51, 33), clc$trim, status);


    = loc$lm_accumulate_names =
      name_length := 31;
      WHILE link_map_data.name (name_length) = ' ' DO
        name_length := name_length - 1;
      WHILEND;
      IF accumulation_line_position + name_length > display_control.page_width THEN
        IF (display_control.line_number + lines_per_detail_text^ [loc$lm_accumulate_names]) >
              display_control.page_length THEN
          clp$new_display_page (display_control, status);
        IFEND;
        clp$put_display (display_control, skeleton_accumulate_names (1, accumulation_line_position - 2),
              clc$trim, status);
        accumulation_line_position := start_of_accumulation_line;
      IFEND;

      skeleton_accumulate_names (accumulation_line_position, name_length + 2) :=
            link_map_data.name (1, name_length);
      accumulation_line_position := accumulation_line_position + name_length + 2;

    = loc$lm_flush_accumulated_names =
      IF (display_control.line_number + lines_per_detail_text^ [loc$lm_flush_accumulated_names]) >
            display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      clp$put_display (display_control, skeleton_accumulate_names (1, accumulation_line_position - 2),
            clc$trim, status);
      accumulation_line_position := start_of_accumulation_line;
?? EJECT ??

    = loc$lm_asis_text =
      skeleton_asis_text := link_map_data.text;
      clp$put_display (display_control, skeleton_asis_text, clc$no_trim, status);

    = loc$lm_issue_diagnostic =
      message := ^message_content;
      osp$format_message (link_map_data.diagnostic_status, osc$full_message_level, display_control.page_width,
            message_content, status);
      RESET message;
      NEXT diagnostic_line_count IN message;
      IF (display_control.line_number + diagnostic_line_count^) > display_control.page_length THEN
        clp$new_display_page (display_control, status);
      IFEND;
      FOR diagnostic_line_index := 1 TO diagnostic_line_count^ DO
        NEXT diagnostic_line_size IN message;
        NEXT diagnostic_line: [diagnostic_line_size^] IN message;
        clp$put_display (display_control, diagnostic_line^ (1, diagnostic_line_size^), clc$trim, status);
      FOREND;
?? EJECT ??

    = loc$lm_diagnostic_summary =
      diagnostic_header_generated := FALSE;
      FOR severity := LOWERVALUE (ost$status_severity) TO UPPERVALUE (ost$status_severity) DO
        IF link_map_data.diagnostic_count [severity] <> 0 THEN
          IF NOT diagnostic_header_generated THEN
            diagnostic_header_generated := TRUE;
            IF (display_control.line_number + lines_per_detail_text^ [loc$lm_diagnostic_summary]) >
                  display_control.page_length THEN
              clp$new_display_page (display_control, status);
            IFEND;
            clp$new_display_line (display_control, 2, status);
            clp$put_display (display_control, diagnostic_summary_header, clc$trim, status);
          IFEND;
          STRINGREP (converted_number, conversion_length, link_map_data.diagnostic_count [severity]);
          diagnostic_summary_detail := ' ****';
          diagnostic_summary_detail (12 - conversion_length, conversion_length) :=
                converted_number (1, conversion_length);
          CASE severity OF
          = osc$informative_status =
            diagnostic_summary_detail (13, 13) := 'INFORMATIONAL';
            last_character := 25;
          = osc$warning_status =
            diagnostic_summary_detail (13, 7) := 'WARNING';
            last_character := 19;
          = osc$error_status =
            diagnostic_summary_detail (13, 5) := 'ERROR';
            last_character := 17;
          = osc$fatal_status =
            diagnostic_summary_detail (13, 5) := 'FATAL';
            last_character := 17;
          = osc$catastrophic_status =
            diagnostic_summary_detail (13, 12) := 'CATASTROPHIC';
            last_character := 24;
          CASEND;
          IF link_map_data.diagnostic_count [severity] = 1 THEN
            diagnostic_summary_detail (last_character + 1, 11) := ' diagnostic';
            last_character := last_character + 11;
          ELSE
            diagnostic_summary_detail (last_character + 1, 12) := ' diagnostics';
            last_character := last_character + 12;
          IFEND;
          clp$put_display (display_control, diagnostic_summary_detail (1, last_character), clc$trim, status);
        IFEND;
      FOREND;

    = loc$lm_page_header =
      IF (NOT continuous_form) AND (display_control.line_number <= 3) THEN
        clp$new_display_page (display_control, status);
      IFEND;


    ELSE
    CASEND;
  PROCEND ocp$generate_link_map_text;
?? OLDTITLE ??
?? NEWTITLE := '  OCP$CLOSE_LINK_MAP', EJECT ??

  PROCEDURE [XDCL] ocp$close_link_map
    (VAR status: ost$status);


    clp$close_display (display_control, status);


  PROCEND ocp$close_link_map;
?? OLDTITLE ??
MODEND ocm$link_map_generator;
