?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Physical Configuration Utility Ring 3.', EJECT ??
MODULE cmm$phys_configuration_utl_23d;

{ PURPOSE:
{    This module contains interfaces that manage various task private data
{    structures in the Physical Configuration Utility.

?? PUSH (LISTEXT := ON) ??
*copyc clc$standard_file_names
*copyc cmc$pcu_parameter_indices
*copyc cme$logical_configuration_mgr
*copyc cme$logical_configuration_utl
*copyc cme$physical_configuration_utl
*copyc cmt$element_definition
*copyc cmt$lcu_display_option_key
*copyc cmt$pcu_command_descriptor
*copyc cmt$state_information
*copyc clt$data_value
*copyc clt$parameter_value_table
*copyc oss$task_private
?? POP ??
*copyc amp$close
*copyc amp$change_file_attributes
*copyc amp$get_segment_pointer
*copyc amp$get_file_attributes
*copyc amp$fetch_access_information
*copyc amp$get_file_attributes
*copyc amp$open
*copyc amp$put_next
*copyc amp$return
*copyc amp$rewind
*copyc amp$set_segment_eoi
*copyc clp$count_list_elements
*copyc clp$convert_string_to_file
*copyc clp$convert_data_to_string
*copyc clp$convert_integer_to_string
*copyc clp$get_work_area
*copyc clp$put_partial_display
*copyc clp$read_variable
*copyc clp$scan_command_file
*copyc clp$write_variable
*copyc cmp$acquire_all_peripherals
*copyc cmp$build_active_conf
*copyc cmp$build_conf_tables
*copyc cmp$check_reserved_names
*copyc cmp$check_for_unique_element
*copyc cmp$clean_up_error_count
*copyc cmp$convert_iou_name
*copyc cmp$echo_errors
*copyc cmp$find_element
*copyc cmp$known_controller_id
*copyc cmp$known_product_id
*copyc cmp$generate_error_listing
*copyc cmp$get_unit_type
*copyc cmp$get_channel_definition
*copyc cmp$get_controller_type
*copyc cmp$get_driver_by_controller
*copyc cmp$install_system_conf
*copyc cmp$open_scratch_err_file
*copyc cmp$set_active_flag
*copyc cmp$valid_channel_name
*copyc fsp$close_file
*copyc fsp$copy_file
*copyc fsp$open_file
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc pmp$generate_unique_name
*copyc pmp$get_mainframe_id
*copyc cmv$configuration_activated
*copyc cmv$reserved_names_list
*copyc osv$task_private_heap
*copyc osv$lower_to_upper
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations declared by This Module.', EJECT ??

  VAR
    cmv$pcu_error_count: [XDCL, #GATE] integer,
    cmv$cmd_value_name: amt$local_file_name,
    cmv$cmd_value_fid: amt$file_identifier,
    cmv$state_value_fid: amt$file_identifier,
    cmv$state_value_name: amt$local_file_name,
    cmv$output_fid: amt$file_identifier,
    cmv$in_editor: [XDCL, #GATE] boolean := FALSE,
    cmv$input_fid: amt$file_identifier,
    cmv$installed_mainframe: [XDCL, #GATE] cmt$element_name,
    cmv$mainframe_name: cmt$element_name;

  VAR
    cmv$executing_within_editor: [XDCL, #GATE] boolean := FALSE;

  VAR
    cmv$command_descriptor_p: [XDCL, #GATE, oss$task_private] ^cmt$pcu_command_descriptor := NIL;

  VAR
    cmv$end_list_p: [XDCL] ^cmt$pcu_command_descriptor := NIL;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$add_definition ', EJECT ??

{ PURPOSE:
{    This procedure adds a command line to the current
{    edited configuration file

  PROCEDURE [XDCL, #GATE] cmp$add_definition
    (    definition: cmt$pcu_command_descriptor;
     VAR status: ost$status);

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      i: integer;

    status.normal := TRUE;
    ALLOCATE current_p IN osv$task_private_heap^;
    initialize_descriptor (current_p^);
    current_p^ := definition;

    IF cmv$command_descriptor_p = NIL THEN

      cmv$command_descriptor_p := current_p;
      cmv$end_list_p := current_p;
    ELSE
      cmv$end_list_p^.next_descriptor := current_p;
      cmv$end_list_p := current_p;
    IFEND;

  PROCEND cmp$add_definition;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$build_descriptor', EJECT ??

{ PURPOSE:
{    This procedure builds a single linked list of
{    commands from the input file.
{    Each node will contain one command line, a
{    head of list and an end of list pointer will be kept
{    global thru out the editing session

  PROCEDURE [XDCL, #GATE] cmp$build_descriptor
    (    definition: cmt$pcu_command_descriptor;
     VAR status: ost$status);

    VAR
      i: integer,
      temp_p: ^cmt$pcu_command_descriptor;

    status.normal := TRUE;

    ALLOCATE temp_p IN osv$task_private_heap^;
    temp_p^ := definition;
    temp_p^.next_descriptor := NIL;

    IF cmv$command_descriptor_p = NIL THEN
      cmv$command_descriptor_p := temp_p;
      cmv$end_list_p := cmv$command_descriptor_p;
    ELSE
      cmv$end_list_p^.next_descriptor := temp_p;
      cmv$end_list_p := temp_p;
    IFEND;
  PROCEND cmp$build_descriptor;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$change_connection_ref_r3', EJECT ??

{ PURPOSE:
{    This procedure updates the connection references of the DEFINE_ELEMENT
{    subcommands in the edited physical configuration file.

  PROCEDURE [XDCL, #GATE] cmp$change_connection_ref_r3
    (    old_channel_list: ^clt$data_value;
         new_channel_list: ^clt$data_value;
         old_mainframe_list: ^clt$data_value;
         new_mainframe_list: ^clt$data_value;
         old_peripheral: cmt$element_name;
         new_peripheral: cmt$element_name;
     VAR status: ost$status);

    VAR
      channel_len: integer,
      current_p: ^cmt$pcu_command_descriptor,
      field_index: integer,
      index: integer,
      iou_len: integer,
      len: integer,
      mainframe_len: integer,
      message: string (256),
      npn: cmt$element_name,
      ncn_channel: cmt$element_name,
      ncn_mainframe: cmt$element_name,
      ncn_iou: cmt$element_name,
      nmn_mainframe: cmt$element_name,
      nmn_iou: cmt$element_name,
      ocn_channel: cmt$element_name,
      ocn_mainframe: cmt$element_name,
      ocn_iou: cmt$element_name,
      old_channel_found: boolean,
      old_mainframe_found: boolean,
      old_peripheral_found: boolean,
      omn_mainframe: cmt$element_name,
      omn_iou: cmt$element_name,
      opn: cmt$element_name,
      peripheral_len: integer;

    status.normal := TRUE;
    ocn_mainframe := cmv$installed_mainframe;
    ncn_mainframe := cmv$installed_mainframe;
    ocn_iou := 'IOU0';
    ncn_iou := 'IOU0';
    omn_mainframe := cmv$installed_mainframe;
    nmn_mainframe := cmv$installed_mainframe;
    omn_iou := 'IOU0';
    nmn_iou := 'IOU0';
    old_channel_found := FALSE;
    old_mainframe_found := FALSE;
    old_peripheral_found := FALSE;
    IF (old_channel_list <> NIL) AND (new_channel_list <> NIL) THEN
      FOR field_index := LOWERBOUND (old_channel_list^.field_values^)
            TO UPPERBOUND (old_channel_list^.field_values^) DO
        IF old_channel_list^.field_values^ [field_index].name = 'CHANNEL' THEN
          IF old_channel_list^.field_values^ [field_index].value <> NIL THEN
            ocn_channel := old_channel_list^.field_values^ [field_index].value^.name_value;
            IF NOT cmp$valid_channel_name (ocn_channel) THEN
              osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_channel_number,
                    'CHANGE_CONNECTION_REFERENCE', status);
              osp$append_status_parameter (osc$status_parameter_delimiter, ocn_channel, status);
              RETURN;
            IFEND;
          IFEND;
        ELSEIF old_channel_list^.field_values^ [field_index].name = 'MAINFRAME' THEN
          IF old_channel_list^.field_values^ [field_index].value <> NIL THEN
            ocn_mainframe := old_channel_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        ELSEIF old_channel_list^.field_values^ [field_index].name = 'IOU' THEN
          IF old_channel_list^.field_values^ [field_index].value <> NIL THEN
            ocn_iou := old_channel_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        IFEND;
      FOREND;
      FOR field_index := LOWERBOUND (new_channel_list^.field_values^)
            TO UPPERBOUND (new_channel_list^.field_values^) DO
        IF new_channel_list^.field_values^ [field_index].name = 'CHANNEL' THEN
          IF new_channel_list^.field_values^ [field_index].value <> NIL THEN
            ncn_channel := new_channel_list^.field_values^ [field_index].value^.name_value;
            IF NOT cmp$valid_channel_name (ncn_channel) THEN
              osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_channel_number,
                    'CHANGE_CONNECTION_REFERENCE', status);
              osp$append_status_parameter (osc$status_parameter_delimiter, ncn_channel, status);
              RETURN;
            IFEND;
          IFEND;
        ELSEIF new_channel_list^.field_values^ [field_index].name = 'MAINFRAME' THEN
          IF new_channel_list^.field_values^ [field_index].value <> NIL THEN
            ncn_mainframe := new_channel_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        ELSEIF new_channel_list^.field_values^ [field_index].name = 'IOU' THEN
          IF new_channel_list^.field_values^ [field_index].value <> NIL THEN
            ncn_iou := new_channel_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        IFEND;
      FOREND;
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;

      /channel_loop/
        WHILE current_p <> NIL DO
          IF current_p^.iou_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.iou_list^) TO UPPERBOUND (current_p^.iou_list^) DO
              IF (ocn_channel = current_p^.iou_list^ [index].channel) AND
                    (ocn_mainframe = current_p^.iou_list^ [index].mainframe) AND
                    (ocn_iou = current_p^.iou_list^ [index].iou) THEN
                old_channel_found := TRUE;
                EXIT /channel_loop/;
              IFEND;
            FOREND;
          ELSEIF current_p^.channel_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.channel_list^) TO UPPERBOUND (current_p^.channel_list^) DO
              IF (ocn_channel = current_p^.channel_list^ [index].channel) AND
                    (ocn_mainframe = current_p^.channel_list^ [index].mainframe) AND
                    (ocn_iou = current_p^.channel_list^ [index].iou) THEN
                old_channel_found := TRUE;
                EXIT /channel_loop/;
              IFEND;
            FOREND;
          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND /channel_loop/;
      IFEND;
      IF NOT old_channel_found THEN
        message := ' ';
        channel_len := find_name_length (ocn_channel) + 1;
        mainframe_len := find_name_length (ocn_mainframe) + 1;
        iou_len := find_name_length (ocn_iou);
        STRINGREP (message, len, 'Channel (', ocn_channel (1, channel_len), ocn_mainframe (1, mainframe_len),
              ocn_iou (1, iou_len), ')');
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, message, status);
        RETURN;
      IFEND;
    IFEND;

    IF (old_mainframe_list <> NIL) AND (new_mainframe_list <> NIL) THEN
      FOR field_index := LOWERBOUND (old_mainframe_list^.field_values^)
            TO UPPERBOUND (old_mainframe_list^.field_values^) DO
        IF old_mainframe_list^.field_values^ [field_index].name = 'MAINFRAME' THEN
          IF old_mainframe_list^.field_values^ [field_index].value <> NIL THEN
            omn_mainframe := old_mainframe_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        ELSEIF old_mainframe_list^.field_values^ [field_index].name = 'IOU' THEN
          IF old_mainframe_list^.field_values^ [field_index].value <> NIL THEN
            omn_iou := old_mainframe_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        IFEND;
      FOREND;
      FOR field_index := LOWERBOUND (new_mainframe_list^.field_values^)
            TO UPPERBOUND (new_mainframe_list^.field_values^) DO
        IF new_mainframe_list^.field_values^ [field_index].name = 'MAINFRAME' THEN
          IF new_mainframe_list^.field_values^ [field_index].value <> NIL THEN
            nmn_mainframe := new_mainframe_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        ELSEIF new_mainframe_list^.field_values^ [field_index].name = 'IOU' THEN
          IF new_mainframe_list^.field_values^ [field_index].value <> NIL THEN
            nmn_iou := new_mainframe_list^.field_values^ [field_index].value^.name_value;
          IFEND;
        IFEND;
      FOREND;
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;

      /mainframe_loop/
        WHILE current_p <> NIL DO
          IF current_p^.iou_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.iou_list^) TO UPPERBOUND (current_p^.iou_list^) DO
              IF (omn_mainframe = current_p^.iou_list^ [index].mainframe) AND
                    (omn_iou = current_p^.iou_list^ [index].iou) THEN
                old_mainframe_found := TRUE;
                EXIT /mainframe_loop/;
              IFEND;
            FOREND;
          ELSEIF current_p^.channel_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.channel_list^) TO UPPERBOUND (current_p^.channel_list^) DO
              IF (omn_mainframe = current_p^.channel_list^ [index].mainframe) AND
                    (omn_iou = current_p^.channel_list^ [index].iou) THEN
                old_mainframe_found := TRUE;
                EXIT /mainframe_loop/;
              IFEND;
            FOREND;

          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND /mainframe_loop/;
      IFEND;

      IF NOT old_mainframe_found THEN
        message := ' ';
        mainframe_len := find_name_length (omn_mainframe) + 1;
        iou_len := find_name_length (omn_iou);
        STRINGREP (message, len, 'Mainframe (', omn_mainframe (1, mainframe_len), omn_iou (1, iou_len), ')');
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, message, status);
        RETURN;
      IFEND;
    IFEND;
    IF (old_peripheral <> osc$null_name) AND (new_peripheral <> osc$null_name) THEN
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        WHILE current_p <> NIL DO
          IF current_p^.pc_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.pc_list^) TO UPPERBOUND (current_p^.pc_list^) DO
              IF (old_peripheral = current_p^.pc_list^[index].peripheral) THEN
                old_peripheral_found := TRUE;
                current_p^.pc_list^[index].peripheral := new_peripheral;
              IFEND;
            FOREND;
          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND;
      IFEND;

      IF NOT old_peripheral_found THEN
        message := ' ';
        peripheral_len := find_name_length (opn);
        STRINGREP (message, len, 'Old peripheral (',
              opn(1,peripheral_len), ')');
        osp$set_status_abnormal (cmc$configuration_management_id,
                cme$pcu_element_not_found, message, status);
        RETURN;
      IFEND;
    IFEND;

    IF old_channel_found THEN
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        WHILE current_p <> NIL DO
          IF current_p^.iou_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.iou_list^) TO UPPERBOUND (current_p^.iou_list^) DO
              IF (ocn_channel = current_p^.iou_list^[index].channel) AND
                     (ocn_mainframe = current_p^.iou_list^[index].mainframe) AND
                     (ocn_iou = current_p^.iou_list^[index].iou) THEN
                current_p^.iou_list^[index].channel := ncn_channel;
                current_p^.iou_list^[index].mainframe := ncn_mainframe;
                current_p^.iou_list^[index].iou := ncn_iou;
              IFEND;
            FOREND;
          ELSEIF current_p^.channel_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.channel_list^) TO UPPERBOUND (current_p^.channel_list^) DO
              IF (ocn_channel = current_p^.channel_list^[index].channel) AND
                     (ocn_mainframe = current_p^.channel_list^[index].mainframe) AND
                     (ocn_iou = current_p^.channel_list^[index].iou) THEN
                current_p^.channel_list^[index].channel := ncn_channel;
                current_p^.channel_list^[index].mainframe := ncn_mainframe;
                current_p^.channel_list^[index].iou := ncn_iou;
              IFEND;
            FOREND;
          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND;
      IFEND;
    IFEND;

    IF old_mainframe_found THEN
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        WHILE current_p <> NIL DO
          IF current_p^.iou_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.iou_list^) TO UPPERBOUND (current_p^.iou_list^) DO
              IF (omn_mainframe = current_p^.iou_list^[index].mainframe) AND
                     (omn_iou = current_p^.iou_list^[index].iou) THEN
                current_p^.iou_list^[index].mainframe := nmn_mainframe;
                current_p^.iou_list^[index].iou := nmn_iou;
              IFEND;
            FOREND;
          ELSEIF current_p^.channel_list <> NIL THEN
            FOR index := LOWERBOUND (current_p^.channel_list^) TO UPPERBOUND (current_p^.channel_list^) DO
              IF (omn_mainframe = current_p^.channel_list^[index].mainframe) AND
                     (omn_iou = current_p^.channel_list^[index].iou) THEN
                current_p^.channel_list^[index].mainframe := nmn_mainframe;
                current_p^.channel_list^[index].iou := nmn_iou;
              IFEND;
            FOREND;
          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND;
      IFEND;
    IFEND;

  PROCEND cmp$change_connection_ref_r3;

?? OLDTITLE ??
?? NEWTITLE := '   cpm$change_definition', EJECT ??

{ PURPOSE:
{    This procedure searches for an element name in a
{    configuration file and change its definition


  PROCEDURE [XDCL, #GATE] cmp$change_definition
    (    pvt: ^clt$parameter_value_table;
     VAR status: ost$status);

    CONST
      c$none = 'none',
      command_name = 'CHANGE_ELEMENT_DEFINITION      ';

    VAR
      connection_specified: boolean,
      current_p: ^cmt$pcu_command_descriptor,
      element: cmt$element_definition,
      found: boolean,
      found_command: cmt$pcu_command_descriptor,
      new_descriptor: cmt$pcu_command_descriptor,
      nil_pointer: boolean,
      previous_p: ^cmt$pcu_command_descriptor,
      same_as: boolean,
      same_element: cmt$pcu_command_descriptor;

    status.normal := TRUE;
    initialize_descriptor (new_descriptor);

    new_descriptor.element_name := pvt^ [p$element].value^.name_value;
    element.element_name := new_descriptor.element_name;

    cmp$search_edited_file (new_descriptor.element_name, 0, element.product_id, found, found_command);
    IF NOT found THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found,
            new_descriptor.element_name, status);
      RETURN;
    IFEND;

    cmp$determine_element_type (found_command.pid, element, status);
    IF element.element_type = cmc$external_processor_element THEN
      new_descriptor.connection := cmc$central_memory_connection;
    ELSE
      new_descriptor.connection := cmc$iou_connection;
    IFEND;

    new_descriptor.verify := found_command.verify;

    same_as := pvt^ [p$same_as].specified;
    IF same_as THEN
      cmp$search_edited_file (pvt^ [p$same_as].value^.name_value, 0, element.product_id, found, same_element);
      IF NOT found THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_same_as_not_defined,
              pvt^ [p$same_as].value^.name_value, status);
        RETURN; {----->
      ELSE
        new_descriptor.pid := same_element.pid;
        new_descriptor.state := same_element.state;
        new_descriptor.sn := same_element.sn;
      IFEND;
    IFEND;

    IF pvt^ [p$verify_element_identification].specified THEN
      new_descriptor.verify := pvt^ [p$verify_element_identification].value^.boolean_value.value;
    IFEND;

    IF pvt^ [p$element_identification].specified THEN
      new_descriptor.pid := pvt^ [p$element_identification].value^.name_value;
      cmp$get_product_id (new_descriptor.pid, element, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    ELSE
      IF same_as THEN
        new_descriptor.pid := same_element.pid;
      IFEND;
    IFEND;

    IF pvt^ [p$serial_number].specified THEN
      new_descriptor.sn := pvt^ [p$serial_number].value^.integer_value.value;
    IFEND;

    IF pvt^ [p$iou_program_name].specified THEN
      IF pvt^ [p$iou_program_name].value^.kind = clc$keyword THEN
        new_descriptor.ioupn := c$none;
      ELSE
        new_descriptor.ioupn := pvt^ [p$iou_program_name].value^.name_value;
      IFEND;
    IFEND;

    IF pvt^ [p$state].specified THEN
      new_descriptor.state := pvt^ [p$state].value^.name_value;
    IFEND;

    IF pvt^ [p$application_information].specified THEN
      ALLOCATE new_descriptor.application_info_p:
            [STRLENGTH(pvt^[p$application_information].value^.string_value^)] IN osv$task_private_heap^;
      new_descriptor.application_info_p^ := pvt^ [p$application_information].value^.string_value^;
    IFEND;

    IF pvt^ [p$site_information].specified THEN
      ALLOCATE new_descriptor.site_info_p:
            [STRLENGTH(pvt^[p$site_information].value^.string_value^)] IN osv$task_private_heap^;
      new_descriptor.site_info_p^ := pvt^ [p$site_information].value^.string_value^;
    IFEND;

    cmp$crack_connection (pvt, command_name, connection_specified, new_descriptor, status);
    IF NOT status.normal THEN
      IF connection_specified THEN
        cmp$free_descriptor (new_descriptor);
      IFEND;
      RETURN;
    IFEND;

    IF cmv$command_descriptor_p <> NIL THEN
      current_p := cmv$command_descriptor_p;
      previous_p := current_p;
      found := FALSE;

    /link_list_loop/
      WHILE current_p <> NIL DO
        found := current_p^.element_name = element.element_name;
        IF found THEN
          EXIT /link_list_loop/;
        ELSE
          previous_p := current_p;
          current_p := current_p^.next_descriptor;
        IFEND;
      WHILEND /link_list_loop/;
    ELSE
      osp$set_status_condition ( cme$pcu_empty_file,  status);
      RETURN;
    IFEND;

    IF NOT found THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found,
            element.element_name, status);
    ELSE
      IF current_p^.connection <> new_descriptor.connection THEN
        IF connection_specified THEN
          CASE current_p^.connection OF
          = cmc$central_memory_connection =
            nil_pointer := (current_p^.cmc_list = NIL) AND (current_p^.channel_list = NIL);
          = cmc$iou_connection =
            nil_pointer := current_p^.iou_list = NIL;
          = cmc$peripheral_connection =
            nil_pointer := current_p^.pc_list = NIL;
          CASEND;
          IF NOT nil_pointer THEN
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_connection_not_found,
                  element.element_name, status);
            cmp$free_descriptor (new_descriptor);
            RETURN;
          IFEND;
        IFEND;
      IFEND;

      IF new_descriptor.same_as <> osc$null_name THEN
        current_p^.same_as := new_descriptor.same_as;
        current_p^.sn := 0;
        current_p^.ioupn := osc$null_name;
        current_p^.state := osc$null_name;
        current_p^.pid := osc$null_name;
      IFEND;

      IF new_descriptor.sn <> 0 THEN
        current_p^.sn := new_descriptor.sn;
      IFEND;

      IF new_descriptor.pid <> osc$null_name THEN
        current_p^.pid := new_descriptor.pid;
      IFEND;

      IF new_descriptor.state <> osc$null_name THEN
        current_p^.state := new_descriptor.state;
      IFEND;

      IF new_descriptor.ioupn <> osc$null_name THEN
        IF new_descriptor.ioupn = c$none THEN
          current_p^.ioupn := osc$null_name;
        ELSE
          current_p^.ioupn := new_descriptor.ioupn;
        IFEND;
      IFEND;

      current_p^.verify := new_descriptor.verify;
      IF new_descriptor.application_info_p <> NIL THEN
        IF current_p^.application_info_p = NIL THEN
          current_p^.application_info_p := new_descriptor.application_info_p;
        ELSE
          FREE current_p^.application_info_p IN osv$task_private_heap^;
          current_p^.application_info_p := new_descriptor.application_info_p;
        IFEND;
      IFEND;

      IF new_descriptor.site_info_p <> NIL THEN
        IF current_p^.site_info_p = NIL THEN
          current_p^.site_info_p := new_descriptor.site_info_p;
        ELSE
          FREE current_p^.site_info_p IN osv$task_private_heap^;
          current_p^.site_info_p := new_descriptor.site_info_p;
        IFEND;
      IFEND;
      IF connection_specified THEN
        current_p^.connection := new_descriptor.connection;
        CASE new_descriptor.connection OF
        = cmc$central_memory_connection =
          IF new_descriptor.cmc_list <> NIL THEN
            IF current_p^.cmc_list <> NIL THEN
              FREE current_p^.cmc_list IN osv$task_private_heap^;
            IFEND;
            current_p^.cmc_list := new_descriptor.cmc_list;
          IFEND;
          IF new_descriptor.channel_list <> NIL THEN
            IF current_p^.channel_list <> NIL THEN
              FREE current_p^.channel_list IN osv$task_private_heap^;
            IFEND;
            current_p^.channel_list := new_descriptor.channel_list;
          IFEND;
        = cmc$iou_connection =
          IF current_p^.iou_list <> NIL THEN
            FREE current_p^.iou_list IN osv$task_private_heap^;
          IFEND;
          current_p^.iou_list := new_descriptor.iou_list;
        = cmc$peripheral_connection =
          IF current_p^.pc_list <> NIL THEN
            FREE current_p^.pc_list IN osv$task_private_heap^;
          IFEND;
          current_p^.pc_list := new_descriptor.pc_list;
        CASEND;
      IFEND;
    IFEND;

  PROCEND cmp$change_definition;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$change_definition_name ', EJECT ??

{ This procedure change the Element name in a
{ physical configuration file


  PROCEDURE [XDCL, #GATE] cmp$change_definition_name
    (    element_name: cmt$element_name;
         new_element_name: cmt$element_name;
         change_references: boolean;
     VAR status: ost$status);

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      found: boolean,
      index: integer,
      i: integer,
      made_change: boolean;

    status.normal := TRUE;
    made_change := FALSE;

  /main_program/

    BEGIN
      cmp$check_reserved_names (new_element_name, cmv$reserved_names_list, status);
      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        WHILE current_p <> NIL DO
          IF current_p^.element_name = new_element_name THEN
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_already_defined,
                  new_element_name, status);
            EXIT /main_program/;
          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND;
      IFEND;

      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;

      /search_line/
        WHILE current_p <> NIL DO
          IF current_p^.element_name = element_name THEN
            made_change := TRUE;
            current_p^.element_name := new_element_name;
          IFEND;
          IF change_references THEN
            IF current_p^.same_as = element_name THEN
              current_p^.same_as := new_element_name;
            IFEND;
            CASE current_p^.connection OF
            = cmc$peripheral_connection =
              IF current_p^.pc_list <> NIL THEN

{ Scan every token of Peripheral connection list and change

                FOR index := LOWERBOUND (current_p^.pc_List^) TO UPPERBOUND (current_p^.pc_list^) DO
                  IF current_p^.pc_list^ [index].peripheral = element_name THEN
                    current_p^.pc_list^ [index].peripheral := new_element_name;
                  IFEND;
                FOREND;
              IFEND;
            ELSE
              ;
            CASEND;

          ELSE
            IF made_change THEN
              EXIT /search_line/;
            IFEND;
          IFEND;
          current_p := current_p^.next_descriptor;
        WHILEND /search_line/;

      IFEND;

      IF (NOT made_change) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, element_name,
              status);
      IFEND;

    END /main_program/;

  PROCEND cmp$change_definition_name;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$check_for_unique_ser_num', EJECT ??

{ PURPOSE:
{   This procedure checks for serial number uniqueness within
{   the physical configuration file.

  PROCEDURE cmp$check_for_unique_ser_num
    (    serial_num: ost$string;
         product_id: cmt$product_identification;
         input_fid: amt$file_identifier;
     VAR status: ost$status);

    VAR
      check_count: integer,
      eoi_addr: array [1 .. 1] of amt$access_info,
      element: ^cmt$element_definition,
      find_count: integer,
      loop_count: integer,
      loop_index: integer,
      ptr1: amt$segment_pointer;

    status.normal := TRUE;
    IF (product_id.product_number = '  $885') OR
           (product_id.product_number = ' $5682') THEN
      check_count := 2;
    ELSEIF (product_id.product_number = '  $895') THEN
      check_count := 4;
    ELSE
      check_count := 0;
    IFEND;
    eoi_addr [1].key := amc$eoi_byte_address;
    amp$get_segment_pointer (input_fid, amc$sequence_pointer, ptr1, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    RESET ptr1.sequence_pointer;
    amp$fetch_access_information (input_fid, eoi_addr, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    find_count := 0;
    IF eoi_addr [1].item_returned THEN
      loop_count := eoi_addr [1].eoi_byte_address DIV #SIZE (cmt$element_definition);
      FOR loop_index := 1 TO loop_count DO
        NEXT element IN ptr1.sequence_pointer;
        IF (element^.serial_number = serial_num.value) AND (element^.product_id = product_id) THEN
          find_count := find_count + 1;
          IF find_count > check_count THEN
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_ser_num,
                  element^.element_name, status);
            osp$append_status_parameter (osc$status_parameter_delimiter, serial_num.value, status);
            RETURN;
          IFEND;
        IFEND;
      FOREND;
    ELSE
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_file_error,
            'cmp$check_for_unique_ser_num', status);
    IFEND;

  PROCEND cmp$check_for_unique_ser_num;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$clean_up_list', EJECT ??

{ PURPOSE:
{    This procedure goes through the linked list built by EDIPC
{    and frees up all pointer allocated in task private.

  PROCEDURE [XDCL, #GATE] cmp$clean_up_list;

    VAR
      current_p,
      next_p: ^cmt$pcu_command_descriptor;

    IF cmv$command_descriptor_p <> NIL THEN

      current_p := cmv$command_descriptor_p;
      WHILE current_p <> NIL DO
        next_p := current_p^.next_descriptor;
        IF current_p <> cmv$command_descriptor_p THEN
          CASE current_p^.connection OF
          = cmc$central_memory_connection =
            IF current_p^.cmc_list <> NIL THEN
              FREE current_p^.cmc_list IN osv$task_private_heap^;
            IFEND;
            IF current_p^.channel_list <> NIL THEN
              FREE current_p^.channel_list IN osv$task_private_heap^;
            IFEND;
          = cmc$iou_connection =
            IF current_p^.iou_list <> NIL THEN
              FREE current_p^.iou_list IN osv$task_private_heap^;
            IFEND;
          = cmc$peripheral_connection =
            IF current_p^.pc_list <> NIL THEN
              FREE current_p^.pc_list IN osv$task_private_heap^;
            IFEND;
          ELSE
            ;
          CASEND;
          IF current_p^.application_info_p <> NIL THEN
            FREE current_p^.application_info_p IN osv$task_private_heap^;
          IFEND;
          IF current_p^.site_info_p <> NIL THEN
            FREE current_p^.site_info_p IN osv$task_private_heap^;
          IFEND;
          FREE current_p IN osv$task_private_heap^;
        IFEND;
        current_p := next_p;
      WHILEND;
      cmv$command_descriptor_p := NIL;
      cmv$end_list_p := NIL;
    IFEND;

  PROCEND cmp$clean_up_list;



?? OLDTITLE ??
?? NEWTITLE := '   cmp$close_in_out_files ', EJECT ??

{ PURPOSE:
{    This procedure closes the input and output file of the
{    PCU editor.

  PROCEDURE [XDCL, #GATE] cmp$close_in_out_files;

    VAR
      status: ost$status;

    fsp$close_file (cmv$output_fid, status);
    fsp$close_file (cmv$input_fid, status);

  PROCEND cmp$close_in_out_files;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$close_utility_files', EJECT ??

{ PURPOSE:
{    This procedures closes the global files used in the Physical
{    Configuration Utility to store definition of peripheral elements
{    and their state information.

  PROCEDURE [XDCL, #GATE] cmp$close_utility_files;

    VAR
      local_status: ost$status;

    amp$close (cmv$cmd_value_fid, local_status);
    amp$close (cmv$state_value_fid, local_status);
    amp$return (cmv$cmd_value_name, local_status);
    amp$return (cmv$state_value_name, local_status);

  PROCEND cmp$close_utility_files;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$compile_phys_configuration', EJECT ??

{ PURPOSE:
{   This procedure scans the physical configuration file and processes commands in the file. It can be called
{   by INSTALL_PHYSICAL_CONFIGURATION or VERIFY_PHYSICAL_CONFIGURATION.
{ NOTE:
{   Because it needs to access ring 3 data structures, the parameter value table is passed to this routine.
{   Therefore, any changes to the parameters of the above commands will result in changes to the variables
{   p$xxxxx used in this routine.

  PROCEDURE [XDCL, #GATE] cmp$compile_phys_configuration
    (    verify_only: boolean;
         pvt_p: ^clt$parameter_value_table;
     VAR status: ost$status);

    VAR
      cm_bool_p: ^ARRAY [1 .. * ] OF clt$boolean,
      cm_var: clt$variable_reference,
      contains_data: boolean,
      error_file: clt$file,
      existing_file: boolean,
      file_attributes: ARRAY [1 .. 1] OF amt$file_item,
      get_attr: ARRAY [1 .. 1] OF amt$get_item,
      input_file: clt$file,
      input_file_id: amt$file_identifier,
      interactive_input: boolean,
      local_file: boolean,
      local_status: ost$status,
      mainframe_name: cmt$element_name,
      mainframe_pct_name: amt$local_file_name,
      pc_fid: amt$file_identifier,
      p$mainframe: integer,
      p$input: integer,
      p$errors: integer,
      state_fid: amt$file_identifier,
      state_file_name: amt$local_file_name,
      syntax_error_found: boolean,
      unique_name: ost$unique_name;

    status.normal := TRUE;

    IF verify_only THEN
      p$mainframe := 1;
      p$input := 2;
      p$errors := 3;
      mainframe_name := pvt_p^ [p$mainframe].value^.name_value;
    ELSE
      p$input := 1;
      p$errors := 2;
      mainframe_name := cmv$installed_mainframe;
    IFEND;

    get_attr [1].key := amc$null_attribute;
    file_attributes [1].key := amc$access_mode;
    file_attributes [1].access_mode :=
          $pft$usage_selections [pfc$shorten, pfc$append, pfc$modify, pfc$read];
    syntax_error_found := FALSE;

    clp$convert_string_to_file (pvt_p^ [p$input].value^.file_value^, input_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    interactive_input := (input_file.local_file_name = '$COMMAND') OR
          (input_file.local_file_name = 'COMMAND');

    IF NOT interactive_input THEN
      get_attr [1].key := amc$file_processor;
      amp$get_file_attributes (pvt_p^ [p$input].value^.file_value^, get_attr, local_file, existing_file,
            contains_data, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF NOT contains_data OR NOT existing_file THEN
        osp$set_status_condition (cme$pcu_empty_file, status);
        RETURN;
      IFEND;
    IFEND;

    clp$convert_string_to_file (pvt_p^ [p$errors].value^.file_value^, error_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    cmp$open_scratch_err_file (status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

   /cleanup_needed/
    BEGIN
      IF NOT interactive_input THEN
        cmv$pcu_error_count := 0;
        clp$scan_command_file (input_file.local_file_name, 'PHYSICAL_CONFIGURATION_UTILITY ', 'PCU', status);
        IF cmv$pcu_error_count > 0 THEN
          syntax_error_found := TRUE;
          IF error_file.local_file_name <> clc$null_file THEN
            cmp$generate_error_listing (error_file.local_file_name, local_status);
            IF verify_only THEN
              osp$set_status_condition (cme$pcu_verpc_err, status);
            ELSE
              osp$set_status_condition (cme$pcu_inspc_err, status);
            IFEND;
            osp$append_status_integer (osc$status_parameter_delimiter, cmv$pcu_error_count, 10, FALSE,
                  status);
          IFEND;
          EXIT /cleanup_needed/;
        ELSEIF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
      IFEND;

      REPEAT
        pmp$generate_unique_name (unique_name, status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
        mainframe_pct_name := unique_name.value;
        amp$get_file_attributes (mainframe_pct_name, get_attr, local_file, existing_file, contains_data,
              status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
      UNTIL NOT local_file;

      REPEAT
        pmp$generate_unique_name (unique_name, status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
        state_file_name := unique_name.value;
        amp$get_file_attributes (state_file_name, get_attr, local_file, existing_file, contains_data, status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
      UNTIL NOT local_file;

     /files_opened/
      BEGIN
        amp$open (mainframe_pct_name, amc$segment, ^file_attributes, pc_fid, status);
        IF NOT status.normal THEN
          EXIT /files_opened/;
        IFEND;
        amp$open (state_file_name, amc$segment, ^file_attributes, state_fid, status);
        IF NOT status.normal THEN
          EXIT /files_opened/;
        IFEND;

        update_downward_connections (cmv$cmd_value_fid, pc_fid, status);
        IF NOT status.normal AND (status.condition = cme$lcu_sys_dev_path_not_found) AND
              (mainframe_name <> cmv$installed_mainframe) THEN
          status.normal := TRUE;
          EXIT /files_opened/;
        IFEND;
        IF NOT status.normal AND ((status.condition = cme$pcu_duplicate_pun) OR
                                  (status.condition = cme$pcu_duplicate_pen)) THEN
          EXIT /files_opened/;
        IFEND;

        cmp$build_active_conf (pc_fid, cmv$cmd_value_fid, cmv$state_value_fid, state_fid, mainframe_name,
              status);
        IF NOT status.normal AND (status.condition = cme$lcu_sys_dev_path_not_found) AND
              (mainframe_name <> cmv$installed_mainframe) THEN
          status.normal := TRUE;
          EXIT /files_opened/;
        IFEND;
      END /files_opened/;
      amp$close (pc_fid, local_status);
      amp$return (mainframe_pct_name, local_status);
      IF NOT status.normal THEN
        EXIT /cleanup_needed/;
      IFEND;

      IF NOT verify_only AND NOT cmv$configuration_activated THEN

        { Build the physical configuration tables and proceed to activate the configuration.

        cmp$build_conf_tables (cmv$cmd_value_fid, state_fid, status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;

        cmp$acquire_all_peripherals (status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;

        cmp$set_active_flag (TRUE);
        PUSH cm_bool_p: [1 .. 1];
        cm_bool_p^ [1].value := TRUE;
        cm_bool_p^ [1].kind := clc$true_false_boolean;
        clp$read_variable ('CMV$CONFIGURATION_ACTIVATED', cm_var, local_status);
        cm_var.value.boolean_value := cm_bool_p;
        clp$write_variable ('CMV$CONFIGURATION_ACTIVATED', cm_var.value, local_status);

        amp$open (input_file.local_file_name, amc$record, ^file_attributes, input_file_id, status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
        cmp$install_system_conf (input_file_id, status);
        IF NOT status.normal THEN
          EXIT /cleanup_needed/;
        IFEND;
      IFEND;
    END /cleanup_needed/;

    IF NOT status.normal AND NOT syntax_error_found THEN
      IF error_file.local_file_name <> '$NULL' THEN
        cmp$echo_errors (FALSE, status);
        cmp$generate_error_listing (error_file.local_file_name, local_status);
        IF verify_only THEN
          osp$set_status_condition (cme$pcu_verpc_err, status);
        ELSE
          osp$set_status_condition (cme$pcu_inspc_err, status);
        IFEND;
        osp$append_status_integer (osc$status_parameter_delimiter, 1, 10, FALSE, status);
      IFEND;
    IFEND;

    IF NOT cmv$executing_within_editor THEN
      cmp$clean_up_list;
      cmp$clean_up_error_count;
      cmp$close_utility_files;
      amp$close (input_file_id, local_status);
      amp$close (state_fid, local_status);
      amp$return (state_file_name, local_status);
      cmp$open_utility_files (local_status);
      cmv$pcu_error_count := 0;
    IFEND;

  PROCEND cmp$compile_phys_configuration;
?? OLDTITLE ??
?? NEWTITLE := '   cmp$crack_connection', EJECT ??

{ PURPOSE:
{    This procedure processes the connections parameter of the PCU subcommands.

  PROCEDURE [XDCL, #GATE] cmp$crack_connection
    (    parameter_value_table: ^clt$parameter_value_table;
         command_name: string ( * <= osc$max_name_size);
     VAR connection_specified: boolean;
     VAR command: cmt$pcu_command_descriptor;
     VAR status: ost$status);


    VAR
      channel_name: cmt$element_name,
      current_list_entry: ^clt$data_value,
      equipment_number: cmt$physical_equipment_number,
      element_definition: cmt$element_definition,
      field_index: integer,
      iou_name: cmt$element_name,
      iou_number: dst$iou_number,
      list_index: integer,
      mainframe_name: cmt$element_name,
      number_of_entries: integer,
      peripheral_element: cmt$element_name,
      physical_address: cmt$physical_unit_number,
      port: 0 .. 3,
      specified_address: boolean;

    status.normal := TRUE;
    connection_specified := FALSE;

    IF parameter_value_table^ [p$peripheral_connection].specified THEN
      connection_specified := TRUE;
      command.connection := cmc$peripheral_connection;
      current_list_entry := parameter_value_table^ [p$peripheral_connection].value;
      number_of_entries := clp$count_list_elements (parameter_value_table^ [p$peripheral_connection].value);
      IF number_of_entries > 0 THEN
        ALLOCATE command.pc_list: [1 .. number_of_entries] IN osv$task_private_heap^;
      IFEND;
      list_index := 0;
      physical_address := 0;
      specified_address := FALSE;
      WHILE current_list_entry <> NIL DO
        FOR field_index := LOWERBOUND (current_list_entry^.element_value^.field_values^)
              TO UPPERBOUND (current_list_entry^.element_value^.field_values^) DO
          IF (current_list_entry^.element_value^.field_values^ [field_index].name = 'PERIPHERAL_ELEMENT') THEN
            IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
              cmp$check_reserved_names (current_list_entry^.element_value^.field_values^ [field_index].value^.
                    name_value, cmv$reserved_names_list, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;
              peripheral_element := current_list_entry^.element_value^.field_values^ [field_index].value^.
                    name_value;
            ELSE
              osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters,
                  'PERIPHERAL_ELEMENT', status);
              osp$append_status_parameter (osc$status_parameter_delimiter,
                        parameter_value_table^ [p$element].value^.name_value, status);
              RETURN;
            IFEND;
          ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name =
                'PHYSICAL_ADDRESS') THEN
            IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
              IF NOT specified_address THEN
                specified_address := TRUE;
                physical_address := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      integer_value.value;
              ELSE
                IF physical_address <> current_list_entry^.element_value^.field_values^ [field_index].value^.
                      integer_value.value THEN
                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                        'Physical address mismatch on PERIPHERAL CONNECTIONS', status);
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        parameter_value_table^ [p$element].value^.name_value, status);
                  RETURN;
                IFEND;
              IFEND;
            IFEND;
          IFEND;
        FOREND;
        list_index := list_index + 1;
        command.pc_list^ [list_index].address := physical_address;
        command.pc_list^ [list_index].peripheral := peripheral_element;
        current_list_entry := current_list_entry^.link;
      WHILEND;

    ELSE

{ If IOU_CONNECTION is specified, must also check CENTRAL_MEMORY_CONNECTION
{ in case element is an external processor.

      IF parameter_value_table^ [p$iou_connection].specified THEN
        connection_specified := TRUE;
        IF command.connection <> cmc$central_memory_connection THEN
          command.connection := cmc$iou_connection;
        IFEND;
        current_list_entry := parameter_value_table^ [p$iou_connection].value;
        number_of_entries := clp$count_list_elements (parameter_value_table^ [p$iou_connection].value);
        IF number_of_entries > 0 THEN
          IF command.connection = cmc$iou_connection THEN
            ALLOCATE command.iou_list: [1 .. number_of_entries] IN osv$task_private_heap^;
          ELSE
            ALLOCATE command.channel_list: [1 .. number_of_entries] IN osv$task_private_heap^;
          IFEND;
        IFEND;
        list_index := 0;
        specified_address := FALSE;
        equipment_number := 0;
        WHILE current_list_entry <> NIL DO
          iou_name := 'IOU0';
          channel_name := osc$null_name;

{ If the command DEFINE_ELEMENT is processed then take the mainframe name from the
{ last DEFINE_WORKING_MAINFRAME command. For other PCU Editor commands, take the
{ mainframe name from the current mainframe id unless specified in the IOU connection.

          IF command_name = 'DEFINE_ELEMENT' THEN
            mainframe_name := cmv$mainframe_name;
          ELSE
            mainframe_name := cmv$installed_mainframe;
          IFEND;
          FOR field_index := LOWERBOUND (current_list_entry^.element_value^.field_values^)
                TO UPPERBOUND (current_list_entry^.element_value^.field_values^) DO
            IF (current_list_entry^.element_value^.field_values^ [field_index].name = 'CHANNEL') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                channel_name := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      name_value;
                IF NOT cmp$valid_channel_name (channel_name) THEN
                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_channel_number,
                        command_name, status);
                  osp$append_status_parameter (osc$status_parameter_delimiter, channel_name, status);
                  RETURN;
                IFEND;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name =
                  'EQUIPMENT') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                IF NOT specified_address THEN
                  specified_address := TRUE;
                  equipment_number := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      integer_value.value;
                ELSE
                  IF equipment_number <> current_list_entry^.element_value^.field_values^ [field_index]
                      .value^.integer_value.value THEN
                    osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                         'Physical address mismatch on IOU CONNECTIONS', status);
                    osp$append_status_parameter (osc$status_parameter_delimiter,
                         parameter_value_table^ [p$element].value^.name_value, status);
                    RETURN;
                  IFEND;
                IFEND;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name = 'MAINFRAME') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                mainframe_name := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      name_value;
                cmp$validate_mainframe_name (mainframe_name, status);
                IF NOT status.normal THEN
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        parameter_value_table^ [p$element].value^.name_value, status);
                  RETURN;
                IFEND;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name = 'IOU') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                iou_name := current_list_entry^.element_value^.field_values^ [field_index].value^.name_value;
                cmp$convert_iou_name (iou_name, iou_number, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;
              IFEND;
            IFEND;
          FOREND;
          list_index := list_index + 1;
          IF command.connection = cmc$central_memory_connection THEN
            command.channel_list^ [list_index].iou := iou_name;
            command.channel_list^ [list_index].channel := channel_name;
            command.channel_list^ [list_index].equipment := equipment_number;
            command.channel_list^ [list_index].mainframe := mainframe_name;
          ELSEIF command.connection = cmc$iou_connection THEN
            command.iou_list^ [list_index].mainframe := mainframe_name;
            command.iou_list^ [list_index].channel := channel_name;
            command.iou_list^ [list_index].iou := iou_name;
            command.iou_list^ [list_index].equipment := equipment_number;
          IFEND;
          current_list_entry := current_list_entry^.link;
        WHILEND;
      IFEND;

      IF parameter_value_table^ [p$central_memory_connection].specified THEN
        connection_specified := TRUE;
        command.connection := cmc$central_memory_connection;
        current_list_entry := parameter_value_table^ [p$central_memory_connection].value;
        number_of_entries := clp$count_list_elements (parameter_value_table^ [p$central_memory_connection].
              value);
        IF number_of_entries > 0 THEN
          ALLOCATE command.cmc_list: [1 .. number_of_entries] IN osv$task_private_heap^;
        IFEND;
        list_index := 0;
        port := 0;
        WHILE current_list_entry <> NIL DO
          IF command_name = 'DEFINE_ELEMENT' THEN
            mainframe_name := cmv$mainframe_name;
          ELSE
            mainframe_name := cmv$installed_mainframe;
          IFEND;
          FOR field_index := LOWERBOUND (current_list_entry^.element_value^.field_values^)
                TO UPPERBOUND (current_list_entry^.element_value^.field_values^) DO
            IF (current_list_entry^.element_value^.field_values^ [field_index].name = 'PORT') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                port := current_list_entry^.element_value^.field_values^ [field_index].value^.integer_value.
                      value;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name = 'MAINFRAME') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                mainframe_name := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      name_value;
              IFEND;
            IFEND;
          FOREND;
          list_index := list_index + 1;
          command.cmc_list^ [list_index].port := port;
          command.cmc_list^ [list_index].mainframe := mainframe_name;
          current_list_entry := current_list_entry^.link;
        WHILEND;
      IFEND;
    IFEND;

  PROCEND cmp$crack_connection;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$crack_parameters', EJECT ??

{ PURPOSE :
{    This procedure crack the parameters of the PCU subcommands
{    that have common parameter passing requirements.
{    Following commands will use this routine:
{      DEFINE_ELEMENT
{      ADD_ELEMENT_DEFINITION
{      REPLACE_ELEMENT_DEFINITION

  PROCEDURE [XDCL, #GATE] cmp$crack_parameters
    (    parameter_value_table: ^clt$parameter_value_table;
         command_name: string ( * <= osc$max_name_size);
     VAR status: ost$status);

    VAR
      command: cmt$pcu_command_descriptor,
      connection_specified: boolean,
      dummy: cmt$pcu_command_descriptor,
      element: cmt$element_definition,
      found: boolean,
      product_index: 1..7,
      same_as: boolean,
      same_as_name: ost$name,
      same_as_element: cmt$pcu_command_descriptor,
      save_abnormal_status: boolean,
      saved_status: ost$status,
      standard_product: boolean;

    status.normal := TRUE;
    saved_status.normal := TRUE;
    save_abnormal_status := (command_name = 'DEFINE_ELEMENT                 ');

    initialize_descriptor (command);

    cmp$check_reserved_names (parameter_value_table^ [p$element].value^.name_value, cmv$reserved_names_list,
          status);
    IF NOT status.normal THEN
      IF save_abnormal_status THEN
        IF saved_status.normal THEN
          saved_status := status;
        IFEND;
      ELSE
        RETURN;
      IFEND;
    IFEND;
    {
    { Reject request if element is already defined.
    {
    cmp$search_edited_file (parameter_value_table^ [p$element].value^.name_value, 0, element.product_id,
          found, dummy);
    IF found AND (command_name <> 'REPLACE_ELEMENT_DEFINITION') THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_already_defined,
            parameter_value_table^ [p$element].value^.name_value, status);
      RETURN;
    IFEND;

    element.element_name := parameter_value_table^ [p$element].value^.name_value;
    command.element_name := parameter_value_table^ [p$element].value^.name_value;

    same_as := parameter_value_table^ [p$same_as].specified;
    IF same_as THEN
      same_as_name := parameter_value_table^ [p$same_as].value^.name_value;
      cmp$search_edited_file (same_as_name, 0, element.product_id, found, same_as_element);
      IF found THEN
        command.pid := same_as_element.pid;
        command.ioupn := same_as_element.ioupn;
        command.sn := same_as_element.sn;
        command.state := same_as_element.state;
        IF NOT parameter_value_table^ [p$element_identification].specified THEN

{ Set the product id value to what it is in the edited file only if the element id is
{ not specified.

          /find_product_number/
          FOR product_index := 1 to 7 DO
            IF command.pid(product_index) = '_' THEN
              EXIT /find_product_number/;
            IFEND;
          FOREND /find_product_number/;
          element.product_id.product_number := '      ';
          element.product_id.product_number (6+2-product_index, product_index-1) :=
                command.pid(1, product_index-1);
          element.product_id.underscore := '_';
          element.product_id.model_number := '   ';
          element.product_id.model_number := command.pid(product_index+1, 3)
        IFEND;
      ELSE
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_same_as_not_defined, same_as_name,
              status);
        IF save_abnormal_status THEN
          IF saved_status.normal THEN
            saved_status := status;
          IFEND;
        ELSE
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    command.verify := parameter_value_table^ [p$verify_element_identification].value^.boolean_value.value;
    standard_product := command.verify;

    IF parameter_value_table^ [p$element_identification].specified THEN
      command.pid := parameter_value_table^ [p$element_identification].value^.name_value;
      cmp$get_product_id (command.pid, element, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    ELSE
      IF NOT same_as THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters,
              'ELEMENT_IDENTIFICATION', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element.element_name, status);
        IF save_abnormal_status THEN
          saved_status := status;
        ELSE
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    IF standard_product THEN
      IF NOT cmp$known_controller_id (element.product_id) AND NOT cmp$known_product_id
            (element.product_id) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_unknown_product_id,
              command.pid, status);
        RETURN;
      IFEND;

      cmp$determine_element_type (command.pid, element, status);
      IF NOT status.normal THEN
        IF save_abnormal_status THEN
          IF saved_status.normal THEN
            saved_status := status;
          IFEND;
        ELSE
          RETURN;
        IFEND;
      IFEND;
    ELSE
      IF cmp$known_controller_id (element.product_id) OR cmp$known_product_id (element.product_id) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
              'Invalid usage of VERIFY_ELEMENT_IDENTIFICATION parameter', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element.element_name, status);
        RETURN;
      IFEND;
    IFEND;

    IF parameter_value_table^ [p$serial_number].specified THEN
      command.sn := parameter_value_table^ [p$serial_number].value^.integer_value.value;
    ELSE
      IF NOT same_as THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters, 'SERIAL_NUMBER',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element.element_name, status);
        IF save_abnormal_status THEN
          IF saved_status.normal THEN
            saved_status := status;
          IFEND;
        ELSE
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    IF parameter_value_table^ [p$state].specified THEN
      command.state := parameter_value_table^ [p$state].value^.name_value;
    ELSE
      IF NOT same_as THEN
        command.state := 'ON';
      IFEND;
    IFEND;

    IF parameter_value_table^ [p$iou_program_name].specified AND standard_product AND
          (element.element_type = cmc$storage_device_element) THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
            'IOU program name cannot be specified on a storage device', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, element.element_name, status);
      IF save_abnormal_status THEN
        IF saved_status.normal THEN
          saved_status := status;
        IFEND;
      ELSE
        RETURN;
      IFEND;
    IFEND;

    IF parameter_value_table^ [p$iou_program_name].specified THEN
      command.ioupn := parameter_value_table^ [p$iou_program_name].value^.name_value;
    ELSE
      command.ioupn := osc$null_name;
    IFEND;

    IF parameter_value_table^ [p$central_memory_connection].specified THEN
      command.connection := cmc$central_memory_connection;
    ELSEIF parameter_value_table^ [p$peripheral_connection].specified THEN
      command.connection := cmc$peripheral_connection;
    ELSE
      command.connection := cmc$iou_connection;
    IFEND;

    cmp$crack_connection (parameter_value_table, command_name, connection_specified, command, status);
    IF NOT connection_specified THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters, 'CONNECTIONS',
            status);
      osp$append_status_parameter (osc$status_parameter_delimiter, element.element_name, status);
    IFEND;

    IF NOT status.normal THEN
      cmp$free_descriptor (command);
      RETURN;
    IFEND;

    IF parameter_value_table^ [p$application_information].specified THEN
      ALLOCATE command.application_info_p: [STRLENGTH (parameter_value_table^ [p$application_information].
            value^.string_value^)] IN osv$task_private_heap^;
      command.application_info_p^ := parameter_value_table^ [p$application_information].value^.string_value^;
    IFEND;

    IF parameter_value_table^ [p$site_information].specified THEN
      ALLOCATE command.site_info_p: [STRLENGTH (parameter_value_table^ [p$site_information].value^.
            string_value^)] IN osv$task_private_heap^;
      command.site_info_p^ := parameter_value_table^ [p$site_information].value^.string_value^;
    IFEND;

    IF command_name = 'ADD_ELEMENT_DEFINITION' THEN
      cmp$add_definition (command, status);
    ELSEIF command_name = 'REPLACE_ELEMENT_DEFINITION' THEN
      cmp$replace_definition (command.element_name, command, status);
    ELSEIF command_name = 'DEFINE_ELEMENT' THEN
      cmp$build_descriptor (command, status);
      IF (NOT saved_status.normal) AND status.normal THEN
        status := saved_status;
      IFEND;
    IFEND;

  PROCEND cmp$crack_parameters;
?? OLDTITLE ??
?? NEWTITLE := '   cmp$delete_all_elements', EJECT ??

{ PURPOSE:
{    This procedure goes thru the list of names defined
{  in the physical configuration file and matchs each of them with
{  the names in the exclude names list. If a match is not found then it deletes
{  the name.


  PROCEDURE [XDCL, #GATE] cmp$delete_all_elements
    (    exclude_names_list_p: ^array [ * ] of cmt$element_name;
     VAR status: ost$status);

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      found: boolean,
      list_index: integer;

    status.normal := TRUE;
    IF cmv$command_descriptor_p <> NIL THEN
      current_p := cmv$command_descriptor_p;
      WHILE current_p <> NIL DO
        found := FALSE;
        IF exclude_names_list_p <> NIL THEN

        /match_name/
          FOR list_index := LOWERBOUND (exclude_names_list_p^) TO UPPERBOUND (exclude_names_list_p^) DO
            IF exclude_names_list_p^ [list_index] = current_p^.element_name THEN
              found := TRUE;
              EXIT /match_name/;
            IFEND;
          FOREND /match_name/;
        IFEND;
        IF NOT found THEN
          cmp$delete_definition (current_p^.element_name, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        IFEND;
        current_p := current_p^.next_descriptor;
      WHILEND;
    ELSE
      osp$set_status_condition ( cme$pcu_empty_file,  status);
    IFEND;

  PROCEND cmp$delete_all_elements;

?? OLDTITLE ??
?? NEWTITLE := '   cpm$delete_definition', EJECT ??

{ PURPOSE:
{    This procedure search for an element name in a
{    configuration file and delete its definition


  PROCEDURE [XDCL, #GATE] cmp$delete_definition
    (    element_name: cmt$element_name;
     VAR status: ost$status);

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      found: boolean,
      previous_p: ^cmt$pcu_command_descriptor;

    status.normal := TRUE;

  /main_program/
    BEGIN
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        previous_p := current_p;
        found := FALSE;

      /link_list_loop/
        WHILE current_p <> NIL DO
          found := current_p^.element_name = element_name;
          IF found THEN
            IF current_p = cmv$command_descriptor_p THEN
              cmv$command_descriptor_p := current_p^.next_descriptor;
              IF current_p = cmv$end_list_p THEN
                cmv$end_list_p := current_p^.next_descriptor;
              IFEND;
            ELSE
              previous_p^.next_descriptor := current_p^.next_descriptor;
              IF current_p = cmv$end_list_p THEN
                cmv$end_list_p := previous_p;
              IFEND;
            IFEND;
            EXIT /link_list_loop/;
          ELSE
            previous_p := current_p;
            current_p := current_p^.next_descriptor;
          IFEND;

        WHILEND /link_list_loop/;
      ELSE
        osp$set_status_condition ( cme$pcu_empty_file,  status);
        EXIT /main_program/;
      IFEND;

      IF found THEN
        cmp$free_descriptor (current_p^);
        FREE current_p IN osv$task_private_heap^;
      ELSE
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, element_name,
              status);
      IFEND;

    END /main_program/;

  PROCEND cmp$delete_definition;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$determine_element_type', EJECT ??

{ PURPOSE:
{   This procedure figures out the element type given the product id string,
{   then stores the product id into a CYBIL type cmt$product_identification.

  PROCEDURE [XDCL, #GATE] cmp$determine_element_type
    (    product_id_string: ost$name;
     VAR element_definition: cmt$element_definition;
     VAR status: ost$status);

    VAR
      local_product_id: ost$name;

    status.normal := TRUE;

    local_product_id := product_id_string;
    cmp$get_product_id(local_product_id, element_definition, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF cmp$known_controller_id (element_definition.product_id) THEN
      IF element_definition.product_id.product_number = '$65354' THEN
        element_definition.element_type := cmc$external_processor_element;
      ELSEIF element_definition.product_id.product_number = ' $2629' THEN
        element_definition.element_type := cmc$channel_adapter_element;
      ELSEIF (element_definition.product_id.product_number = '  $380') OR
            (element_definition.product_id.product_number = ' $2620') OR
            (element_definition.product_id.product_number = ' $5380') OR
            (element_definition.product_id.product_number = ' $4000') OR
            (element_definition.product_id.product_number = ' $7040') OR
            (element_definition.product_id.product_number = ' $2621') THEN
        element_definition.element_type := cmc$communications_element;
      ELSE
        element_definition.element_type := cmc$controller_element;
      IFEND;
    ELSE
      IF cmp$known_product_id (element_definition.product_id) THEN
        element_definition.element_type := cmc$storage_device_element;
      IFEND;
    IFEND;

  PROCEND cmp$determine_element_type;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$display_descriptor', EJECT ??

{ PURPOSE:
{    This procedure displays the DEFINE_ELEMENT command
{    from the input file to EDIT_PHYSICAL_CONFIGURATION.

  PROCEDURE cmp$display_descriptor
    (    current_p: ^cmt$pcu_command_descriptor;
         fid: amt$file_identifier;
     VAR status: ost$status);

    VAR
      byte_address: amt$file_byte_address,
      in_line: string (osc$max_string_size),
      index: integer,
      i: 0 .. osc$max_string_size,
      line: string (osc$max_string_size),
      option: clt$data_representation_option,
      representation: ^clt$data_representation,
      string_count: ^clt$data_representation_count,
      string_ptr: ^clt$string_value,
      string_size: ^clt$string_size,
      str: ost$string,
      value: clt$data_value,
      work_area: ^^clt$work_area;

    line := '    ';
    line (2, 19) := 'DEFINE_ELEMENT E = ';
    line (21, 31) := current_p^.element_name;
    trim_blank (line, i);
    IF current_p^.same_as <> osc$null_name THEN
      line (i, 10) := 'SAME_AS = ';
      line (i + 11, 31) := current_p^.same_as;
      trim_blank (line, i);
    IFEND;
    line (i, 2) := '..';
    i := i + 2;
    amp$put_next (fid, ^line, i, byte_address, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    line := '   ';

    IF current_p^.pid <> osc$null_name THEN
      line (5, 25) := 'ELEMENT_IDENTIFICATION = ';
      line (30, 10) := current_p^.pid;
      trim_blank (line, i);
    IFEND;


    IF current_p^.state <> osc$null_name THEN
      line (i, 8) := 'STATE = ';
      line (i + 8, 5) := current_p^.state;
      trim_blank (line, i);
    IFEND;
    IF current_p^.sn <> 0 THEN
      line (i, 16) := 'SERIAL_NUMBER = ';
      clp$convert_integer_to_string (current_p^.sn, 10, FALSE, str, status);
      line (i + 16, str.size) := str.value (1, str.size);
      trim_blank (line, i);
    IFEND;
    line (i, 2) := '..';
    i := i + 2;
    amp$put_next (fid, ^line, i, byte_address, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    line := '  ';
    IF current_p^.ioupn <> osc$null_name THEN
      line (5, 19) := 'IOU_PROGRAM_NAME = ';
      line (24, 31) := current_p^.ioupn;
      trim_blank (line, i);
      line (i, 2) := '..';
      i := i + 2;
      amp$put_next (fid, ^line, i, byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      line := '   ';
    IFEND;

    CASE current_p^.connection OF
    = cmc$central_memory_connection =
      IF current_p^.cmc_list <> NIL THEN
        line (5, 28) := 'CENTRAL_MEMORY_CONNECTION = ';
        line (34, 4) := '( ..';
        amp$put_next (fid, ^line, i, byte_address, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        FOR index := LOWERBOUND (current_p^.cmc_list^) TO UPPERBOUND (current_p^.cmc_list^) DO
          line := '   ';
          line (10, 2) := ' (';
          clp$convert_integer_to_string (current_p^.cmc_list^ [index].port, 10, FALSE, str, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          line (13, * ) := str.value;
          trim_blank (line, i);
          line (i, * ) := current_p^.cmc_list^ [index].mainframe;
          trim_blank (line, i);
          IF index = UPPERBOUND (current_p^.cmc_list^) THEN
            line (i, 5) := ')) ..';
          ELSE
            line (i, 5) := ')  ..';
          IFEND;
          i := i + 5;
          amp$put_next (fid, ^line, i, byte_address, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        FOREND;
      IFEND;
      line := '    ';
      IF current_p^.channel_list <> NIL THEN
        line (5, 17) := 'IOU_CONNECTION = ';
        line (22, 4) := '( ..';
        amp$put_next (fid, ^line, 30, byte_address, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        FOR index := LOWERBOUND (current_p^.channel_list^) TO UPPERBOUND (current_p^.channel_list^) DO
          line := '   ';
          line (10, 2) := '( ';
          line (13, * ) := current_p^.channel_list^ [index].channel;
          trim_blank (line, i);
          clp$convert_integer_to_string (current_p^.channel_list^ [index].equipment, 10, FALSE, str, status);
          line (i, * ) := str.value;
          trim_blank (line, i);
          IF current_p^.channel_list^ [index].mainframe <> osc$null_name THEN
            line (i, * ) := current_p^.channel_list^ [index].mainframe;
            trim_blank (line, i);
          IFEND;
          IF current_p^.channel_list^ [index].iou <> osc$null_name THEN
            line (i, * ) := current_p^.channel_list^ [index].iou;
            trim_blank (line, i);
          IFEND;
          IF index = UPPERBOUND (current_p^.channel_list^) THEN
            line (i, 5) := ')) ..';
          ELSE
            line (i, 5) := ')  ..';
          IFEND;
          i := i + 5;
          amp$put_next (fid, ^line, i, byte_address, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        FOREND;

      IFEND;


    = cmc$iou_connection =
      IF current_p^.iou_list <> NIL THEN
        line (5, 17) := 'IOU_CONNECTION = ';
        line (22, 4) := '( ..';
        amp$put_next (fid, ^line, 30, byte_address, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        FOR index := LOWERBOUND (current_p^.iou_list^) TO UPPERBOUND (current_p^.iou_list^) DO
          line := '   ';
          line (10, 2) := '( ';
          line (13, * ) := current_p^.iou_list^ [index].channel;
          trim_blank (line, i);
          clp$convert_integer_to_string (current_p^.iou_list^ [index].equipment, 10, FALSE, str, status);
          line (i, * ) := str.value;
          trim_blank (line, i);
          IF current_p^.iou_list^ [index].mainframe <> osc$null_name THEN
            line (i, * ) := current_p^.iou_list^ [index].mainframe;
            trim_blank (line, i);
          IFEND;
          IF current_p^.iou_list^ [index].iou <> osc$null_name THEN
            line (i, * ) := current_p^.iou_list^ [index].iou;
            trim_blank (line, i);
          IFEND;
          IF index = UPPERBOUND (current_p^.iou_list^) THEN
            line (i, 5) := ')) ..';
          ELSE
            line (i, 5) := ')  ..';
          IFEND;
          i := i + 5;
          amp$put_next (fid, ^line, i, byte_address, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        FOREND;
      IFEND;

    = cmc$peripheral_connection =
      IF current_p^.pc_list <> NIL THEN
        line (5, 24) := 'PERIPHERAL_CONNECTION = ';
        line (29, 4) := '( ..';
        amp$put_next (fid, ^line, 34, byte_address, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        FOR index := LOWERBOUND (current_p^.pc_list^) TO UPPERBOUND (current_p^.pc_list^) DO
          line := '  ';
          line (10, 2) := ' (';
          line (13, * ) := current_p^.pc_list^ [index].peripheral;
          trim_blank (line, i);
          clp$convert_integer_to_string (current_p^.pc_list^ [index].address, 10, FALSE, str, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          line (i, * ) := str.value;
          trim_blank (line, i);
          IF index = UPPERBOUND (current_p^.pc_list^) THEN
            line (i, 5) := ')) ..';
          ELSE
            line (i, 5) := ')  ..';
          IFEND;
          i := i + 5;
          amp$put_next (fid, ^line, i, byte_address, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        FOREND;
      IFEND;
    CASEND;

    line := '    ';
    line (5, 32) := 'VERIFY_ELEMENT_IDENTIFICATION = ';
    IF current_p^.verify THEN
      IF (current_p^.application_info_p <> NIL) OR (current_p^.site_info_p <> NIL) THEN
        line (37, 8) := 'TRUE ..';
      ELSE
        line (37, 5) := 'TRUE ';
      IFEND;
    ELSE
      IF (current_p^.application_info_p <> NIL) OR (current_p^.site_info_p <> NIL) THEN
        line (37, 8) := 'FALSE ..';
      ELSE
        line (37, 5) := 'FALSE';
      IFEND;
    IFEND;
    amp$put_next (fid, ^line, 45, byte_address, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    line := '  ';
    IF (current_p^.application_info_p <> NIL) OR (current_p^.site_info_p <> NIL) THEN
      clp$get_work_area (#RING (^work_area), work_area, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;
    IF current_p^.application_info_p <> NIL THEN
      line (5, 28) := 'APPLICATION_INFORMATION = ..';
      amp$put_next (fid, ^line, 33, byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      value.kind := clc$string;
      value.string_value := current_p^.application_info_p;
      clp$convert_data_to_string (^value, clc$data_source_representation, 65, work_area^,
            representation, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      NEXT string_count IN representation;
      FOR i := 1 TO string_count^ DO
        line := ' ';
        NEXT string_size IN representation;
        NEXT string_ptr: [string_size^] IN representation;
        line (11, string_size^) := string_ptr^;
        IF (i = string_count^) AND (current_p^.site_info_p <> NIL) THEN
          line (string_size^+11, 3) := ' ..';
        IFEND;
        #TRANSLATE(osv$lower_to_upper, line, line);
        amp$put_next (fid, ^line, string_size^+14, byte_address, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      FOREND;
      RESET work_area^ TO representation;
    IFEND;
    IF current_p^.site_info_p <> NIL THEN
      line := '   ';
      line (5, 21) := 'SITE_INFORMATION = ..';
      amp$put_next (fid, ^line, 26, byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      value.kind := clc$string;
      value.string_value := current_p^.site_info_p;
      clp$convert_data_to_string (^value, clc$data_source_representation, 65, work_area^,
            representation, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      NEXT string_count IN representation;
      FOR i := 1 TO string_count^ DO
        line := '  ';
        NEXT string_size IN representation;
        NEXT string_ptr: [string_size^] IN representation;
        line (11, string_size^) := string_ptr^;
        #TRANSLATE(osv$lower_to_upper, line, line);
        amp$put_next (fid, ^line, string_size^+11, byte_address, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      FOREND;
      RESET work_area^ TO representation;
    IFEND;
    line := '  ';
    amp$put_next (fid, ^line, 2, byte_address, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND cmp$display_descriptor;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$display_elements_def', EJECT ??

{ PURPOSE:
{    This procedures display the command definition of an
{    element name.

  PROCEDURE [XDCL, #GATE] cmp$display_elements_def
    (    display_option: cmt$lcu_display_option_key;
         display_by_name: boolean;
         name: cmt$element_name;
         file_id: amt$file_identifier;
     VAR status: ost$status);

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      display_once: boolean,
      element: cmt$element_definition,
      found: boolean,
      index: ost$string_index,
      same_as_p: ^cmt$pcu_command_descriptor;

    status.normal := TRUE;
    display_once := FALSE;
    found := FALSE;

  /main_program/
    BEGIN

      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        IF NOT display_by_name THEN
          CASE display_option OF
          = cmc$lcu_do_all =
            WHILE current_p <> NIL DO
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;
              cmp$display_descriptor (current_p, file_id, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;
              display_once := TRUE;
              current_p := current_p^.next_descriptor;
            WHILEND;

          = cmc$lcu_do_channel =
            ;
          = cmc$lcu_do_controller =
            WHILE current_p <> NIL DO
              IF current_p^.pid <> osc$null_name THEN
                cmp$determine_element_type (current_p^.pid, element, status);
              ELSE
                same_as_p := cmv$command_descriptor_p;

              /same_as_loop_1/
                WHILE same_as_p <> NIL DO
                  IF same_as_p^.element_name = current_p^.same_as THEN
                    cmp$determine_element_type (same_as_p^.pid, element, status);
                    EXIT /same_as_loop_1/;
                  ELSE
                    same_as_p := same_as_p^.next_descriptor;
                  IFEND;
                WHILEND /same_as_loop_1/;
              IFEND;
              IF NOT status.normal THEN
                status.normal := TRUE;
                IF current_p^.connection = cmc$iou_connection THEN
                  IF current_p^.iou_list <> NIL THEN
                    element.element_type := cmc$controller_element;
                  IFEND;
                IFEND;
              IFEND;
              IF element.element_type = cmc$controller_element THEN
                cmp$display_descriptor (current_p, file_id, status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;
                display_once := TRUE;
              IFEND;
              current_p := current_p^.next_descriptor;
            WHILEND;

          = cmc$lcu_do_channel_adapter =
            WHILE current_p <> NIL DO
              IF current_p^.pid <> osc$null_name THEN
                cmp$determine_element_type (current_p^.pid, element, status);
              ELSE
                same_as_p := cmv$command_descriptor_p;

              /same_as_loop_ca/
                WHILE same_as_p <> NIL DO
                  IF same_as_p^.element_name = current_p^.same_as THEN
                    cmp$determine_element_type (same_as_p^.pid, element, status);
                    EXIT /same_as_loop_ca/;
                  ELSE
                    same_as_p := same_as_p^.next_descriptor;
                  IFEND;
                WHILEND /same_as_loop_ca/;
              IFEND;
              IF NOT status.normal THEN
                status.normal := TRUE;
                IF current_p^.connection = cmc$iou_connection THEN
                  IF current_p^.iou_list <> NIL THEN
                    element.element_type := cmc$channel_adapter_element;
                  IFEND;
                IFEND;
              IFEND;
              IF element.element_type = cmc$channel_adapter_element THEN
                cmp$display_descriptor (current_p, file_id, status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;
                display_once := TRUE;
              IFEND;
              current_p := current_p^.next_descriptor;
            WHILEND;

          = cmc$lcu_do_communications =
            WHILE current_p <> NIL DO
              IF current_p^.pid <> osc$null_name THEN
                cmp$determine_element_type (current_p^.pid, element, status);
              ELSE
                same_as_p := cmv$command_descriptor_p;

              /same_as_loop_comm/
                WHILE same_as_p <> NIL DO
                  IF same_as_p^.element_name = current_p^.same_as THEN
                    cmp$determine_element_type (same_as_p^.pid, element, status);
                    EXIT /same_as_loop_comm/;
                  ELSE
                    same_as_p := same_as_p^.next_descriptor;
                  IFEND;
                WHILEND /same_as_loop_comm/;
              IFEND;
              IF NOT status.normal THEN
                status.normal := TRUE;
                IF current_p^.connection = cmc$iou_connection THEN
                  IF current_p^.iou_list <> NIL THEN
                    element.element_type := cmc$communications_element;
                  IFEND;
                IFEND;
              IFEND;
              IF element.element_type = cmc$communications_element THEN
                cmp$display_descriptor (current_p, file_id, status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;
                display_once := TRUE;
              IFEND;
              current_p := current_p^.next_descriptor;
            WHILEND;

          = cmc$lcu_do_storage_device =
            WHILE current_p <> NIL DO
              IF current_p^.pid <> osc$null_name THEN
                cmp$determine_element_type (current_p^.pid, element, status);
              ELSE
                same_as_p := cmv$command_descriptor_p;

              /same_as_loop_2/
                WHILE same_as_p <> NIL DO
                  IF same_as_p^.element_name = current_p^.same_as THEN
                    cmp$determine_element_type (same_as_p^.pid, element, status);
                    EXIT /same_as_loop_2/;
                  ELSE
                    same_as_p := same_as_p^.next_descriptor;
                  IFEND;
                WHILEND /same_as_loop_2/;
              IFEND;
              IF NOT status.normal THEN
                status.normal := TRUE;
                IF current_p^.connection = cmc$peripheral_connection THEN
                  element.element_type := cmc$storage_device_element;
                IFEND;
              IFEND;
              IF element.element_type = cmc$storage_device_element THEN
                cmp$display_descriptor (current_p, file_id, status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;
                display_once := TRUE;
              IFEND;
              current_p := current_p^.next_descriptor;
            WHILEND;

          = cmc$lcu_do_external_processor =
            WHILE current_p <> NIL DO
              IF current_p^.pid <> osc$null_name THEN
                cmp$determine_element_type (current_p^.pid, element, status);
              ELSE
                same_as_p := cmv$command_descriptor_p;

              /same_as_loop_3/
                WHILE same_as_p <> NIL DO
                  IF same_as_p^.element_name = current_p^.same_as THEN
                    cmp$determine_element_type (same_as_p^.pid, element, status);
                    EXIT /same_as_loop_3/;
                  ELSE
                    same_as_p := same_as_p^.next_descriptor;
                  IFEND;
                WHILEND /same_as_loop_3/;
              IFEND;
              IF NOT status.normal THEN
                status.normal := TRUE;
                IF current_p^.connection = cmc$central_memory_connection THEN
                  element.element_type := cmc$external_processor_element;
                IFEND;
              IFEND;
              IF element.element_type = cmc$external_processor_element THEN
                cmp$display_descriptor (current_p, file_id, status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;
                display_once := TRUE;
              IFEND;
              current_p := current_p^.next_descriptor;
            WHILEND;

          CASEND;
        ELSE

{ display by name

        /loop/
          WHILE current_p <> NIL DO
            IF current_p^.element_name = name THEN
              found := TRUE;
              cmp$display_descriptor (current_p, file_id, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;
              display_once := TRUE;
              EXIT /loop/;
            IFEND;
            current_p := current_p^.next_descriptor;
          WHILEND /loop/;
          IF NOT found THEN
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, name,
                  status);
            EXIT /main_program/;
          IFEND;
        IFEND;
        IF NOT display_once THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found,
                ' Element type specified ', status);
          EXIT /main_program/;
        IFEND;

      ELSE
        osp$set_status_condition ( cme$pcu_empty_file,  status);
      IFEND;

    END /main_program/;

  PROCEND cmp$display_elements_def;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$find_state_element', EJECT ??

{ PURPOSE:
{     This procedure returns the state information of an element.
{     This is primarely used in case one specify same_as on
{     DEFINE_ELEMENT.

  PROCEDURE [XDCL, #GATE] cmp$find_state_element
    (    element_name: cmt$element_name;
         iou_name: cmt$element_name;
         fid: amt$file_identifier;
     VAR element: ^cmt$state_information;
     VAR status: ost$status);

    VAR
      eoi_addr: array [1 .. 1] of amt$access_info,
      found: boolean,
      loop_count,
      loop_index: integer,
      seg: amt$segment_pointer;

    status.normal := TRUE;

  /main_program/
    BEGIN

      eoi_addr [1].key := amc$eoi_byte_address;
      amp$get_segment_pointer (fid, amc$sequence_pointer, seg, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      amp$fetch_access_information (fid, eoi_addr, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      IF NOT eoi_addr [1].item_returned THEN
        osp$set_status_condition ( cme$lcm_incompatible_lc,  status);
        EXIT /main_program/;
      IFEND;

      loop_count := eoi_addr [1].eoi_byte_address DIV #SIZE (cmt$state_information);
      RESET seg.sequence_pointer;
      found := FALSE;
      FOR loop_index := 1 TO loop_count DO
        NEXT element IN seg.sequence_pointer;
        IF element^.element_name = element_name THEN
          IF element^.element_type = cmc$data_channel_element THEN
            found := iou_name = element^.iou;
          ELSE
            found := TRUE;
          IFEND;
          IF found THEN
            EXIT /main_program/;
          IFEND;
        IFEND;
        IF element^.element_type <> cmc$data_channel_element THEN
          IF element^.application_info_size <> 0 THEN
            NEXT element^.application_info_p: [element^.application_info_size]
                  IN seg.sequence_pointer;
          IFEND;
          IF element^.site_info_size <> 0 THEN
            NEXT element^.site_info_p: [element^.site_info_size]
                  IN seg.sequence_pointer;
          IFEND;
        IFEND;
      FOREND;

      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, element_name,
            status);

    END /main_program/;

  PROCEND cmp$find_state_element;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$free_descriptor', EJECT ??

{ PURPOSE:
{     This procedure frees a command descriptor connection list
{     pointer, allocated in Task private.

  PROCEDURE cmp$free_descriptor
    (VAR command: cmt$pcu_command_descriptor);

    IF command.application_info_p <> NIL THEN
      FREE command.application_info_p IN osv$task_private_heap^;
    IFEND;
    IF command.site_info_p <> NIL THEN
      FREE command.site_info_p IN osv$task_private_heap^;
    IFEND;
    CASE command.connection OF
    = cmc$central_memory_connection =
      IF command.cmc_list <> NIL THEN
        FREE command.cmc_list IN osv$task_private_heap^;
      IFEND;
      IF command.channel_list <> NIL THEN
        FREE command.channel_list IN osv$task_private_heap^;
      IFEND;
    = cmc$iou_connection =
      IF command.iou_list <> NIL THEN
        FREE command.iou_list IN osv$task_private_heap^;
      IFEND;
    = cmc$peripheral_connection =
      IF command.pc_list <> NIL THEN
        FREE command.pc_list IN osv$task_private_heap^;
      IFEND;
    ELSE
      ;
    CASEND;

  PROCEND cmp$free_descriptor;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$get_product_id', EJECT ??

{ PURPOSE:
{   This procedure converts the product id into
{   the CYBIL type cmt$product_identification.

  PROCEDURE cmp$get_product_id
    (VAR product_id: ost$name;
     VAR element: cmt$element_definition;
     VAR status: ost$status);

    VAR
      del: integer;

    status.normal := TRUE;

    IF product_id (1, 1) <> '$' THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_element_id,
            element.element_name, status);
      osp$append_status_parameter (osc$status_parameter_delimiter,
            ' the ELEMENT_IDENTIFICATION must begin with a ''$''', status);
      RETURN;
    IFEND;

  /loop1/
    FOR del := 2 TO 8 DO
      IF product_id (del, 1) = '_' THEN
        EXIT /loop1/;
      IFEND;
    FOREND /loop1/;

    IF del = 8 THEN
      {
      { An underscore was not found in the specified element_identification.
      {
      IF product_id = '  $887' THEN
        element.product_id.product_number := '     ';
        element.product_id.product_number := product_id (1, 6);
        element.product_id.underscore := '_';
        element.product_id.model_number := '1   ';
      ELSE
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_element_id,
              element.element_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              ' an underscore ''_'', must separate the product number and the model number.', status);
      IFEND;
      RETURN;
    IFEND;

    element.product_id.product_number := '     ';
    element.product_id.product_number ((8 - del), (del - 1)) := product_id (1, del - 1);
    element.product_id.underscore := '_';

    IF (product_id (del + 1, 3) = 'xxx') OR (product_id (del + 1, 3) = 'XXX') THEN
      IF (element.product_id.product_number = ' $2620') OR (element.product_id.product_number = ' $2621') THEN
        product_id (del + 1, 3) := '210';
      ELSEIF (element.product_id.product_number = '  $836') THEN
        product_id (del + 1, 3) := '110';
      IFEND;
    ELSEIF (product_id (del + 2, 1) = 'x') OR (product_id (del + 2, 1) = 'X') THEN
      IF (element.product_id.product_number = '  $698') OR (element.product_id.product_number = ' $5698') OR
            (element.product_id.product_number = '$65354') THEN
        product_id (del + 2, 1) := '0';
      ELSEIF (element.product_id.product_number = ' $7155') OR
            (element.product_id.product_number = ' $7165') OR
            (element.product_id.product_number = ' $7021') OR
            (element.product_id.product_number = '  $844') OR
            (element.product_id.product_number = '  $885') THEN
        product_id (del + 2, 1) := '1';
      ELSEIF (element.product_id.product_number = ' $5682') THEN
        product_id (del + 2, 1) := '2';
      IFEND;
    ELSEIF (product_id (del + 1, 1) = 'x') OR (product_id (del + 1, 1) = 'X') THEN
      IF (element.product_id.product_number = ' $9853') OR (element.product_id.product_number = ' $2629') THEN
        product_id (del + 1, 1) := '1';
      ELSEIF (element.product_id.product_number = '  $679') THEN
        product_id (del + 1, 1) := '7';
      IFEND;
    IFEND;

    element.product_id.model_number := product_id (del + 1, 3);

  PROCEND cmp$get_product_id;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$get_serial_number', EJECT ??

{ PURPOSE:
{    This procedure converts the serial number
{    and saves it in the definition of the element.

  PROCEDURE cmp$get_serial_number
    (    serial_number: clt$integer;
     VAR element: cmt$element_definition;
     VAR status: ost$status);

    VAR
      str: ost$string;

    status.normal := TRUE;

    clp$convert_integer_to_string (serial_number.value, 10, FALSE, str, status);
    IF status.normal THEN
      IF str.size > STRLENGTH (element.serial_number) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_value_out_of_range,
              'SERIAL_NUMBER is too large', status);
      ELSE
        cmp$check_for_unique_ser_num (str, element.product_id, cmv$cmd_value_fid, status);
        IF status.normal THEN
          element.serial_number := str.value;
        IFEND;
      IFEND;
    IFEND;

  PROCEND cmp$get_serial_number;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$increment_pcu_error_count', EJECT ??

{ PURPOSE:
{    This procedure increments the count of errors encountered
{    while processing the PCU define_element subcommands.

  PROCEDURE [XDCL, #GATE] cmp$increment_pcu_error_count;

    cmv$pcu_error_count := cmv$pcu_error_count + 1;

  PROCEND cmp$increment_pcu_error_count;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$open_utility_files', EJECT ??

{ PURPOSE:
{   This procedure opens the global files used to store definition
{   of peripheral elements and their state information.

  PROCEDURE [XDCL, #GATE] cmp$open_utility_files
    (VAR status: ost$status);

    VAR
      local_file,
      existing_file,
      contains_data: boolean,
      local_status: ost$status,
      output_file,
      input_file: amt$local_file_name,
      input_fid,
      output_fid: amt$file_identifier,
      byte_address: amt$file_byte_address,
      unique_name: ost$unique_name,
      get_attr: array [1 .. 1] of amt$get_item,
      file_attr: array [1 .. 1] of amt$access_selection;

    status.normal := TRUE;

  /main_program/
    BEGIN

      file_attr [1].key := amc$access_mode;
      file_attr [1].access_mode := $pft$usage_selections [pfc$shorten, pfc$read, pfc$modify, pfc$append,
            pfc$execute];


      get_attr [1].key := amc$null_attribute;
      REPEAT

        pmp$generate_unique_name (unique_name, status);

        IF NOT status.normal THEN
          EXIT /main_program/;
        IFEND;
        amp$get_file_attributes (unique_name.value, get_attr, local_file, existing_file, contains_data,
              status);
        IF NOT status.normal THEN
          EXIT /main_program/;
        IFEND;

      UNTIL NOT local_file;

      cmv$cmd_value_name := unique_name.value;
      amp$open (cmv$cmd_value_name, amc$segment, ^file_attr, cmv$cmd_value_fid, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      REPEAT

        pmp$generate_unique_name (unique_name, status);

        IF NOT status.normal THEN
          EXIT /main_program/;
        IFEND;
        amp$get_file_attributes (unique_name.value, get_attr, local_file, existing_file, contains_data,
              status);
        IF NOT status.normal THEN
          EXIT /main_program/;
        IFEND;

      UNTIL NOT local_file;

      cmv$state_value_name := unique_name.value;

      amp$open (cmv$state_value_name, amc$segment, ^file_attr, cmv$state_value_fid, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

    END /main_program/;


  PROCEND cmp$open_utility_files;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$process_define_element', EJECT ??

{ PURPOSE:
{     This procedure processes the parameter list of the PCU
{     subcommands DEFINE_ELEMENT and builds the data structures
{     needed to verify and/or activate the configuration.
{ NOTE:
{     This routine is called only when subcommands are being
{     processed via INSTALL_PHYSICAL_CONFIGURATION or
{     VERIFY_PHYSICAL_CONFIGURATION command.

  PROCEDURE [XDCL, #GATE] cmp$process_define_element
    (    parameter_value_table: ^clt$parameter_value_table;
     VAR status: ost$status);

    CONST
      command_name = 'DEFINE_ELEMENT';

    VAR
      map_state: [STATIC, READ, oss$job_paged_literal] array [cmt$element_state] of string (4) := ['ON  ',
            'OFF ', 'DOWN'];

    TYPE
      channel_definition = packed record
        configured: boolean,
        descriptor: cmt$element_definition,
      recend;

    VAR
      alternate_driver_name: dst$driver_name,
      channel_def: cmt$data_channel_definition,
      channel_descriptor: cmt$channel_descriptor,
      channel_element_p: ^array [ * ] of channel_definition,
      channel_name: cmt$element_name,
      connection_number: integer,
      connection_specified: boolean,
      comm_port_number: cmt$communications_port_number,
      ct_port_number: cmt$controller_port_number,
      controller_type: cmt$controller_type,
      current_list_entry: ^clt$data_value,
      definition_p: ^cmt$element_definition,
      driver_name: dst$driver_name,
      element_is_a_unit: boolean,
      equipment_number: cmt$physical_equipment_number,
      element: cmt$element_definition,
      element_name: cmt$element_name,
      field_index: integer,
      found: boolean,
      i: integer,
      io_unit_type: iot$unit_type,
      iou_name: cmt$element_name,
      iou_number: dst$iou_number,
      local_status: ost$status,
      list_index: integer,
      mainframe_name: cmt$element_name,
      p_unit_number: cmt$physical_unit_number,
      pen: cmt$physical_equipment_number,
      peripheral_element: cmt$element_name,
      physical_address: cmt$physical_unit_number,
      port: 0 .. 3,
      port_number: cmt$controller_port_number,
      pp_module_name: pmt$program_name,
      same_as: boolean,
      same_element_p: ^cmt$element_definition,
      same_state_element_p: ^cmt$state_information,
      segment_pointer: amt$segment_pointer,
      specified_address: boolean,
      standard_product: boolean,
      state: cmt$element_state,
      state_element_p: ^cmt$state_information,
      state_index: cmt$element_state,
      state_value: ost$name,
      state_segment_pointer: amt$segment_pointer,
      unit_type: cmt$unit_type,
      unit_class: cmt$unit_class,
      valid_ipn: boolean;

    status.normal := TRUE;
    channel_element_p := NIL;
    element_name := parameter_value_table^ [p$element].value^.name_value;

    cmp$check_reserved_names (element_name, cmv$reserved_names_list, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    cmp$check_for_unique_element (element_name, osc$null_name, cmv$cmd_value_fid, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    same_as := parameter_value_table^ [p$same_as].specified;
    IF same_as THEN
      cmp$find_element (parameter_value_table^ [p$same_as].value^.name_value, {unused} iou_name,
            osc$null_name, cmv$cmd_value_fid, same_element_p, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      element := same_element_p^;
      cmp$find_state_element (parameter_value_table^ [p$same_as].value^.name_value, {unused} iou_name,
            cmv$state_value_fid, same_state_element_p, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    element.element_name := element_name;
    standard_product := parameter_value_table^ [p$verify_element_identification].value^.boolean_value.value;

    IF NOT parameter_value_table^ [p$element_identification].specified THEN
      IF NOT same_as THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters,
              'ELEMENT_IDENTIFICATION', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
        RETURN;
      IFEND;
    ELSE
      cmp$get_product_id (parameter_value_table^ [p$element_identification].value^.name_value, element,
            status);
      IF NOT status.normal THEN
        IF NOT standard_product THEN
          RETURN;
        ELSE
          status.normal := TRUE;
        IFEND;
      IFEND;
    IFEND;

{ Determine the need to check for unique serial number
{ based on product_id and also  determine element type.

    IF standard_product THEN
      IF NOT cmp$known_controller_id (element.product_id) AND NOT cmp$known_product_id
            (element.product_id) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_unknown_product_id,
              parameter_value_table^ [p$element_identification].value^.name_value, status);
        RETURN;
      IFEND;
      IF cmp$known_controller_id (element.product_id) THEN
        cmp$get_controller_type (element.product_id, controller_type, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        CASE controller_type OF
        = cmc$ms7154_x .. cmc$mscm3_ct, cmc$mt7021_3x, cmc$mt698_xx, cmc$mt5698_xx, cmc$mt7021_4x,
              cmc$ms5831_x, cmc$msntdc_1, cmc$msntdc_2, cmc$mt5680_xx, cmc$mt7221_1, cmc$mt7221_2_s0,
              cmc$ms7255_1_1, cmc$ms7255_1_2 =
          element.element_type := cmc$controller_element;
        = cmc$mp65354_11 =
          element.element_type := cmc$external_processor_element;
        = cmc$ca2629_2 =
          element.element_type := cmc$channel_adapter_element;
        = cmc$lcn380_170, cmc$mti2620_21x, cmc$mdi2621_21x, cmc$fs740_200, cmc$expresslink =
          element.element_type := cmc$communications_element;
        ELSE
        CASEND;
      ELSE
        IF cmp$known_product_id (element.product_id) THEN
          element.element_type := cmc$storage_device_element;
        IFEND;
      IFEND;
    ELSE
      IF cmp$known_controller_id (element.product_id) OR cmp$known_product_id (element.product_id) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
              'Invalid usage of VERIFY_ELEMENT_IDENTIFICATION parameter', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
        RETURN;
      IFEND;
      element.element_type := cmc$storage_device_element;
    IFEND;

    IF NOT parameter_value_table^ [p$serial_number].specified THEN
      IF NOT same_as THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters, 'SERIAL_NUMBER',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
        RETURN;
      IFEND;
    ELSE
      cmp$get_serial_number (parameter_value_table^ [p$serial_number].value^.integer_value, element, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

{ Initialize all connections field.

    CASE element.element_type OF
    = cmc$storage_device_element =
      FOR port_number := LOWERVALUE (cmt$controller_port_number) TO UPPERVALUE (cmt$controller_port_number) DO
        element.storage_device.connection.port [port_number].configured := FALSE;
      FOREND;
    = cmc$controller_element =
      FOR ct_port_number := LOWERVALUE (ct_port_number) TO UPPERVALUE (ct_port_number) DO
        element.controller.connection.port [ct_port_number].configured := FALSE;
      FOREND;
      FOR p_unit_number := LOWERVALUE (p_unit_number) TO UPPERVALUE (p_unit_number) DO
        element.controller.connection.unit [p_unit_number].configured := FALSE;
      FOREND;
    = cmc$external_processor_element =
      FOR pen := LOWERVALUE (cmt$physical_equipment_number) TO UPPERVALUE (cmt$physical_equipment_number) DO
        element.external_processor.connection.io_port [pen].configured := FALSE;
      FOREND;

    = cmc$channel_adapter_element =

{ Channel adapters only have 1 upline connection

      element.channel_adapter.connection.channel.configured := FALSE;
      FOR pen := LOWERVALUE (cmt$physical_equipment_number) TO UPPERVALUE (cmt$physical_equipment_number) DO
        element.channel_adapter.connection.equipment [pen].configured := FALSE;
      FOREND;
    = cmc$communications_element =
      FOR comm_port_number := LOWERVALUE (comm_port_number) TO UPPERVALUE (comm_port_number) DO
        element.communications_element.connection.port [comm_port_number].configured := FALSE;
      FOREND;
    ELSE
    CASEND;

{ Process PERIPHERAL_CONNECTIONS list.

    connection_specified := FALSE;
    connection_number := 0;
    specified_address := FALSE;
    IF parameter_value_table^ [p$peripheral_connection].specified THEN
      element_is_a_unit := TRUE;
      connection_specified := TRUE;
      current_list_entry := parameter_value_table^ [p$peripheral_connection].value;
      IF element.element_type <> cmc$storage_device_element THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
              'Invalid peripheral connection', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
        RETURN;
      IFEND;
      element.storage_device.physical_unit_number := 0;
      physical_address := 0;
      WHILE current_list_entry <> NIL DO
        FOR field_index := LOWERBOUND (current_list_entry^.element_value^.field_values^)
              TO UPPERBOUND (current_list_entry^.element_value^.field_values^) DO

          IF (current_list_entry^.element_value^.field_values^ [field_index].name = 'PERIPHERAL_ELEMENT') THEN
            IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
              cmp$check_reserved_names (current_list_entry^.element_value^.field_values^ [field_index].value^.
                    name_value, cmv$reserved_names_list, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;
              peripheral_element := current_list_entry^.element_value^.field_values^ [field_index].value^.
                    name_value;
            IFEND;
          ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name =
                'PHYSICAL_ADDRESS') THEN
            IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
              IF NOT specified_address THEN
                specified_address := TRUE;
                physical_address := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      integer_value.value;
              ELSE
                IF physical_address <> current_list_entry^.element_value^.field_values^ [field_index].value^.
                      integer_value.value THEN
                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                        'Physical address mismatch on PERIPHERAL CONNECTIONS', status);
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        parameter_value_table^ [p$element].value^.name_value, status);
                  RETURN;
                IFEND;
              IFEND;
            IFEND;
          IFEND;
        FOREND;
        element.storage_device.connection.port [connection_number].configured := TRUE;
        element.storage_device.connection.port [connection_number].element_name := peripheral_element;
        element.storage_device.physical_unit_number := physical_address;
        cmp$get_unit_type (element.product_id, unit_type, io_unit_type, unit_class, found);
        IF (unit_type = cmc$msfsd2_s0) OR (unit_type = cmc$msxmd_3) THEN
          IF clp$count_list_elements (parameter_value_table^ [p$peripheral_connection].value) > 2 THEN
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                  'Too many peripheral connections specified', status);
            osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
            RETURN;
          IFEND;
        IFEND;
        cmp$validate_address_range (unit_type, physical_address, status);
        IF NOT status.normal THEN
          osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
          RETURN;
        IFEND;
        IF unit_type = cmc$mshydra THEN
          element.storage_device.connection.port [connection_number].upline_connection_type :=
                cmc$data_channel_element;
        ELSE
          element.storage_device.connection.port [connection_number].upline_connection_type :=
                cmc$controller_element;
        IFEND;
        connection_number := connection_number + 1;
        current_list_entry := current_list_entry^.link;
        IF (current_list_entry <> NIL) AND (connection_number > UPPERVALUE (cmt$data_storage_port_number))
              THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                'Too many values given on PERIPHERAL_CONNECTIONS', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
          RETURN;
        IFEND;
      WHILEND;
    IFEND;

{ Process IOU_CONNECTIONS List.

    IF parameter_value_table^ [p$iou_connection].specified THEN
      connection_specified := TRUE;
      connection_number := 0;
      IF NOT standard_product THEN
        element.element_type := cmc$controller_element;
        FOR ct_port_number := LOWERVALUE (ct_port_number) TO UPPERVALUE (ct_port_number) DO
          element.controller.connection.port [ct_port_number].configured := FALSE;
        FOREND;
        FOR p_unit_number := LOWERVALUE (p_unit_number) TO UPPERVALUE (p_unit_number) DO
          element.controller.connection.unit [p_unit_number].configured := FALSE;
        FOREND;
      IFEND;
      IF clp$count_list_elements (parameter_value_table^ [p$iou_connection].value) > 0 THEN
        PUSH channel_element_p: [1 .. clp$count_list_elements
              (parameter_value_table^ [p$iou_connection].value)];

        current_list_entry := parameter_value_table^ [p$iou_connection].value;
        list_index := 0;
        specified_address := FALSE;
        equipment_number := 0;
        WHILE current_list_entry <> NIL DO
          mainframe_name := cmv$mainframe_name;
          iou_name := 'IOU0';
          list_index := list_index + 1;
          FOR pen := LOWERVALUE (cmt$physical_equipment_number)
                TO UPPERVALUE (cmt$physical_equipment_number) DO
            channel_element_p^ [list_index].descriptor.data_channel.connection.equipment [pen].configured :=
                  FALSE;
          FOREND;
          FOR field_index := LOWERBOUND (current_list_entry^.element_value^.field_values^)
                TO UPPERBOUND (current_list_entry^.element_value^.field_values^) DO

            IF (current_list_entry^.element_value^.field_values^ [field_index].name = 'CHANNEL') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                channel_name := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      name_value;
                IF NOT cmp$valid_channel_name (channel_name) THEN
                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_channel_number,
                        command_name, status);
                  osp$append_status_parameter (osc$status_parameter_delimiter, channel_name, status);
                  RETURN;
                IFEND;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name =
                  'EQUIPMENT') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                IF NOT specified_address THEN
                  equipment_number := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      integer_value.value;
                  specified_address := TRUE;
                ELSE
                  IF equipment_number <> current_list_entry^.element_value^.field_values^ [field_index]
                       .value^.integer_value.value THEN
                    osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                         'Physical address mismatch on IOU CONNECTIONS', status);
                    osp$append_status_parameter (osc$status_parameter_delimiter,
                         parameter_value_table^ [p$element].value^.name_value, status);
                    RETURN;
                  IFEND;
                IFEND;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name = 'MAINFRAME') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                mainframe_name := current_list_entry^.element_value^.field_values^ [field_index].value^.
                      name_value;
                cmp$validate_mainframe_name (mainframe_name, status);
                IF NOT status.normal THEN
                  osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
                  RETURN;
                IFEND;
              IFEND;
            ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name = 'IOU') THEN
              IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
                iou_name := current_list_entry^.element_value^.field_values^ [field_index].value^.name_value;
                cmp$convert_iou_name (iou_name, iou_number, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;
              IFEND;
            IFEND;
          FOREND;
          CASE element.element_type OF
          = cmc$controller_element =
            element.controller.connection.port [connection_number].configured := TRUE;
            element.controller.connection.port [connection_number].element_name := channel_name;
            element.controller.connection.port [connection_number].upline_connection_type :=
                  cmc$data_channel_element;
            element.controller.connection.port [connection_number].mainframe_ownership := mainframe_name;
            element.controller.connection.port [connection_number].iou := iou_name;
            element.controller.physical_equipment_number := equipment_number;
          = cmc$external_processor_element =
            element.external_processor.connection.io_port [connection_number].configured := TRUE;
            element.external_processor.connection.io_port [connection_number].element_name := channel_name;
            element.external_processor.connection.io_port [connection_number].upline_connection_type :=
                  cmc$data_channel_element;
            element.external_processor.connection.io_port [connection_number].mainframe_ownership :=
                  mainframe_name;
            element.external_processor.connection.io_port [connection_number].iou := iou_name;
            element.external_processor.connection.central_memory.memory_port := cmc$memory_port_0;
            element.external_processor.connection.central_memory.element_name := mainframe_name;
            element.external_processor.physical_equipment_number := equipment_number;
          = cmc$channel_adapter_element =
            element.channel_adapter.connection.channel.configured := TRUE;
            element.channel_adapter.connection.channel.element_name := channel_name;
            element.channel_adapter.connection.channel.upline_connection_type := cmc$data_channel_element;
            element.channel_adapter.connection.channel.mainframe_ownership := mainframe_name;
            element.channel_adapter.connection.channel.iou := iou_name;
            element.channel_adapter.physical_equipment_number := equipment_number;
          = cmc$communications_element =
            element.communications_element.connection.port [connection_number].configured := TRUE;
            element.communications_element.connection.port [connection_number].element_name := channel_name;
            element.communications_element.connection.port [connection_number].upline_connection_type :=
                  cmc$data_channel_element;
            element.communications_element.connection.port [connection_number].iou := iou_name;
            element.communications_element.connection.port [connection_number].mainframe_ownership :=
                  mainframe_name;
            element.communications_element.physical_equipment_number := equipment_number;
          = cmc$storage_device_element =
            cmp$get_unit_type (element.product_id, unit_type, io_unit_type, unit_class, found);
            IF (unit_type = cmc$mshydra) THEN
              element.storage_device.connection.port [connection_number].configured := TRUE;
              element.storage_device.connection.port [connection_number].element_name := channel_name;
              cmp$validate_address_range (unit_type, equipment_number, status);
              IF NOT status.normal THEN
                osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
                RETURN;
              IFEND;
              element.storage_device.connection.port [connection_number].configured := TRUE;
              element.storage_device.connection.port [connection_number].upline_connection_type :=
                    cmc$data_channel_element;
              element.storage_device.connection.port [connection_number].mainframe_ownership :=
                    mainframe_name;
              element.storage_device.connection.port [connection_number].iou := iou_name;
              element.storage_device.physical_unit_number := equipment_number;
            ELSE
              osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                    'Iou connection not applicable to storage device', status);
              osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
              RETURN;
            IFEND;

          ELSE { Error. }
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                  'Iou connection not applicable to storage device', status);
            osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
            RETURN;
          CASEND;

          channel_element_p^ [list_index].descriptor.element_type := cmc$data_channel_element;
          IF cmp$valid_channel_name (channel_name) THEN
            channel_element_p^ [list_index].descriptor.element_name := channel_name;
            channel_element_p^ [list_index].descriptor.product_id.product_number := '      ';
            channel_element_p^ [list_index].descriptor.product_id.underscore := ' ';
            channel_element_p^ [list_index].descriptor.product_id.model_number := '   ';
            channel_element_p^ [list_index].descriptor.serial_number := '      ';
            channel_element_p^ [list_index].descriptor.data_channel.iou := iou_name;
            channel_element_p^ [list_index].descriptor.data_channel.connection.equipment [equipment_number].
                  configured := TRUE;
            channel_element_p^ [list_index].descriptor.data_channel.connection.equipment [equipment_number].
                  element_name := element_name;
          ELSE
            osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_channel_number,
                  'DEFINE_ELEMENT', status);
            osp$append_status_parameter (osc$status_parameter_delimiter, channel_name, status);
            RETURN;
          IFEND;
          channel_descriptor.iou := channel_element_p^ [list_index].descriptor.data_channel.iou;
          channel_descriptor.use_logical_identification := TRUE;
          channel_descriptor.name := channel_element_p^ [list_index].descriptor.element_name;
          cmp$get_channel_definition (channel_descriptor, channel_def, status);
          IF NOT status.normal THEN
            IF (status.condition = cme$lcm_element_not_found) OR
                  (status.condition = cme$unknown_channel_type) THEN
              status.normal := TRUE;
            ELSE
              RETURN;
            IFEND;
          IFEND;
          channel_element_p^ [list_index].descriptor.data_channel.concurrent := channel_def.concurrent;
          channel_element_p^ [list_index].descriptor.data_channel.direct_memory_access :=
                channel_def.direct_memory_access;
          channel_element_p^ [list_index].descriptor.data_channel.kind := channel_def.kind;
          channel_element_p^ [list_index].descriptor.data_channel.number := channel_def.number;
          channel_element_p^ [list_index].descriptor.data_channel.port := channel_def.port;
          channel_element_p^ [list_index].descriptor.data_channel.mainframe_ownership := mainframe_name;
          channel_element_p^ [list_index].descriptor.data_channel.pps_capable_of_access :=
                channel_def.pps_capable_of_access;
          channel_element_p^ [list_index].descriptor.data_channel.ordinal := channel_def.ordinal;
          connection_number := connection_number + 1;
          current_list_entry := current_list_entry^.link;

{ If there is more entry in the list to process, make sure we have not
{ exceeded the maximum allowable number of upline connections.

          IF current_list_entry <> NIL THEN
            CASE element.element_type OF
            = cmc$controller_element =
              IF (connection_number > UPPERVALUE (cmt$controller_port_number)) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                      'Too many values given on IOU_CONNECTIONS', status);
              IFEND;
            = cmc$external_processor_element =
              IF (connection_number > UPPERVALUE (cmt$physical_equipment_number)) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                      'Too many values given on IOU_CONNECTIONS', status);
              IFEND;
            = cmc$channel_adapter_element =
              IF (connection_number > 1) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                      'Too many values given on IOU_CONNECTIONS', status);
              IFEND;
            = cmc$communications_element =
              IF (connection_number > UPPERVALUE (cmt$communications_port_number)) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                      'Too many values given on IOU_CONNECTIONS', status);
              IFEND;
            = cmc$storage_device_element =
              IF (connection_number > UPPERVALUE (cmt$data_storage_port_number)) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                      'Too many values given on IOU_CONNECTIONS', status);
              IFEND;
            ELSE
            CASEND;
            IF NOT status.normal THEN
              osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
              RETURN;
            IFEND;
          IFEND;
        WHILEND;
      IFEND;
    IFEND;

{ Process CENTRAL_MEMORY_CONNECTION.

    IF parameter_value_table^ [p$central_memory_connection].specified THEN
      IF element.element_type <> cmc$external_processor_element THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
              'Central memory connection applicable' CAT ' to external processor element only', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
        RETURN;
      IFEND;
      connection_specified := TRUE;
      current_list_entry := parameter_value_table^ [p$central_memory_connection].value;
      mainframe_name := cmv$mainframe_name;
      port := 0;
      WHILE current_list_entry <> NIL DO
        FOR field_index := LOWERBOUND (current_list_entry^.element_value^.field_values^)
              TO UPPERBOUND (current_list_entry^.element_value^.field_values^) DO
          IF (current_list_entry^.element_value^.field_values^ [field_index].name = 'PORT') THEN
            IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
              port := current_list_entry^.element_value^.field_values^ [field_index].value^.integer_value.
                    value;
            IFEND;
          ELSEIF (current_list_entry^.element_value^.field_values^ [field_index].name = 'MAINFRAME') THEN
            IF (current_list_entry^.element_value^.field_values^ [field_index].value <> NIL) THEN
              mainframe_name := current_list_entry^.element_value^.field_values^ [field_index].value^.
                    name_value;
            IFEND;
          IFEND;
        FOREND;
        element.external_processor.connection.central_memory.upline_connection_type :=
              cmc$central_memory_element;
        element.external_processor.connection.central_memory.element_name := mainframe_name;
        IF port = 0 THEN
          element.external_processor.connection.central_memory.memory_port := cmc$memory_port_0;
        ELSEIF port = 1 THEN
          element.external_processor.connection.central_memory.memory_port := cmc$memory_port_1;
        ELSEIF port = 2 THEN
          element.external_processor.connection.central_memory.memory_port := cmc$memory_port_2;
        ELSEIF port = 3 THEN
          element.external_processor.connection.central_memory.memory_port := cmc$memory_port_3;
        ELSE
          osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                'PORT value out of range' CAT ' on CENTRAL_MEMORY_CONNECTION', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
          RETURN;
        IFEND;
        current_list_entry := current_list_entry^.link;
        IF current_list_entry <> NIL THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                'Too many values given on CENTRAL_MEMORY_CONNECTIONS', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
          RETURN;
        IFEND;
      WHILEND;
    IFEND;
    IF NOT connection_specified THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_missing_parameters, 'Connections',
            status);
      osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
      RETURN;
    IFEND;
    IF same_as THEN
      state := same_state_element_p^.status.state;
    ELSE
      state_value := parameter_value_table^ [p$state].value^.name_value;

    /state_loop/
      FOR state_index := LOWERVALUE (cmt$element_state) TO UPPERVALUE (cmt$element_state) DO
        IF state_value = map_state [state_index] THEN
          state := state_index;
          EXIT /state_loop/;
        IFEND;
      FOREND /state_loop/;
    IFEND;

{ Find the channel belonging to the current mainframe that is being
{ verified or installed and use the concurrent field to validate IOU
{ PROGRAM NAME.

    IF channel_element_p <> NIL THEN

    /search_channel/
      FOR i := LOWERBOUND (channel_element_p^) TO UPPERBOUND (channel_element_p^) DO
        IF (channel_element_p^ [i].descriptor.data_channel.mainframe_ownership = cmv$mainframe_name) THEN
          channel_def := channel_element_p^ [i].descriptor.data_channel;
          EXIT /search_channel/;
        IFEND;
      FOREND /search_channel/;
    IFEND;

{ Get and validate IOU_PROGRAM_NAME parameter

    valid_ipn := TRUE;
    IF parameter_value_table^ [p$iou_program_name].specified THEN
      IF (element.element_type = cmc$storage_device_element) AND (unit_type <> cmc$mshydra) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
              'IOU_PROGRAM_NAME cannot be specified' CAT ' on a storage device', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
        RETURN;
      IFEND;
      pp_module_name := parameter_value_table^ [p$iou_program_name].value^.name_value;
      IF standard_product THEN
        cmp$convert_iou_name (channel_def.iou, iou_number, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        cmp$get_driver_by_controller (controller_type, channel_def.concurrent, iou_number, driver_name,
              alternate_driver_name);
        IF (pp_module_name <> driver_name) AND (pp_module_name <> alternate_driver_name) THEN
          valid_ipn := FALSE;
        IFEND;
      IFEND;
    ELSE
      IF same_as THEN
        CASE same_element_p^.element_type OF
        = cmc$controller_element =
          pp_module_name := same_element_p^.controller.peripheral_driver_name;
        = cmc$external_processor_element =
          pp_module_name := same_element_p^.external_processor.peripheral_driver_name;
        = cmc$channel_adapter_element =
          pp_module_name := same_element_p^.channel_adapter.peripheral_driver_name;
        = cmc$communications_element =
          pp_module_name := same_element_p^.communications_element.peripheral_driver_name;
        ELSE
          ;
        CASEND;
        IF standard_product AND (same_element_p^.element_type <> cmc$storage_device_element) THEN
          cmp$convert_iou_name (channel_def.iou, iou_number, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          cmp$get_driver_by_controller (controller_type, channel_def.concurrent, iou_number, driver_name,
                alternate_driver_name);
          IF (pp_module_name <> driver_name) AND (pp_module_name <> alternate_driver_name) THEN
            valid_ipn := FALSE;
          IFEND;
        IFEND

      ELSE

{ Get the default driver name based on product and channel types.

        IF standard_product THEN
          IF (element.element_type <> cmc$storage_device_element) THEN
            cmp$convert_iou_name (channel_def.iou, iou_number, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
            cmp$get_driver_by_controller (controller_type, channel_def.concurrent, iou_number, driver_name,
                  alternate_driver_name);
            pp_module_name := driver_name;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF NOT valid_ipn THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
            'Invalid IOU_PROGRAM_NAME specified', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, element_name, status);
      RETURN;
    IFEND;

    CASE element.element_type OF
    = cmc$controller_element =
      element.controller.peripheral_driver_name := pp_module_name;
    = cmc$external_processor_element =
      element.external_processor.peripheral_driver_name := pp_module_name;

    = cmc$channel_adapter_element =
      element.channel_adapter.peripheral_driver_name := pp_module_name;

    = cmc$communications_element =
      element.communications_element.peripheral_driver_name := pp_module_name;

    ELSE
      ;
    CASEND;

    {
    {Initialize unused/non-initialized fields.
    {
    CASE element.element_type OF
    = cmc$controller_element =
      element.controller.microcode_identification.number := '    ';
      element.controller.microcode_identification.dollar := ' ';
      element.controller.microcode_identification.type_identifier := ' ';
      element.controller.microcode_identification.series_code := ' ';
      element.controller.response_handler_name := osc$null_name;

    = cmc$communications_element =
      element.communications_element.microcode_identification.number := '    ';
      element.communications_element.microcode_identification.dollar := ' ';
      element.communications_element.microcode_identification.type_identifier := ' ';
      element.communications_element.microcode_identification.series_code := ' ';

    ELSE
    CASEND;


{ Put definition of element as well as state information into the segment
{ access files

    IF channel_element_p <> NIL THEN
      FOR i := LOWERBOUND (channel_element_p^) TO UPPERBOUND (channel_element_p^) DO
        cmp$find_element (channel_element_p^ [i].descriptor.element_name,
              channel_element_p^ [i].descriptor.data_channel.iou,
              channel_element_p^ [i].descriptor.data_channel.mainframe_ownership, cmv$cmd_value_fid,
              same_element_p, local_status);
        IF NOT local_status.normal THEN

{ This channel is not present in the file.

          channel_element_p^ [i].configured := TRUE;
        ELSE
          channel_element_p^ [i].configured := FALSE;
        IFEND;
      FOREND;
    IFEND;

    IF channel_element_p <> NIL THEN
      FOR i := LOWERBOUND (channel_element_p^) TO UPPERBOUND (channel_element_p^) DO
        IF channel_element_p^ [i].configured THEN
          amp$get_segment_pointer (cmv$cmd_value_fid, amc$sequence_pointer, segment_pointer, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          NEXT definition_p IN segment_pointer.sequence_pointer;

          amp$get_segment_pointer (cmv$state_value_fid, amc$sequence_pointer, state_segment_pointer, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          NEXT state_element_p IN state_segment_pointer.sequence_pointer;

          definition_p^ := channel_element_p^ [i].descriptor;
          state_element_p^.status.state := cmc$on;
          state_element_p^.element_name := channel_element_p^ [i].descriptor.element_name;
          state_element_p^.element_type := cmc$data_channel_element;
          state_element_p^.iou := channel_element_p^ [i].descriptor.data_channel.iou;
          amp$set_segment_eoi (cmv$cmd_value_fid, segment_pointer, local_status);
          amp$set_segment_eoi (cmv$state_value_fid, state_segment_pointer, local_status);
        IFEND;
      FOREND;
    IFEND;

    amp$get_segment_pointer (cmv$cmd_value_fid, amc$sequence_pointer, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    NEXT definition_p IN segment_pointer.sequence_pointer;

    amp$get_segment_pointer (cmv$state_value_fid, amc$sequence_pointer, state_segment_pointer, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    NEXT state_element_p IN state_segment_pointer.sequence_pointer;

    definition_p^ := element;
    IF NOT same_as THEN
      state_element_p^.status.state := state;
      state_element_p^.element_name := element.element_name;
      state_element_p^.element_type := element.element_type;
      state_element_p^.logical_unit := 0;
      state_element_p^.product_id := element.product_id;
      IF element.element_type <> cmc$data_channel_element THEN
        IF parameter_value_table^ [p$application_information].specified THEN
          NEXT state_element_p^.application_info_p:
             [STRLENGTH(parameter_value_table^[p$application_information].value^.
                string_value^)] IN state_segment_pointer.sequence_pointer;
          state_element_p^.application_info_p^ := parameter_value_table^ [p$application_information].
              value^.string_value^;
          state_element_p^.application_info_size := STRLENGTH(parameter_value_table^
              [p$application_information].value^.string_value^);
        ELSE
          state_element_p^.application_info_p := NIL;
          state_element_p^.application_info_size := 0;
        IFEND;
        IF parameter_value_table^ [p$site_information].specified THEN
          NEXT state_element_p^.site_info_p:
             [STRLENGTH(parameter_value_table^[p$site_information].value^.
                string_value^)] IN state_segment_pointer.sequence_pointer;
          state_element_p^.site_info_p^ := parameter_value_table^ [p$site_information].
              value^.string_value^;
          state_element_p^.site_info_size := STRLENGTH(parameter_value_table^
              [p$site_information].value^.string_value^);
        ELSE
          state_element_p^.site_info_p := NIL;
          state_element_p^.site_info_size := 0;
        IFEND;
      IFEND;
    ELSE
      state_element_p^ := same_state_element_p^;
      state_element_p^.element_name := element_name;
    IFEND;
    amp$set_segment_eoi (cmv$cmd_value_fid, segment_pointer, local_status);
    amp$set_segment_eoi (cmv$state_value_fid, state_segment_pointer, local_status);

  PROCEND cmp$process_define_element;


?? OLDTITLE ??
?? NEWTITLE := '   cpm$replace_definition', EJECT ??

{ PURPOSE:
{    This procedure searches for an element name in a
{    configuration file and replace its definition


  PROCEDURE [XDCL, #GATE] cmp$replace_definition
    (    element_name: cmt$element_name;
         new_descriptor: cmt$pcu_command_descriptor;
     VAR status: ost$status);

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      found: boolean,
      save_p: ^cmt$pcu_command_descriptor;


    status.normal := TRUE;

  /main_program/
    BEGIN
      IF cmv$command_descriptor_p <> NIL THEN
        current_p := cmv$command_descriptor_p;
        found := FALSE;

      /link_list_loop/
        WHILE current_p <> NIL DO
          found := current_p^.element_name = element_name;
          IF found THEN
            save_p := current_p^.next_descriptor;
            cmp$free_descriptor (current_p^);
            current_p^ := new_descriptor;
            current_p^.next_descriptor := save_p;
            EXIT /link_list_loop/;
          ELSE
            current_p := current_p^.next_descriptor;
          IFEND;

        WHILEND /link_list_loop/;
      ELSE
        osp$set_status_condition ( cme$pcu_empty_file,  status);
        EXIT /main_program/;
      IFEND;

      IF NOT found THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_element_not_found, element_name,
              status);
      IFEND;

    END /main_program/;


  PROCEND cmp$replace_definition;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$search_edited_file', EJECT ??

{  PURPOSE:
{    This procedure search a token in the physical configuration
{    file. Two types of token are searched :
{     * Integer ( Serial number of an element )
{     * Name  ( Name of an element )
{    If found is TRUE then the element name or the serial number
{    is already being used.


  PROCEDURE [XDCL, #GATE] cmp$search_edited_file
    (    element_name: cmt$element_name;
         serial_number: integer;
         product_id: cmt$product_identification;
     VAR found: boolean;
     VAR descriptor: cmt$pcu_command_descriptor);

    VAR
      j,
      i: integer,
      pid: ost$name,
      found_count,
      check_count: integer,
      current_p: ^cmt$pcu_command_descriptor;

    found := FALSE;
    IF product_id.product_number = '  $885' THEN
      check_count := 2;
    ELSEIF product_id.product_number = ' $895' THEN
      check_count := 4;
    ELSE
      check_count := 0;
    IFEND;
    found_count := 0;
    pid := osc$null_name;
    j := 0;
    FOR i := 1 TO 6 DO
      IF product_id.product_number (i, 1) <> ' ' THEN
        j := j + 1;
        pid (j, 1) := product_id.product_number (i, 1);
      IFEND;
    FOREND;
    j := j + 1;
    pid (j, 1) := product_id.underscore;
    pid (j + 1, 3) := product_id.model_number;
    IF cmv$command_descriptor_p <> NIL THEN
      current_p := cmv$command_descriptor_p;

    /search/
      WHILE current_p <> NIL DO
        IF serial_number <> 0 THEN
          IF (serial_number = current_p^.sn) AND (pid = current_p^.pid) THEN
            found_count := found_count + 1;
            IF found_count > check_count THEN
              found := TRUE;
            IFEND;

          IFEND;
        ELSE
          IF current_p^.element_name = element_name THEN
            found := TRUE;
          IFEND;
        IFEND;

        IF found THEN
          descriptor := current_p^;
          EXIT /search/; {----->
        ELSE
          current_p := current_p^.next_descriptor;
        IFEND;

      WHILEND /search/;
    IFEND;
  PROCEND cmp$search_edited_file;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$save_output', EJECT ??

{ PURPOSE:
{     This procedure opens the output file specified on
{     EDIPC command.

  PROCEDURE [XDCL, #GATE] cmp$save_output
    (    output_file: amt$local_file_name;
         input_file: boolean;
     VAR status: ost$status);


    VAR
      attribute_override: array [1 .. 1] of fst$file_cycle_attribute,
      attribute_validation: array [1 .. 2] of fst$file_cycle_attribute,
      def_creation_attributes: array [1 .. 2] of fst$file_cycle_attribute,
      file_attachment: array [1 .. 3] of fst$attachment_option,
      mandate_creation_attributes: array [1 .. 2] of fst$file_cycle_attribute;

    file_attachment [1].selector := fsc$access_and_share_modes;
    file_attachment [2].selector := fsc$open_share_modes;
    file_attachment [3].selector := fsc$create_file;

    file_attachment [1].access_modes.selector := fsc$specific_access_modes;
    file_attachment [1].share_modes.selector := fsc$specific_share_modes;
    file_attachment [1].access_modes.value := $fst$file_access_options
          [fsc$read, fsc$execute, fsc$shorten, fsc$append];
    file_attachment [1].share_modes.value := $fst$file_access_options [];
    IF input_file THEN
      file_attachment [2].open_share_modes := $fst$file_access_options [fsc$read, fsc$execute];
    ELSE
      file_attachment [2].open_share_modes := $fst$file_access_options
            [fsc$read, fsc$execute, fsc$shorten, fsc$append];
    IFEND;
    file_attachment [3].create_file := TRUE;
    def_creation_attributes [1].selector := fsc$record_type;
    def_creation_attributes [1].record_type := amc$variable;
    def_creation_attributes [2].selector := fsc$file_contents_and_processor;
    def_creation_attributes [2].file_contents := amc$legible;
    def_creation_attributes [2].file_processor := osc$null_name;
    attribute_validation [1].selector := fsc$file_contents_and_processor;
    attribute_validation [1].file_contents := amc$unknown_contents;
    attribute_validation [1].file_processor := amc$unknown_processor;
    attribute_validation [2].selector := fsc$file_contents_and_processor;
    attribute_validation [2].file_contents := amc$legible;
    attribute_validation [2].file_processor := osc$null_name;

    mandate_creation_attributes [1].selector := fsc$record_type;
    mandate_creation_attributes [1].record_type := amc$variable;
    mandate_creation_attributes [2].selector := fsc$ring_attributes;
    mandate_creation_attributes [2].ring_attributes.r1 := osc$user_ring;
    mandate_creation_attributes [2].ring_attributes.r2 := osc$user_ring;
    mandate_creation_attributes [2].ring_attributes.r3 := osc$user_ring;
    attribute_override [1].selector := fsc$ring_attributes;
    attribute_override [1].ring_attributes.r1 := osc$user_ring;
    attribute_override [1].ring_attributes.r2 := osc$user_ring;
    attribute_override [1].ring_attributes.r3 := osc$user_ring;
    IF NOT input_file THEN
      fsp$open_file (output_file, amc$record, ^file_attachment, ^def_creation_attributes,
            ^mandate_creation_attributes, ^attribute_validation, ^attribute_override, cmv$output_fid, status);
    ELSE
      fsp$open_file (output_file, amc$record, ^file_attachment, ^def_creation_attributes,
            ^mandate_creation_attributes, ^attribute_validation, ^attribute_override, cmv$input_fid, status);
    IFEND;
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND cmp$save_output;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$set_exec_within_editor', EJECT ??

{ PURPOSE:
{    This procedure sets a flag to indicate that the user is in
{    the PCU editor.

  PROCEDURE [XDCL, #GATE] cmp$set_exec_in_editor
    (    active: boolean);

    cmv$executing_within_editor := active;

  PROCEND cmp$set_exec_in_editor;

?? OLDTITLE ??
?? NEWTITLE := '  cmp$set_in_editor ', EJECT ??

{ PURPOSE:
{    Set the value of CMV$IN_EDITOR to indicate that  user
{    is currently in the PCU editor.

  PROCEDURE [XDCL, #GATE] cmp$set_in_editor
    (    in_editor: boolean);

    cmv$in_editor := in_editor;
  PROCEND cmp$set_in_editor;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$set_default_mainframe_name', EJECT ??

{ PURPOSE:
{   This procedure assigns the default value of the mainframe name.

  PROCEDURE [XDCL, #GATE] cmp$set_default_mainframe_name
    (VAR status: ost$status);

    VAR
      index: integer,
      str: ost$string;

    VAR
      mainframe_id: pmt$mainframe_id;

    pmp$get_mainframe_id (mainframe_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    cmv$mainframe_name := mainframe_id;
    cmv$installed_mainframe := cmv$mainframe_name;

  PROCEND cmp$set_default_mainframe_name;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$setup_mainframe_name', EJECT ??

{ PURPOSE:
{    This procedure sets up the value of the mainframe name
{    as defined by the PCU subcommand DEFINE_WORKING_MAINFRAME.

  PROCEDURE [XDCL, #GATE] cmp$setup_mainframe_name
    (    mainframe_name: cmt$element_name);

    cmv$mainframe_name := mainframe_name;

  PROCEND cmp$setup_mainframe_name;
?? OLDTITLE ??
?? NEWTITLE := 'update_downward_connections', EJECT ??

{ PURPOSE:
{   This procedure scans the file produced by INSTALL_PHYSICAL_CONFIGURATION or VERIFY_PHYSICAL_CONFIGURATION,
{   then updates all the downline connections of all elements. It also validates duplicate physical addresses
{   of elements in the configuration file.

  PROCEDURE update_downward_connections
    (    input_fid: amt$file_identifier;
         output_fid: amt$file_identifier;
     VAR status: ost$status);

    VAR
      cm_unit_type: cmt$unit_type,
      comm_port_number: cmt$communications_port_number,
      ct_port_number: cmt$controller_port_number,
      element: ^cmt$element_definition,
      eoi_addr: array [1 .. 1] of amt$access_info,
      found: boolean,
      inn: amt$segment_pointer,
      in_el: ^cmt$element_definition,
      iou_name: cmt$element_name,
      io_unit_type: iot$unit_type,
      loop_count: integer,
      loop_index: integer,
      mf_name: cmt$element_name,
      out: amt$segment_pointer,
      out_el: ^cmt$element_definition,
      pen: cmt$physical_equipment_number,
      sd_port_number: cmt$data_storage_port_number,
      unit_class: cmt$unit_class;

    status.normal := TRUE;

  /main_program/
    BEGIN

      eoi_addr [1].key := amc$eoi_byte_address;

      amp$get_segment_pointer (input_fid, amc$sequence_pointer, inn, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      amp$get_segment_pointer (output_fid, amc$sequence_pointer, out, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      amp$fetch_access_information (input_fid, eoi_addr, status);

      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      IF NOT eoi_addr [1].item_returned THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_file_error,
              'update_downward_connections', status);
        EXIT /main_program/;
      IFEND;

      RESET inn.sequence_pointer;
      RESET out.sequence_pointer;
      loop_count := eoi_addr [1].eoi_byte_address DIV #SIZE (cmt$element_definition);
      FOR loop_index := 1 TO loop_count DO
        NEXT in_el IN inn.sequence_pointer;
        NEXT out_el IN out.sequence_pointer;
        out_el^ := in_el^;
      FOREND;

      amp$set_segment_eoi (output_fid, out, status);
      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;
      RESET out.sequence_pointer;
      FOR loop_index := 1 TO loop_count DO
        NEXT out_el IN out.sequence_pointer;
        CASE out_el^.element_type OF
        = cmc$storage_device_element =

          FOR sd_port_number := LOWERVALUE (sd_port_number) TO UPPERVALUE (sd_port_number) DO
            IF out_el^.storage_device.connection.port [sd_port_number].configured THEN
              cmp$get_unit_type (out_el^.product_id, cm_unit_type, io_unit_type, unit_class, found);
              IF (cm_unit_type = cmc$mshydra) OR (out_el^.storage_device.connection.port [sd_port_number].
                    upline_connection_type = cmc$data_channel_element) THEN
                mf_name := out_el^.storage_device.connection.port [sd_port_number].mainframe_ownership;
                iou_name := out_el^.storage_device.connection.port [sd_port_number].iou;
              ELSE
                mf_name := osc$null_name;
              IFEND;

              cmp$find_element (out_el^.storage_device.connection.port [sd_port_number].element_name,
                    iou_name, mf_name, output_fid, element, status);

              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;

              IF element^.element_type = cmc$controller_element THEN
                IF (element^.controller.connection.unit [out_el^.storage_device.physical_unit_number].
                      configured) AND (element^.controller.connection.
                      unit [out_el^.storage_device.physical_unit_number].element_name <>
                      out_el^.element_name) THEN

                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_pun,
                        out_el^.element_name, status);
                  osp$append_status_integer (osc$status_parameter_delimiter,
                        out_el^.storage_device.physical_unit_number, 10, TRUE, status);
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        element^.controller.connection.unit [out_el^.storage_device.physical_unit_number].
                        element_name, status);

                  EXIT /main_program/;
                IFEND;
                element^.controller.connection.unit [out_el^.storage_device.physical_unit_number].
                      configured := TRUE;
                element^.controller.connection.unit [out_el^.storage_device.physical_unit_number].
                      element_name := out_el^.element_name;
              ELSEIF element^.element_type = cmc$data_channel_element THEN
                IF (element^.data_channel.connection.equipment [out_el^.storage_device.physical_unit_number].
                      configured) AND (element^.data_channel.connection.
                      equipment [out_el^.storage_device.physical_unit_number].element_name <>
                      out_el^.element_name) THEN

                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_pun,
                        out_el^.element_name, status);
                  osp$append_status_integer (osc$status_parameter_delimiter,
                        out_el^.storage_device.physical_unit_number, 10, TRUE, status);
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        element^.data_channel.connection.equipment [out_el^.storage_device.
                        physical_unit_number].element_name, status);

                  EXIT /main_program/;
                IFEND;
                element^.data_channel.connection.equipment [out_el^.storage_device.physical_unit_number].
                      configured := TRUE;
                element^.data_channel.connection.equipment [out_el^.storage_device.physical_unit_number].
                      element_name := out_el^.element_name;
              IFEND;

            IFEND;

          FOREND;

        = cmc$controller_element =

{ Need to update connection in case of Channel adapter being
{ the upline connection type

          FOR ct_port_number := LOWERVALUE (ct_port_number) TO UPPERVALUE (ct_port_number) DO
            IF out_el^.controller.connection.port [ct_port_number].configured THEN

              cmp$find_element (out_el^.controller.connection.port [ct_port_number].element_name,
                    out_el^.controller.connection.port [ct_port_number].iou,
                    out_el^.controller.connection.port [ct_port_number].mainframe_ownership, output_fid,
                    element, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;

              IF element^.element_type = cmc$data_channel_element THEN
                IF (element^.data_channel.connection.equipment [out_el^.controller.physical_equipment_number].
                      configured) AND (element^.data_channel.connection.
                      equipment [out_el^.controller.physical_equipment_number].element_name <>
                      out_el^.element_name) THEN


                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_pen,
                        out_el^.element_name, status);
                  osp$append_status_integer (osc$status_parameter_delimiter,
                        out_el^.controller.physical_equipment_number, 10, TRUE, status);
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        element^.data_channel.connection.equipment [out_el^.controller.
                        physical_equipment_number].element_name, status);

                  EXIT /main_program/;
                IFEND;
              IFEND;

              element^.data_channel.connection.equipment [out_el^.controller.physical_equipment_number].
                    configured := TRUE;
              element^.data_channel.connection.equipment [out_el^.controller.physical_equipment_number].
                    element_name := out_el^.element_name;
            IFEND;
          FOREND;

        = cmc$channel_adapter_element =
          IF out_el^.channel_adapter.connection.channel.configured THEN
            cmp$find_element (out_el^.channel_adapter.connection.channel.element_name,
                  out_el^.channel_adapter.connection.channel.iou,
                  out_el^.channel_adapter.connection.channel.mainframe_ownership, output_fid, element,
                  status);
            IF NOT status.normal THEN
              EXIT /main_program/;
            IFEND;
            IF element^.element_type = cmc$data_channel_element THEN
              IF (element^.data_channel.connection.equipment [out_el^.channel_adapter.
                    physical_equipment_number].configured) AND (element^.data_channel.connection.
                    equipment [out_el^.channel_adapter.physical_equipment_number].element_name <>
                    out_el^.element_name) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_pen,
                      out_el^.element_name, status);
                osp$append_status_integer (osc$status_parameter_delimiter,
                      out_el^.channel_adapter.physical_equipment_number, 10, TRUE, status);
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      element^.data_channel.connection.equipment [out_el^.channel_adapter.
                      physical_equipment_number].element_name, status);
                EXIT /main_program/;
              IFEND;
            IFEND;

            element^.data_channel.connection.equipment [out_el^.channel_adapter.physical_equipment_number].
                  configured := TRUE;
            element^.data_channel.connection.equipment [out_el^.channel_adapter.physical_equipment_number].
                  element_name := out_el^.element_name;
          IFEND;

        = cmc$communications_element =

          FOR comm_port_number := LOWERVALUE (comm_port_number) TO UPPERVALUE (comm_port_number) DO
            IF out_el^.communications_element.connection.port [comm_port_number].configured THEN
              cmp$find_element (out_el^.communications_element.connection.port [comm_port_number].
                    element_name, out_el^.communications_element.connection.port [comm_port_number].iou,
                    out_el^.communications_element.connection.port [comm_port_number].mainframe_ownership,
                    output_fid, element, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;

              IF element^.element_type = cmc$data_channel_element THEN
                IF (element^.data_channel.connection.equipment [out_el^.communications_element.
                      physical_equipment_number].configured) AND (element^.data_channel.connection.
                      equipment [out_el^.communications_element.physical_equipment_number].element_name <>
                      out_el^.element_name) THEN
                  osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_pen,
                        out_el^.element_name, status);
                  osp$append_status_integer (osc$status_parameter_delimiter,
                        out_el^.communications_element.physical_equipment_number, 10, TRUE, status);
                  osp$append_status_parameter (osc$status_parameter_delimiter,
                        element^.data_channel.connection.equipment [out_el^.communications_element.
                        physical_equipment_number].element_name, status);
                  EXIT /main_program/;
                IFEND;
              IFEND;
              element^.data_channel.connection.equipment [out_el^.communications_element.
                    physical_equipment_number].configured := TRUE;
              element^.data_channel.connection.equipment [out_el^.communications_element.
                    physical_equipment_number].element_name := out_el^.element_name;
            IFEND;
          FOREND;

        = cmc$external_processor_element =
          FOR ct_port_number := LOWERVALUE (ct_port_number) TO UPPERVALUE (ct_port_number) DO
            IF out_el^.external_processor.connection.io_port [ct_port_number].configured THEN

              cmp$find_element (out_el^.external_processor.connection.io_port [ct_port_number].element_name,
                    out_el^.external_processor.connection.io_port [ct_port_number].iou,
                    out_el^.external_processor.connection.io_port [ct_port_number].mainframe_ownership,
                    output_fid, element, status);

              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;

              IF (element^.data_channel.connection.equipment [out_el^.external_processor.
                    physical_equipment_number].configured) AND (element^.data_channel.connection.
                    equipment [out_el^.external_processor.physical_equipment_number].element_name <>
                    out_el^.element_name) THEN
                osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_duplicate_pen,
                      out_el^.element_name, status);
                osp$append_status_integer (osc$status_parameter_delimiter,
                      out_el^.external_processor.physical_equipment_number, 10, TRUE, status);
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      element^.data_channel.connection.equipment [out_el^.external_processor.
                      physical_equipment_number].element_name, status);

                EXIT /main_program/;
              IFEND;

              element^.data_channel.connection.equipment [out_el^.external_processor.
                    physical_equipment_number].configured := TRUE;
              element^.data_channel.connection.equipment [out_el^.external_processor.
                    physical_equipment_number].element_name := out_el^.element_name;
            IFEND;

          FOREND;

        ELSE

        CASEND;
      FOREND;

    END /main_program/;

  PROCEND update_downward_connections;
?? OLDTITLE ??
?? NEWTITLE := '   cmp$update_descriptor', EJECT ??

{ PURPOSE:
{    This procedure scans the single linked list of PCU command descriptors
{    produced by EDIT_PHYSICAL_CONFIGURATION, and updates values of command
{    descriptors that use SAME_AS parameter.

  PROCEDURE [XDCL, #GATE] cmp$update_descriptor;

    VAR
      current_p: ^cmt$pcu_command_descriptor,
      temp_p: ^cmt$pcu_command_descriptor;

    IF cmv$command_descriptor_p <> NIL THEN
      current_p := cmv$command_descriptor_p;
      WHILE current_p <> NIL DO
        IF (current_p^.same_as <> osc$null_name) THEN
          temp_p := cmv$command_descriptor_p;

        /loop/
          WHILE temp_p <> NIL DO
            IF temp_p^.element_name = current_p^.same_as THEN
              current_p^.same_as := osc$null_name;
              IF current_p^.sn = 0 THEN
                current_p^.sn := temp_p^.sn;
              IFEND;
              IF current_p^.pid = osc$null_name THEN
                current_p^.pid := temp_p^.pid;
              IFEND;
              current_p^.verify := temp_p^.verify;
              IF current_p^.state = osc$null_name THEN
                current_p^.state := temp_p^.state;
              IFEND;
              IF current_p^.application_info_p = NIL THEN
                current_p^.application_info_p := temp_p^.application_info_p;
              ELSE
                IF temp_p^.application_info_p <> NIL THEN
                  FREE current_p^.application_info_p IN osv$task_private_heap^;
                  current_p^.application_info_p := temp_p^.application_info_p;
                IFEND;
              IFEND;
              IF current_p^.site_info_p = NIL THEN
                current_p^.site_info_p := temp_p^.site_info_p;
              ELSE
                IF temp_p^.site_info_p <> NIL THEN
                  FREE current_p^.site_info_p IN osv$task_private_heap^;
                  current_p^.site_info_p := temp_p^.site_info_p;
                IFEND;
              IFEND;
              EXIT /loop/;
            IFEND;
            temp_p := temp_p^.next_descriptor;
          WHILEND /loop/;
        IFEND;
        current_p := current_p^.next_descriptor;
      WHILEND;
    IFEND;
  PROCEND cmp$update_descriptor;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$update_output_file', EJECT ??

{ PURPOSE:
{    This procedure update the contents of the output file
{    on the EDIT_PHYSICAL_CONFIGURATION command.

  PROCEDURE [XDCL, #GATE] cmp$update_output_file
    (VAR status: ost$status);

    cmp$update_pc (cmv$output_fid, status);

  PROCEND cmp$update_output_file;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$update_pc', EJECT ??

{ PURPOSE:
{     This procedure updates the physical configuration
{   file specified on the output parameter of EDIPC.
{   This procedure will be invoked if QUIT WPC=TRUE


  PROCEDURE [XDCL] cmp$update_pc
    (    output_fid: amt$file_identifier;
     VAR status: ost$status);

    VAR
      byte_address: amt$file_byte_address,
      current_p: ^cmt$pcu_command_descriptor,
      index: integer,
      line: string (2),
      local_status: ost$status,
      next_p: ^cmt$pcu_command_descriptor;

    amp$rewind (output_fid, osc$wait, local_status);

    IF cmv$command_descriptor_p <> NIL THEN
      current_p := cmv$command_descriptor_p;
      WHILE current_p <> NIL DO
        cmp$display_descriptor (current_p, output_fid, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        current_p := current_p^.next_descriptor;

      WHILEND;
    ELSE
      line := '  ';
      amp$put_next (output_fid, ^line, 2, byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;
    cmp$clean_up_list;

    fsp$close_file (output_fid, status);


  PROCEND cmp$update_pc;


?? OLDTITLE ??
?? NEWTITLE := '   cmp$validate_address_range', EJECT ??

{ PURPOSE:
{    This procedure validates the range of physical unit number based
{    on the device type.

  PROCEDURE cmp$validate_address_range
    (    unit_type: cmt$unit_type;
         physical_address: integer;
     VAR status: ost$status);

    VAR
      error_string: string (40),
      str: ost$string;

    status.normal := TRUE;
    clp$convert_integer_to_string (physical_address, 10, TRUE, str, status);
    error_string := '   ';
    error_string (1, 18) := ' Physical address ';
    error_string (19, str.size) := str.value (1, str.size);
    error_string (19 + str.size + 1, * ) := 'is out of range';

    CASE unit_type OF
    = cmc$mt639_1 =
      IF (physical_address <> 0) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;

    = cmc$mt639_s0 =
      IF (physical_address < 0) OR (physical_address > 1) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;

    = cmc$mt679_5 .. cmc$mt698_3x, cmc$ms844_4x, cmc$mshydra, cmc$ms5832_2,
            cmc$ms5833_1p .. cmc$ms5833_4, cmc$ms5837_1p .. cmc$ms5837_4, cmc$ms5838_1p .. cmc$ms5838_4,
            cmc$ms47444_1p .. cmc$ms47444_4 =
      IF (physical_address < 0) OR (physical_address > 7) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;

    = cmc$mt5682_1x =
      IF (physical_address < 0) OR (physical_address > 15) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;

    = cmc$ms885_1x .. cmc$ms885_4x =
      IF (physical_address < 32) OR (physical_address > 47) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;
    = cmc$msfsd2_s0 =

      IF (physical_address < 0) OR (physical_address > 7) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;

    = cmc$ms834_2, cmc$msfsd_2 =
      IF (physical_address < 0) OR (physical_address > 4) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;
    = cmc$ms895_2, cmc$ms5832_1, cmc$ms5833_1, cmc$ms5837_1, cmc$ms5838_1, cmc$ms47444_1,
      cmc$ms_ntdd_1 .. cmc$ms_ntdd_6 =
      IF (physical_address < 0) OR (physical_address > 31) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;
    ELSE

{ may be a foreign product

      IF (physical_address < 0) OR (physical_address > 63) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter, error_string,
              status);
        RETURN;
      IFEND;
    CASEND;


  PROCEND cmp$validate_address_range;

?? OLDTITLE ??
?? NEWTITLE := '   cmp$validate_mainframe_name', EJECT ??

{ PURPOSE:
{   This procedure validates the name of the mainframe used in PCU subcommands.

  PROCEDURE [XDCL, #GATE] cmp$validate_mainframe_name
    (    mainframe_name: cmt$element_name;
     VAR status: ost$status);

    VAR
      i: 1 .. 31,
      found: boolean;

    VAR
      alpha_numeric: [STATIC, READ, oss$job_paged_literal] set of char := ['0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

    status.normal := TRUE;
    IF mainframe_name (1, 8) = '$SYSTEM_' THEN
      FOR i := 1 TO 4 DO
        IF NOT (mainframe_name (8 + i, 1) IN alpha_numeric) THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
                'Invalid mainframe_name specified', status);
          RETURN;
        IFEND;
      FOREND;
    ELSE

{ Error

      osp$set_status_abnormal (cmc$configuration_management_id, cme$pcu_invalid_parameter,
            'Invalid mainframe_name specified', status);
      RETURN;
    IFEND;

  PROCEND cmp$validate_mainframe_name;

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

{ PURPOSE:
{   Initialize all fields of a descriptor that will be used
{   in the linked list created by the PCU editor.

  PROCEDURE initialize_descriptor
    (VAR descriptor: cmt$pcu_command_descriptor);

    descriptor.same_as := osc$null_name;
    descriptor.sn := 0;
    descriptor.pid := osc$null_name;
    descriptor.state := osc$null_name;
    descriptor.ioupn := osc$null_name;
    descriptor.next_descriptor := NIL;
    descriptor.pc_list := NIL;
    descriptor.iou_list := NIL;
    descriptor.cmc_list := NIL;
    descriptor.channel_list := NIL;
    descriptor.application_info_p := NIL;
    descriptor.site_info_p := NIL;
  PROCEND initialize_descriptor;

?? OLDTITLE ??
?? NEWTITLE := '   Function find_name_length', EJECT ??

{ PURPOSE:
{   Returns the length of a name.


  FUNCTION [INLINE] find_name_length
    (    element_name: cmt$element_name): integer;

    VAR
      i: integer;

    i := 0;
    REPEAT
      i := i + 1;
    UNTIL (element_name (i) = ' ') OR (i = 31);
    find_name_length := i - 1;

  FUNCEND find_name_length;


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

{ PURPOSE:
{   This procedure trims all blanks in a string. The number of
{   non blanks characters is returned.

  PROCEDURE [INLINE] trim_blank
    (    line: string (osc$max_string_size);
     VAR length: 0 .. osc$max_string_size);

    VAR
      i: 0 .. osc$max_string_size;

    i := osc$max_string_size;
    WHILE (i >= 1) AND (line (i, 1) = ' ') DO
      i := i - 1;
    WHILEND;
    length := i + 2;

  PROCEND trim_blank;

?? OLDTITLE ??

MODEND cmm$phys_configuration_utl_23d;
