?? LEFT := 1, RIGHT := 110 ??
?? TITLE := 'NOS/VE: Manage Non-CDNA OSI address command processors' ??
?? NEWTITLE := 'Global Declarations' ??
MODULE nam$manage_non_cdna_addresses;

{ PURPOSE
{   This module implements the command processors for manipulating non-CDNA OSI addresses
{   in the CDNA Directory, as documented in DCS document A8273.
{ DESIGN
{   The facilities of the CDNA Directory are used to store all information used by these
{   command processors. No information is retained locally within this module or within
{   unique network paged structures. This allows these command processors to reside on the
{   $system.osf$system_library and execute in the user's ring.

?? PUSH (LISTEXT := ON) ??
*copyc clc$page_widths
*copyc clt$parameter_list
*copyc clt$parameter_value_table
*copyc clt$which_parameter
*copyc nae$application_management
*copyc nae$manage_network_applications
*copyc nat$directory_interfaces
*copyc nat$osi_address_length
*copyc nat$protocol
*copyc ost$date
*copyc ost$name
*copyc ost$status
*copyc ost$time
*copyc pmt$os_name
?? POP ??
*copyc avp$get_capability
*copyc clp$close_display
*copyc clp$evaluate_parameters
*copyc clp$new_display_line
*copyc clp$open_display_reference
*copyc clp$put_display
*copyc clp$put_partial_display
*copyc clp$reset_for_next_display_page
*copyc nlp$delete_registered_title
*copyc nlp$end_title_translation
*copyc nlp$get_title_translation
*copyc nlp$register_title
*copyc nlp$translate_title
*copyc osp$append_status_integer
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc pmp$get_legible_date_time
*copyc pmp$get_os_version
?? OLDTITLE ??
?? NEWTITLE := 'Local definitions', EJECT ??

  CONST
    command_level = '88203',
    command_version = 'V1.0',
    default_password = 1234;

  TYPE
    osi_address_header = record
      kind: nat$network_address_kind,
      length: nat$osi_address_length,
    recend,

    osi_presentation_selector = record
      length: nat$osi_psap_selector_length,
      value: nat$osi_presentation_selector,
    recend,

    osi_session_selector = record
      length: nat$osi_ssap_selector_length,
      value: nat$osi_session_selector,
    recend,

    osi_transport_selector = record
      tsap_length: nat$osi_tsap_selector_length,
      tsap: string ( * ),
    recend,

    osi_network_address = record
      network_address_length: nat$osi_network_address_length,
      network_address: string ( * ),
    recend;

  VAR
    hex_digits: [STATIC, READ] array [0 .. 15] of char := ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
          'A', 'B', 'C', 'D', 'E', 'F'],
    wild_card_title: string (1) := '*';

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] nap$add_osi_address', EJECT ??

{ PURPOSE: This procedure processes the ADD_OSI_ADDRESS command, which adds a non-CDNA OSI
{          address to the CDNA Directory. Translations of this address are available only
{          to entities in the local system.
{ DESIGN:  The command parameters are parsed and validated. The title/address pair is then
{          placed in the local CDNA Directory. An identifier is assigned to this title/address
{          pair either by command parameter or by default. The title identifier is used as
{          the user identifier in the CDNA Directory and is used by the DISPLAY_OSI_ADDRESSES
{          and DELETE_OSI_ADDRESSES command processors.

  PROCEDURE [XDCL] nap$add_osi_address
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE (nam$addosia) add_osi_addresses, add_osi_address, addosia (
{ titles, title, t: list of any of
{     string 1 .. 255
{     name
{   anyend = $required
{ network_address, na: (check) string 1 .. 40 = $required
{ transport_selector, ts: (check) string 0 .. 64 = $required
{ session_selector, ss: (check) string 0 .. 32 = $required
{ presentation_selector, ps: (check) string 0 .. 8
{ priority, p: integer 1 .. 255 = 1
{ data, d: string 1 .. 32
{ title_identifier, ti: name
{ network_service, ns: key
{     (connection_less_net_service, clns)
{     (connection_oriented_net_service, cons)
{   keyend = clns
{ transport_class, tc: integer 0 .. 4 = 4
{ status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 22] of clt$pdt_parameter_name,
      parameters: array [1 .. 11] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier,
        element_type_spec: record
          header: clt$type_specification_header,
          qualifier: clt$union_type_qualifier,
          type_size_1: clt$type_specification_size,
          element_type_spec_1: record
            header: clt$type_specification_header,
            qualifier: clt$string_type_qualifier,
          recend,
          type_size_2: clt$type_specification_size,
          element_type_spec_2: record
            header: clt$type_specification_header,
            qualifier: clt$name_type_qualifier,
          recend,
        recend,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$string_type_qualifier,
      recend,
      type3: record
        header: clt$type_specification_header,
        qualifier: clt$string_type_qualifier,
      recend,
      type4: record
        header: clt$type_specification_header,
        qualifier: clt$string_type_qualifier,
      recend,
      type5: record
        header: clt$type_specification_header,
        qualifier: clt$string_type_qualifier,
      recend,
      type6: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type7: record
        header: clt$type_specification_header,
        qualifier: clt$string_type_qualifier,
      recend,
      type8: record
        header: clt$type_specification_header,
        qualifier: clt$name_type_qualifier,
      recend,
      type9: record
        header: clt$type_specification_header,
        qualifier: clt$keyword_type_qualifier,
        keyword_specs: array [1 .. 4] of clt$keyword_specification,
        default_value: string (4),
      recend,
      type10: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type11: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [89, 11, 16, 11, 51, 37, 272],
    clc$command, 22, 11, 4, 0, 0, 0, 11, 'NAM$ADDOSIA'], [
    ['D                              ',clc$abbreviation_entry, 7],
    ['DATA                           ',clc$nominal_entry, 7],
    ['NA                             ',clc$abbreviation_entry, 2],
    ['NETWORK_ADDRESS                ',clc$nominal_entry, 2],
    ['NETWORK_SERVICE                ',clc$nominal_entry, 9],
    ['NS                             ',clc$abbreviation_entry, 9],
    ['P                              ',clc$abbreviation_entry, 6],
    ['PRESENTATION_SELECTOR          ',clc$nominal_entry, 5],
    ['PRIORITY                       ',clc$nominal_entry, 6],
    ['PS                             ',clc$abbreviation_entry, 5],
    ['SESSION_SELECTOR               ',clc$nominal_entry, 4],
    ['SS                             ',clc$abbreviation_entry, 4],
    ['STATUS                         ',clc$nominal_entry, 11],
    ['T                              ',clc$abbreviation_entry, 1],
    ['TC                             ',clc$abbreviation_entry, 10],
    ['TI                             ',clc$abbreviation_entry, 8],
    ['TITLE                          ',clc$alias_entry, 1],
    ['TITLES                         ',clc$nominal_entry, 1],
    ['TITLE_IDENTIFIER               ',clc$nominal_entry, 8],
    ['TRANSPORT_CLASS                ',clc$nominal_entry, 10],
    ['TRANSPORT_SELECTOR             ',clc$nominal_entry, 3],
    ['TS                             ',clc$abbreviation_entry, 3]],
    [
{ PARAMETER 1
    [18, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 49, clc$required_parameter,
  0, 0],
{ PARAMETER 2
    [4, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$extended_parameter_checking, 8, clc$required_parameter, 0
  , 0],
{ PARAMETER 3
    [21, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$extended_parameter_checking, 8, clc$required_parameter, 0
  , 0],
{ PARAMETER 4
    [11, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$extended_parameter_checking, 8, clc$required_parameter, 0
  , 0],
{ PARAMETER 5
    [8, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$extended_parameter_checking, 8, clc$optional_parameter, 0
  , 0],
{ PARAMETER 6
    [9, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 7
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 8, clc$optional_parameter, 0
  , 0],
{ PARAMETER 8
    [19, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 5, clc$optional_parameter, 0
  , 0],
{ PARAMETER 9
    [5, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 155,
  clc$optional_default_parameter, 0, 4],
{ PARAMETER 10
    [20, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 11
    [13, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$list_type], [33, 1, clc$max_list_size, FALSE],
      [[1, 0, clc$union_type], [[clc$name_type, clc$string_type],
      TRUE, 2],
      8, [[1, 0, clc$string_type], [1, 255, FALSE]],
      5, [[1, 0, clc$name_type], [1, osc$max_name_size]]
      ]
    ],
{ PARAMETER 2
    [[1, 0, clc$string_type], [1, 40, FALSE]],
{ PARAMETER 3
    [[1, 0, clc$string_type], [0, 64, FALSE]],
{ PARAMETER 4
    [[1, 0, clc$string_type], [0, 32, FALSE]],
{ PARAMETER 5
    [[1, 0, clc$string_type], [0, 8, FALSE]],
{ PARAMETER 6
    [[1, 0, clc$integer_type], [1, 255, 10],
    '1'],
{ PARAMETER 7
    [[1, 0, clc$string_type], [1, 32, FALSE]],
{ PARAMETER 8
    [[1, 0, clc$name_type], [1, osc$max_name_size]],
{ PARAMETER 9
    [[1, 0, clc$keyword_type], [4], [
    ['CLNS                           ', clc$abbreviation_entry, clc$normal_usage_entry, 1],
    ['CONNECTION_LESS_NET_SERVICE    ', clc$nominal_entry, clc$normal_usage_entry, 1],
    ['CONNECTION_ORIENTED_NET_SERVICE', clc$nominal_entry, clc$normal_usage_entry, 2],
    ['CONS                           ', clc$abbreviation_entry, clc$normal_usage_entry, 2]]
    ,
    'clns'],
{ PARAMETER 10
    [[1, 0, clc$integer_type], [0, 4, 10],
    '4'],
{ PARAMETER 11
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$titles = 1,
      p$network_address = 2,
      p$transport_selector = 3,
      p$session_selector = 4,
      p$presentation_selector = 5,
      p$priority = 6,
      p$data = 7,
      p$title_identifier = 8,
      p$network_service = 9,
      p$transport_class = 10,
      p$status = 11;

    VAR
      pvt: array [1 .. 11] of clt$parameter_value;

    VAR
      address_header: ^osi_address_header,
      address_length: nat$osi_address_length,
      directory_identifier: nat$directory_entry_identifier,
      domain: nat$title_domain,
      network_address: ^osi_network_address,
      network_application_management: boolean,
      osi_address: nat$osi_registration_address,
      priority: nat$directory_priority,
      protocol: nat$protocol,
      psap_selector: ^osi_presentation_selector,
      ssap_selector: ^osi_session_selector,
      title: ^string ( * ),
      title_value: ^clt$data_value,
      transport_selector: ^osi_transport_selector,
      user_data: ^string ( * ),
      user_data_length: 0 .. nac$max_directory_data_length,
      user_identifier: ost$name;

?? NEWTITLE := '  check_hex_string_parameters', EJECT ??

    PROCEDURE check_hex_string_parameters
      (    parameter_value_table: ^clt$parameter_value_table;
           which_parameter: clt$which_parameter;
       VAR status: ost$status);

      VAR
        i: integer,
        legal_hex_characters: [STATIC, READ] set of char := ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
              'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'],
        parameter_length: integer,
        parameter_value: ^string ( * );

      IF which_parameter.specific THEN
        CASE which_parameter.number OF
        = p$network_address =
          parameter_value := pvt [p$network_address].value^.string_value;

        = p$transport_selector =
          parameter_value := pvt [p$transport_selector].value^.string_value;

        = p$session_selector =
          parameter_value := pvt [p$session_selector].value^.string_value;

        = p$presentation_selector =
          parameter_value := pvt [p$presentation_selector].value^.string_value;

        ELSE
          RETURN;
        CASEND;

        parameter_length := STRLENGTH (parameter_value^);
        IF parameter_length MOD 2 = 1 THEN
          osp$set_status_condition (nae$even_char_count_required, status);
          osp$append_status_integer (osc$status_parameter_delimiter, parameter_length, 10, FALSE, status);
        ELSE
          FOR i := 1 TO parameter_length DO
            IF NOT (parameter_value^ (i, 1) IN legal_hex_characters) THEN
              osp$set_status_abnormal (nac$status_id, nae$invalid_hex_digit, parameter_value^ (i, 1), status);
              RETURN;
            IFEND;
          FOREND;
        IFEND;
      IFEND;

    PROCEND check_hex_string_parameters;

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

    PROCEDURE convert_hex_string_to_binary
      (    hex_string: string ( * );
       VAR binary: string ( * ));

      FUNCTION convert
        (    hex_digit: char): 0 .. 128;

        CASE hex_digit OF
        = '0' .. '9' =
          convert := $INTEGER (hex_digit) - $INTEGER ('0');
        = 'A' .. 'F' =
          convert := $INTEGER (hex_digit) - $INTEGER ('A') + 10;
        = 'a' .. 'f' =
          convert := $INTEGER (hex_digit) - $INTEGER ('a') + 10;
        ELSE
          convert := 0;
        CASEND;

      FUNCEND convert;

      VAR
        binary_index: integer,
        hex_index: integer;

      hex_index := 1;
      binary_index := 1;
      WHILE hex_index < STRLENGTH (hex_string) DO
        binary (binary_index) := $CHAR ((convert (hex_string (hex_index)) * 16) +
              convert (hex_string (hex_index + 1)));
        hex_index := hex_index + 2;
        binary_index := binary_index + 1;
      WHILEND;

    PROCEND convert_hex_string_to_binary;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    clp$evaluate_parameters (parameter_list, #SEQ (pdt), ^check_hex_string_parameters, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    avp$get_capability (avc$network_applic_management, avc$user, network_application_management, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF NOT network_application_management THEN
      osp$set_status_abnormal (nac$status_id, nae$invalid_user, 'ADD_OSI_ADDRESS', status);
      RETURN;
    IFEND;

{ Determine protocol value based on transport class and network service type.

    IF pvt [p$network_service].value^.keyword_value = 'CONNECTION_LESS_NET_SERVICE' THEN
      IF pvt [p$transport_class].value^.integer_value.value < 4 THEN
        osp$set_status_condition (nae$transport_network_mismatch, status);
        RETURN;
      IFEND;
      IF NOT pvt [p$presentation_selector].specified THEN
        protocol := nac$non_cdna_osi_sess_tp4_clns;
      ELSE
        protocol := nac$non_cdna_osi_pres_tp4_clns;
      IFEND;
    ELSE {'CONNECTION_ORIENTED_NET_SERVICE'
      CASE pvt [p$transport_class].value^.integer_value.value OF
      = 0, 1 =
        protocol := nac$non_cdna_osi_pres_tp0_cons;
      = 2, 3 =
        protocol := nac$non_cdna_osi_pres_tp2_cons;
      = 4 =
        protocol := nac$non_cdna_osi_pres_tp4_cons;
      CASEND;
    IFEND;

{ Compute length of address sequence.

    address_length := (STRLENGTH (pvt [p$network_address].value^.string_value^) +
          STRLENGTH (pvt [p$transport_selector].value^.string_value^) +
          STRLENGTH (pvt [p$session_selector].value^.string_value^)) DIV 2 +
          (#SIZE (nat$osi_network_address_length) + #SIZE (nat$osi_tsap_selector_length) +
          #SIZE (nat$osi_ssap_selector_length));
    IF pvt [p$presentation_selector].specified THEN
      address_length := address_length + (STRLENGTH (pvt [p$presentation_selector].value^.string_value^) DIV
            2) + #SIZE (nat$osi_psap_selector_length);
    IFEND;

    PUSH osi_address.osi_address: [[REP address_length + #SIZE (osi_address_header) OF cell]];
    RESET osi_address.osi_address;
    NEXT address_header IN osi_address.osi_address;
    address_header^.length := address_length;
    IF pvt [p$presentation_selector].specified THEN
      address_header^.kind := nac$osi_non_cdna_present_addr;
      osi_address.kind := nac$osi_non_cdna_present_addr;
      NEXT psap_selector: [STRLENGTH (pvt [p$presentation_selector].value^.string_value^) DIV 2] IN
            osi_address.osi_address;
      psap_selector^.length := STRLENGTH (pvt [p$presentation_selector].value^.string_value^) DIV 2;
      convert_hex_string_to_binary (pvt [p$presentation_selector].value^.string_value^, psap_selector^.value);
    ELSE
      address_header^.kind := nac$osi_non_cdna_session_addr;
      osi_address.kind := nac$osi_non_cdna_session_addr;
    IFEND;
    NEXT ssap_selector: [STRLENGTH (pvt [p$session_selector].value^.string_value^) DIV 2] IN
          osi_address.osi_address;
    ssap_selector^.length := STRLENGTH (pvt [p$session_selector].value^.string_value^) DIV 2;
    convert_hex_string_to_binary (pvt [p$session_selector].value^.string_value^, ssap_selector^.value);
    NEXT transport_selector: [STRLENGTH (pvt [p$transport_selector].value^.string_value^) DIV 2] IN
          osi_address.osi_address;
    transport_selector^.tsap_length := STRLENGTH (pvt [p$transport_selector].value^.string_value^) DIV 2;
    convert_hex_string_to_binary (pvt [p$transport_selector].value^.string_value^, transport_selector^.tsap);
    NEXT network_address: [STRLENGTH (pvt [p$network_address].value^.string_value^) DIV 2] IN
          osi_address.osi_address;
    network_address^.network_address_length := STRLENGTH (pvt [p$network_address].value^.string_value^) DIV 2;
    convert_hex_string_to_binary (pvt [p$network_address].value^.string_value^,
          network_address^.network_address);

    domain.kind := nac$local_system_domain;
    priority := pvt [p$priority].value^.integer_value.value;
    title_value := pvt [p$titles].value;
    IF pvt [p$data].specified THEN
      user_data := pvt [p$data].value^.string_value;
      user_data_length := #SIZE (user_data^);
    ELSE
      user_data := NIL;
      user_data_length := 0;
    IFEND;
    IF pvt [p$title_identifier].specified THEN
      user_identifier := pvt [p$title_identifier].value^.name_value;
    ELSE
      user_identifier := osc$null_name;
    IFEND;

    WHILE title_value <> NIL DO
      IF title_value^.element_value^.kind = clc$name THEN
        title := ^title_value^.element_value^.name_value;
      ELSE {title_value^.element_value^.kind = clc$string
        title := title_value^.element_value^.string_value;
      IFEND;
      nlp$register_title (title^, osi_address, protocol, user_data, user_data_length, priority,
            domain, {distribute =} FALSE, nac$cdna_external, default_password, user_identifier,
            directory_identifier, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      title_value := title_value^.link;
    WHILEND;
  PROCEND nap$add_osi_address;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] nap$delete_osi_address', EJECT ??

{ PURPOSE: This procedure processes the DELETE_OSI_ADDRESS command, which deletes a non-CDNA
{          OSI address in the CDNA Directory.
{ DESIGN:  The command parameters are parsed and validated. The Directory is searched for the
{          entry or entries with the requested title identifier. They are then deleted.

  PROCEDURE [XDCL] nap$delete_osi_address
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{  PROCEDURE (nam$delosia) delete_osi_addresses, delete_osi_address, delosia (
{  title_identifier, ti: name = $required
{  status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 3] of clt$pdt_parameter_name,
      parameters: array [1 .. 2] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$name_type_qualifier,
      recend,
      type2: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [88, 12, 7, 10, 29, 32, 280],
    clc$command, 3, 2, 1, 0, 0, 0, 2, 'NAM$DELOSIA'], [
    ['STATUS                         ',clc$nominal_entry, 2],
    ['TI                             ',clc$abbreviation_entry, 1],
    ['TITLE_IDENTIFIER               ',clc$nominal_entry, 1]],
    [
{ PARAMETER 1
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 5, clc$required_parameter, 0
  , 0],
{ PARAMETER 2
    [1, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$name_type], [1, osc$max_name_size]],
{ PARAMETER 2
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$title_identifier = 1,
      p$status = 2;

    VAR
      pvt: array [1 .. 2] of clt$parameter_value;

    VAR
      address: nat$osi_translation_address,
      directory_identifier: nat$directory_entry_identifier,
      local_domain: nat$title_domain,
      local_status: ost$status,
      network_application_management: boolean,
      priority: nat$directory_priority,
      protocol: nat$protocol,
      request_id: nat$directory_search_identifier,
      user_information: SEQ (REP nac$max_directory_data_length of cell),
      title: string (nac$max_title_length),
      title_found: boolean,
      user_identifier: ost$name,
      user_info_length: 0 .. nac$max_directory_data_length;

    status.normal := TRUE;
    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    avp$get_capability (avc$network_applic_management, avc$user, network_application_management, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF NOT network_application_management THEN
      osp$set_status_abnormal (nac$status_id, nae$invalid_user, 'DELETE_OSI_ADDRESS', status);
      RETURN;
    IFEND;

    local_domain.kind := nac$local_system_domain;
    nlp$translate_title (wild_card_title, {wild_card=} TRUE, nac$unknown_protocol, {recurrent_search=}
          FALSE, local_domain, nac$cdna_external, request_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    title_found := FALSE;

  /search_for_identifier/
    REPEAT
      nlp$get_title_translation (request_id, title, address, protocol, ^user_information, user_info_length,
            priority, user_identifier, directory_identifier, local_status);
      IF (local_status.normal) AND (user_identifier = pvt [p$title_identifier].value^.name_value) AND
            ((address.kind = nac$osi_non_cdna_present_addr) OR (address.kind = nac$osi_non_cdna_session_addr))
            THEN
        title_found := TRUE;
        nlp$delete_registered_title (title, default_password, directory_identifier, status);
        IF NOT status.normal THEN
          EXIT /search_for_identifier/;
        IFEND;
      IFEND;
    UNTIL NOT local_status.normal; {/search_for_identifier/}

    nlp$end_title_translation (request_id, {ignore} local_status);
    IF NOT title_found THEN
      osp$set_status_abnormal (nac$status_id, nae$unknown_identifier,
            pvt [p$title_identifier].value^.name_value, status);
    IFEND;

  PROCEND nap$delete_osi_address;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] nap$display_osi_address', EJECT ??

{ PURPOSE: This procedure processes the DISPLAY_OSI_ADDRESS command, which displays non-CDNA
{          OSI addresses in the CDNA Directory. Translations of these addresses are available
{          only to entities in the local system.
{ DESIGN:  The command parameters are parsed and validated. The information registered for the
{          specified titles is displayed to the requested output file.

  PROCEDURE [XDCL] nap$display_osi_address
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE (nam$disosia) display_osi_addresses, display_osi_address, disosia (
{ titles, title, t: list of any of key
{       all
{     keyend
{     string 1 .. 255
{     name
{   anyend = all
{ output, o: file = $output
{ status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 6] of clt$pdt_parameter_name,
      parameters: array [1 .. 3] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier,
        element_type_spec: record
          header: clt$type_specification_header,
          qualifier: clt$union_type_qualifier,
          type_size_1: clt$type_specification_size,
          element_type_spec_1: record
            header: clt$type_specification_header,
            qualifier: clt$keyword_type_qualifier,
            keyword_specs: array [1 .. 1] of clt$keyword_specification,
          recend,
          type_size_2: clt$type_specification_size,
          element_type_spec_2: record
            header: clt$type_specification_header,
            qualifier: clt$string_type_qualifier,
          recend,
          type_size_3: clt$type_specification_size,
          element_type_spec_3: record
            header: clt$type_specification_header,
            qualifier: clt$name_type_qualifier,
          recend,
        recend,
        default_value: string (3),
      recend,
      type2: record
        header: clt$type_specification_header,
        default_value: string (7),
      recend,
      type3: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [89, 11, 16, 11, 47, 52, 105],
    clc$command, 6, 3, 0, 0, 0, 0, 3, 'NAM$DISOSIA'], [
    ['O                              ',clc$abbreviation_entry, 2],
    ['OUTPUT                         ',clc$nominal_entry, 2],
    ['STATUS                         ',clc$nominal_entry, 3],
    ['T                              ',clc$abbreviation_entry, 1],
    ['TITLE                          ',clc$alias_entry, 1],
    ['TITLES                         ',clc$nominal_entry, 1]],
    [
{ PARAMETER 1
    [6, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 97,
  clc$optional_default_parameter, 0, 3],
{ PARAMETER 2
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 7],
{ PARAMETER 3
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$list_type], [81, 1, clc$max_list_size, FALSE],
      [[1, 0, clc$union_type], [[clc$keyword_type, clc$name_type, clc$string_type],
      FALSE, 3],
      44, [[1, 0, clc$keyword_type], [1], [
        ['ALL                            ', clc$nominal_entry, clc$normal_usage_entry, 1]]
        ],
      8, [[1, 0, clc$string_type], [1, 255, FALSE]],
      5, [[1, 0, clc$name_type], [1, osc$max_name_size]]
      ]
    ,
    'all'],
{ PARAMETER 2
    [[1, 0, clc$file_type],
    '$output'],
{ PARAMETER 3
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$titles = 1,
      p$output = 2,
      p$status = 3;

    VAR
      pvt: array [1 .. 3] of clt$parameter_value;

    VAR
      address: nat$osi_translation_address,
      address_header: ^osi_address_header,
      address_length: nat$osi_address_length,
      default_ring_attributes: amt$ring_attributes,
      directory_identifier: nat$directory_search_identifier,
      display_control: clt$display_control,
      line: string (nac$max_title_length + 40),
      line_length: integer,
      local_domain: nat$title_domain,
      local_status: ost$status,
      network_address: ^SEQ ( * ),
      network_address_value: ^string ( * ),
      network_application_management: boolean,
      network_service: string (20),
      priority: nat$directory_priority,
      protocol: nat$protocol,
      psap_selector: ^osi_presentation_selector,
      request_id: nat$directory_search_identifier,
      ssap_selector: ^osi_session_selector,
      title: ^clt$data_value,
      title_found: boolean,
      title_string: ^string ( * ),
      title_value: string (nac$max_title_length),
      transport_class: 0 .. 4,
      transport_selector: ^osi_transport_selector,
      user_identifier: ost$name,
      user_info: ^SEQ (REP nac$max_directory_data_length of cell),
      user_information: SEQ (REP nac$max_directory_data_length of cell),
      user_information_value: ^string ( * ),
      user_info_length: 0 .. nac$max_directory_data_length,
      wild_card: boolean;

?? NEWTITLE := '  convert_string_to_hex_digits', EJECT ??

    PROCEDURE convert_string_to_hex_digits
      (    input_string: string ( * );
       VAR output_string { input, output } : string ( * );
       VAR output_index { input, output } : integer);

      VAR
        data_index: integer;

      FOR data_index := 1 TO STRLENGTH (input_string) DO
        output_string (output_index) := hex_digits [$INTEGER (input_string (data_index)) DIV 16];
        output_string (output_index + 1) := hex_digits [$INTEGER (input_string (data_index)) MOD 16];
        output_index := output_index + 2;
      FOREND;
      output_string (output_index) := ' ';

    PROCEND convert_string_to_hex_digits;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    avp$get_capability (avc$network_applic_management, avc$user, network_application_management, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF NOT network_application_management THEN
      osp$set_status_abnormal (nac$status_id, nae$invalid_user, 'DISPLAY_OSI_ADDRESS', status);
      RETURN;
    IFEND;

    default_ring_attributes.r1 := #RING (^default_ring_attributes);
    default_ring_attributes.r2 := #RING (^default_ring_attributes);
    default_ring_attributes.r3 := #RING (^default_ring_attributes);
    clp$open_display_reference (pvt [p$output].value^.file_value^, ^generate_headers, fsc$list,
          default_ring_attributes, display_control, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    local_domain.kind := nac$local_system_domain;
    title := pvt [p$titles].value;
    WHILE title <> NIL DO
      CASE title^.element_value^.kind OF
      = clc$name =
        title_string := ^title^.element_value^.name_value;
        wild_card := FALSE;
      = clc$string =
        title_string := title^.element_value^.string_value;
        wild_card := FALSE;
      ELSE { = clc$keyword = }
        title_string := ^wild_card_title;
        wild_card := TRUE;
      CASEND;

      nlp$translate_title (title_string^, wild_card, nac$unknown_protocol, {recurrent_search=} FALSE,
            local_domain, nac$cdna_external, request_id, status);
      IF NOT status.normal THEN
        clp$close_display (display_control, {ignore} local_status);
        RETURN;
      IFEND;

      title_found := FALSE;

      REPEAT
        nlp$get_title_translation (request_id, title_value, address, protocol, ^user_information,
              user_info_length, priority, user_identifier, directory_identifier, local_status);
        IF local_status.normal AND ((address.kind = nac$osi_non_cdna_present_addr) OR
              (address.kind = nac$osi_non_cdna_session_addr)) THEN
          title_found := TRUE;
          STRINGREP (line, line_length, '   Title:                    ', title_value);
          clp$put_display (display_control, line (1, line_length), clc$trim, status);
          IF NOT status.normal THEN
            clp$close_display (display_control, {ignore} local_status);
            RETURN;
          IFEND;
          CASE address.kind OF
          = nac$osi_non_cdna_present_addr =
            line := '     Network_address: ';
            line_length := 30;
            network_address := ^address.osi_presentation_address.network_address;
            RESET network_address;
            NEXT network_address_value: [address.osi_presentation_address.network_address_length] IN
                  network_address;
            convert_string_to_hex_digits (network_address_value^, line, line_length);
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

            line := '     Transport_selector: ';
            line_length := 30;
            IF address.osi_presentation_address.transport_selector_length > 0 THEN
              convert_string_to_hex_digits (address.osi_presentation_address.
                    transport_selector (1, address.osi_presentation_address.transport_selector_length), line,
                    line_length);
            ELSE
              line (line_length, 4) := 'None';
              line_length := line_length + 4;
            IFEND;
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

            line := '     Session_selector: ';
            line_length := 30;
            IF address.osi_presentation_address.session_selector_length > 0 THEN
              convert_string_to_hex_digits (address.osi_presentation_address.
                    session_selector (1, address.osi_presentation_address.session_selector_length), line,
                    line_length);
            ELSE
              line (line_length, 4) := 'None';
              line_length := line_length + 4;
            IFEND;
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

            line := '     Presentation_selector: ';
            line_length := 30;
            IF address.osi_presentation_address.presentation_selector_length > 0 THEN
              convert_string_to_hex_digits (address.osi_presentation_address.
                    presentation_selector (1, address.osi_presentation_address.presentation_selector_length),
                    line, line_length);
            ELSE
              line (line_length, 4) := 'None';
              line_length := line_length + 4;
            IFEND;
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

          = nac$osi_non_cdna_session_addr =
            line := '     Network_address: ';
            line_length := 30;
            network_address := ^address.osi_session_address.network_address;
            RESET network_address;
            NEXT network_address_value: [address.osi_session_address.network_address_length] IN
                  network_address;
            convert_string_to_hex_digits (network_address_value^, line, line_length);
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

            line := '     Transport_selector: ';
            line_length := 30;
            IF address.osi_session_address.transport_selector_length > 0 THEN
              convert_string_to_hex_digits (address.osi_session_address.
                    transport_selector (1, address.osi_session_address.transport_selector_length), line,
                    line_length);
            ELSE
              line (line_length, 4) := 'None';
              line_length := line_length + 4;
            IFEND;
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

            line := '     Session_selector: ';
            line_length := 30;
            IF address.osi_session_address.session_selector_length > 0 THEN
              convert_string_to_hex_digits (address.osi_session_address.
                    session_selector (1, address.osi_session_address.session_selector_length), line,
                    line_length);
            ELSE
              line (line_length, 4) := 'None';
              line_length := line_length + 4;
            IFEND;
            clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);

          ELSE
          CASEND;

          clp$put_partial_display (display_control, '     Data:                   ', clc$no_trim, amc$start,
                {ignore} status);
          IF user_info_length > 0 THEN
            user_info := ^user_information;
            RESET user_info;
            NEXT user_information_value: [user_info_length] IN user_info;
            clp$put_partial_display (display_control, user_information_value^, clc$trim, amc$terminate,
                  {ignore} status);
          ELSE
            clp$put_partial_display (display_control, 'None', clc$trim, amc$terminate, {ignore} status);
          IFEND;
          STRINGREP (line, line_length, '     Priority:              ', priority);
          clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);
          STRINGREP (line, line_length, '     Title_identifier:       ', user_identifier);
          clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);
          transport_class := 4;
          network_service := ' Connection_oriented';
          CASE protocol OF
          = nac$non_cdna_osi_pres_tp0_cons =
            transport_class := 0;
          = nac$non_cdna_osi_pres_tp2_cons =
            transport_class := 2;
          = nac$non_cdna_osi_pres_tp4_cons =
            ;
          = nac$non_cdna_osi_sess_tp4_clns, nac$non_cdna_osi_pres_tp4_clns =
            network_service := ' Connection_less';
          CASEND;
          STRINGREP (line, line_length, '     Transport_class:       ', transport_class);
          clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);
          STRINGREP (line, line_length, '     Network_service:       ', network_service);
          clp$put_display (display_control, line (1, line_length), clc$trim, {ignore} status);
        IFEND;
      UNTIL NOT local_status.normal;

      nlp$end_title_translation (request_id, {ignore} local_status);
      IF NOT title_found THEN
        IF wild_card THEN
          osp$set_status_condition (nae$empty_osi_title_list, status);
        ELSE
          osp$set_status_abnormal (nac$status_id, nae$unknown_osi_title, title_string^, status);
        IFEND;
      IFEND;
      title := title^.link;
    WHILEND;

    clp$close_display (display_control, {ignore} local_status);

  PROCEND nap$display_osi_address;
?? OLDTITLE ??
?? NEWTITLE := 'generate_headers', EJECT ??

{ PURPOSE: This procedure formats a page header for DISOSIA output.
{ DESIGN:  This procedure is called by the clp$display... routines when a page header
{          is needed.

  PROCEDURE generate_headers
    (VAR display_control: {input,output} clt$display_control;
         page_number: integer;
     VAR status: ost$status);

    CONST
      date_length = 18,
      long_date_start = 91,
      long_header_length = 132,
      long_os_version_start = 48,
      long_page_number_start = 127, {includes leading blank}
      long_page_title_start = 123,
      long_product_level_start = 85,
      long_product_name_start = 55,
      long_product_version_start = 78,
      long_time_start = 110,
      os_version_length = 6,
      page_number_length = 5, {includes leading blank}
      product_name = 'DISPLAY OSI ADDRESSES',
      product_level_length = 5,
      product_name_length = 21,
      product_version_length = 4,
      short_date_start = 1,
      short_header_length = 80,
      short_os_version_start = 20,
      short_page_number_start = 66, {includes leading blank}
      short_page_title_start = 62,
      short_product_level_start = 57,
      short_product_name_start = 27,
      short_product_version_start = 52,
      short_time_start = 49,
      time_length = 12;

    VAR
      date: ost$date,
      date_line: 1 .. 2,
      date_start: 0 .. long_header_length,
      header: array [1 .. 2] of string (long_header_length),
      header1_length: 0 .. long_header_length,
      header2_length: 0 .. long_header_length,
      j: integer,
      os_version: pmt$os_name,
      page_number_start: 0 .. long_header_length,
      str: string (10),
      time: ost$time,
      time_line: 1 .. 2,
      time_start: 0 .. long_header_length;

    pmp$get_legible_date_time (osc$default_date, date, osc$default_time, time, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    pmp$get_os_version (os_version, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    header [1] := ' ';
    header [2] := ' ';
    IF (display_control.page_width < long_header_length) THEN
      header1_length := short_header_length;
      header2_length := short_header_length;
      page_number_start := short_page_number_start;
      header [2] (short_os_version_start, os_version_length) := os_version;
      date_line := 2;
      date_start := short_date_start;
      time_line := 1;
      time_start := short_time_start;
      header [2] (short_product_name_start, product_name_length) := product_name;
      header [2] (short_product_version_start, product_version_length) := command_version;
      header [2] (short_product_level_start, product_level_length) := command_level;
      header [1] (short_page_title_start, 4) := 'PAGE';
    ELSE
      header1_length := long_header_length;
      page_number_start := long_page_number_start;
      header [1] (long_os_version_start, os_version_length) := os_version;
      date_line := 1;
      date_start := long_date_start;
      time_line := 1;
      time_start := long_time_start;
      header [1] (long_product_name_start, product_name_length) := product_name;
      header [1] (long_product_version_start, product_version_length) := command_version;
      header [1] (long_product_level_start, product_level_length) := command_level;
      header [1] (long_page_title_start, 4) := 'PAGE';
      header2_length := 0;
    IFEND;

    CASE date.date_format OF
    = osc$month_date =
      header [date_line] (date_start, date_length) := date.month;

    = osc$mdy_date =
      header [date_line] (date_start, date_length) := date.mdy;

    = osc$iso_date =
      header [date_line] (date_start, date_length) := date.iso;

    = osc$dmy_date =
      header [date_line] (date_start, date_length) := date.dmy;

    ELSE
    CASEND;

    CASE time.time_format OF
    = osc$ampm_time =
      header [time_line] (time_start, time_length) := time.ampm;

    = osc$hms_time =
      header [time_line] (time_start, time_length) := time.hms;

    = osc$millisecond_time =
      header [time_line] (time_start, time_length) := time.millisecond;

    ELSE
    CASEND;
    clp$reset_for_next_display_page (display_control, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    STRINGREP (str, j, page_number);
    header [1] (page_number_start, j) := str (1, j);
    clp$put_display (display_control, header [1], clc$trim, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF (header2_length > 0) THEN
      clp$put_display (display_control, header [2], clc$trim, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    clp$new_display_line (display_control, 1, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND generate_headers;
?? OLDTITLE ??
MODEND nam$manage_non_cdna_addresses;
