?? LEFT := 1, RIGHT := 110 ??
MODULE nam$init_directive_processor;
?? NEWTITLE := 'NOS/VE: Initialization M-E Directive Processors' ??
{ PURPOSE: Process Initialization Management Entity directives.
{          These directives can be used to define what system
{          versions to load and what error codes should trigger a
{          dump. Values can be specified for specific systems and
{          for a global default.
{
{ DESIGN:  A command utility is established and the directive file
{          is read by SCL. Values for the system exception list are
{          reset based on the values given on DEFINE_EXCEPTION_SYSTEM
{          commands. Default object code version and dump error list
{          are updated based on the DEFINE_BOOT_DEFAULTS command.
{
?? PUSH (LISTEXT := ON) ??
*copyc nac$network_management_catalog
*copyc nae$initialization_me
*copyc clt$value
*copyc nat$init_me_directives
*copyc nat$object_code_version
*copyc ost$status
*copyc pft$cycle_selector
*copyc pft$name
*copyc pft$password
*copyc pft$share_selections
*copyc pft$usage_selections
?? POP ??
*copyc amp$return
*copyc clp$get_set_count
*copyc clp$get_value
*copyc clp$pop_utility
*copyc clp$push_utility
*copyc clp$scan_command_file
*copyc clp$scan_parameter_list
*copyc clp$test_parameter
*copyc osp$set_status_abnormal
*copyc pfp$attach
*copyc pmp$get_unique_name

  CONST
    system_address_prefix = 080025000000(16);

  TYPE
    linked_exception_entry = record
      link: ^linked_exception_entry,
      entry: nat$init_exception_entry,
    recend;

  VAR
    defaults_processed: boolean,
    first_system_entry: ^linked_exception_entry,
    initial_object_code_version: nat$object_code_version := LOWERVALUE (nat$object_code_version),
    initial_dump_error_list: nat$di_dump_error_list := -$nat$di_dump_error_list [nac$di_power_on_reset,
          nac$ica_channel_master_clear, nac$ica_reset_function, nac$di_reset_kils_no_dump,
          nac$di_reset_protocol_stk_chg, nac$mpb_ii_reset, nac$ac_power_low],
    dump_error_list: nat$di_dump_error_list,
    object_code_version: nat$object_code_version,
    system_count: integer;

?? EJECT ??

  PROCEDURE [XDCL] nap$process_init_directives (VAR system_exceptions: nat$init_exception_list;
    VAR default_object_code_version: nat$object_code_version;
    VAR default_dump_error_list: nat$di_dump_error_list;
    VAR status: ost$status);

{ table init_directives
{ command (define_boot_defaults,define_boot_default,defbd) p=define_boot_defaults
{ command (define_exception_system, defes) p=define_exception_system

?? PUSH (LISTEXT := ON) ??
VAR
  init_directives: [STATIC, READ] ^clt$command_table := ^init_directives_entries,

  init_directives_entries: [STATIC, READ] array [1 .. 5] of  clt$command_table_entry := [
  {} ['DEFBD                          ', clc$abbreviation_entry, clc$advertised_entry, 1,
        clc$automatically_log, clc$linked_call, ^define_boot_defaults],
  {} ['DEFES                          ', clc$abbreviation_entry, clc$advertised_entry, 2,
        clc$automatically_log, clc$linked_call, ^define_exception_system],
  {} ['DEFINE_BOOT_DEFAULT            ', clc$alias_entry, clc$advertised_entry, 1,
        clc$automatically_log, clc$linked_call, ^define_boot_defaults],
  {} ['DEFINE_BOOT_DEFAULTS           ', clc$nominal_entry, clc$advertised_entry, 1,
        clc$automatically_log, clc$linked_call, ^define_boot_defaults],
  {} ['DEFINE_EXCEPTION_SYSTEM        ', clc$nominal_entry, clc$advertised_entry, 2,
        clc$automatically_log, clc$linked_call, ^define_exception_system]];

?? POP ??

    VAR
      exception_file: [STATIC] array [1 .. 5] of pft$name := [nac$management_family,
        nac$management_master_catalog, nac$cdcnet_subcatalog, nac$site_controlled_subcatalog,
        nac$exception_list ],
      exception_file_name: amt$local_file_name,
      highest_cycle: [STATIC, READ] pft$cycle_selector := [pfc$highest_cycle],
      ignore_status: ost$status,
      index: integer,
      init_me_id: [STATIC] ost$name := 'INIT_M_E',
      next_system: ^linked_exception_entry,
      password: [STATIC, READ] pft$password := ' ',
      share_selections: [STATIC, READ] pft$share_selections := [pfc$read],
      system_entry: ^linked_exception_entry,
      usage_selections: [STATIC, READ] pft$usage_selections := [pfc$read];

    defaults_processed := FALSE;
    first_system_entry := NIL;
    system_count := 0;
    object_code_version := initial_object_code_version;
    dump_error_list := initial_dump_error_list;
    status.normal := TRUE;
    pmp$get_unique_name (exception_file_name, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pfp$attach (exception_file_name, exception_file, highest_cycle, password, usage_selections,
          share_selections, pfc$wait, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$push_utility (init_me_id, clc$restricted_command_search, init_directives, NIL, status);
    IF NOT status.normal THEN
      amp$return (exception_file_name, ignore_status);
      RETURN;
    IFEND;

    clp$scan_command_file (exception_file_name, init_me_id, 'IME', status);
    amp$return (exception_file_name, ignore_status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$pop_utility (status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF system_exceptions <> NIL THEN
      FREE system_exceptions;
    IFEND;

    IF system_count = 0 THEN
      system_exceptions := NIL;
    ELSE
      system_entry := first_system_entry;
      ALLOCATE system_exceptions: [1 .. system_count];
      FOR index := 1 TO system_count DO
        system_exceptions^ [index] := system_entry^.entry;
        next_system := system_entry^.link;
        FREE system_entry;
        system_entry := next_system;
      FOREND;
    IFEND;

    default_object_code_version := object_code_version;
    default_dump_error_list := dump_error_list;

  PROCEND nap$process_init_directives;
?? NEWTITLE := 'define_exception_system', EJECT ??

  PROCEDURE define_exception_system (parameter_list: clt$parameter_list;
    VAR status: ost$status);


{ PDT system_pdt (
{   system_id,si : integer 0 .. 0ffffff(16) = $REQUIRED
{   version_number,vn : integer 0 .. 0ffff(16)
{   service_system,ss : boolean = TRUE
{   delete_dump_on_error,ddoe : LIST RANGE OF integer 0 .. nac$max_di_reset_code
{   add_dump_on_error,adoe : LIST RANGE OF integer 0 .. nac$max_di_reset_code
{   transmit_rate,tr : integer 4800 .. 2000000 = 2000000
{   status)

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

  VAR
    system_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^system_pdt_names,
  ^system_pdt_params];

  VAR
    system_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 13] of
  clt$parameter_name_descriptor := [['SYSTEM_ID', 1], ['SI', 1], ['VERSION_NUMBER', 2], ['VN', 2], [
  'SERVICE_SYSTEM', 3], ['SS', 3], ['DELETE_DUMP_ON_ERROR', 4], ['DDOE', 4], ['ADD_DUMP_ON_ERROR', 5], ['ADOE'
  , 5], ['TRANSMIT_RATE', 6], ['TR', 6], ['STATUS', 7]];

  VAR
    system_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 7] of clt$parameter_descriptor := [

{ SYSTEM_ID SI }
    [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$integer_value, 0, 0ffffff(16)]],

{ VERSION_NUMBER VN }
    [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$integer_value, 0, 0ffff(16)]],

{ SERVICE_SYSTEM SS }
    [[clc$optional_with_default, ^system_pdt_dv3], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
  clc$boolean_value]],

{ DELETE_DUMP_ON_ERROR DDOE }
    [[clc$optional], 1, clc$max_value_sets,1, 1, clc$value_range_allowed, [NIL, clc$integer_value, 0,
  nac$max_di_reset_code]],

{ ADD_DUMP_ON_ERROR ADOE }
    [[clc$optional], 1, clc$max_value_sets,1, 1, clc$value_range_allowed, [NIL, clc$integer_value, 0,
  nac$max_di_reset_code]],

{ TRANSMIT_RATE TR }
    [[clc$optional_with_default, ^system_pdt_dv6], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
  clc$integer_value, 4800, 2000000]],

{ STATUS }
    [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$variable_reference,
  clc$array_not_allowed, clc$status_value]]];

  VAR
    system_pdt_dv3: [STATIC, READ, cls$pdt_names_and_defaults] string (4) := 'TRUE';

  VAR
    system_pdt_dv6: [STATIC, READ, cls$pdt_names_and_defaults] string (7) := '2000000';

?? FMT (FORMAT := ON) ??
?? POP ??
    VAR
      error_list_count: 0 .. clc$max_value_sets,
      high_value: clt$value,
      index: integer,
      low_value: clt$value,
      reset_code_index: 0 .. nac$max_di_reset_code,
      system_id: nat$system_identifier,
      system_entry: ^linked_exception_entry,
      value: clt$value;

    clp$scan_parameter_list (parameter_list, system_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF NOT defaults_processed THEN
      osp$set_status_abnormal (nac$status_id, nae$defaults_not_set_first, '', status);
      RETURN;
    IFEND;

    clp$get_value ('SYSTEM_ID', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    system_id := system_address_prefix + value.int.value;
    system_entry := first_system_entry;

  /find_system_entry/
    BEGIN
      WHILE system_entry <> NIL DO
        IF system_entry^.entry.system_id = system_id THEN
          EXIT /find_system_entry/;
        IFEND;
        system_entry := system_entry^.link;
      WHILEND;
      system_count := system_count + 1;
      ALLOCATE system_entry;
      system_entry^.link := first_system_entry;
      system_entry^.entry.system_id := system_id;
      system_entry^.entry.dump_error_list := dump_error_list;
      first_system_entry := system_entry;
    END /find_system_entry/;

    clp$get_value ('SERVICE_SYSTEM', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    system_entry^.entry.service_system := value.bool.value;

    clp$test_parameter ('VERSION_NUMBER', system_entry^.entry.version_specified, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF system_entry^.entry.version_specified THEN
      clp$get_value ('VERSION_NUMBER', 1, 1, clc$low, value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      system_entry^.entry.object_code_version := value.int.value;
    IFEND;

    clp$get_set_count ('DELETE_DUMP_ON_ERROR', error_list_count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    FOR index := 1 TO error_list_count DO
      clp$get_value ('DELETE_DUMP_ON_ERROR', index, 1, clc$low, low_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      clp$get_value ('DELETE_DUMP_ON_ERROR', index, 1, clc$high, high_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      FOR reset_code_index := low_value.int.value TO high_value.int.value DO
        system_entry^.entry.dump_error_list := system_entry^.entry.dump_error_list -
              $nat$di_dump_error_list [reset_code_index];
      FOREND;
    FOREND;

    clp$get_set_count ('ADD_DUMP_ON_ERROR', error_list_count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    FOR index := 1 TO error_list_count DO
      clp$get_value ('ADD_DUMP_ON_ERROR', index, 1, clc$low, low_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      clp$get_value ('ADD_DUMP_ON_ERROR', index, 1, clc$high, high_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      FOR reset_code_index := low_value.int.value TO high_value.int.value DO
        system_entry^.entry.dump_error_list := system_entry^.entry.dump_error_list +
              $nat$di_dump_error_list [reset_code_index];
      FOREND;
    FOREND;

    clp$get_value ('TRANSMIT_RATE', 1, 1, clc$low, value, status);
    IF  NOT status.normal THEN
       RETURN;
    IFEND;
    system_entry^.entry.transmit_rate := value.int.value;

  PROCEND define_exception_system;
?? OLDTITLE ??
?? NEWTITLE := 'define_boot_defaults', EJECT ??

  PROCEDURE define_boot_defaults (parameter_list: clt$parameter_list;
    VAR status: ost$status);

{ PDT init_defaults_pdt (
{   default_version,dv : integer 0 .. 0ffff(16) = $REQUIRED
{   delete_dump_on_error,ddoe: LIST RANGE OF integer 0 .. nac$max_di_reset_code
{   status)

?? PUSH (LISTEXT := ON) ??

  VAR
    init_defaults_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^init_defaults_pdt_names,
      ^init_defaults_pdt_params];

  VAR
    init_defaults_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 5] of
      clt$parameter_name_descriptor := [['DEFAULT_VERSION', 1], ['DV', 1], ['DELETE_DUMP_ON_ERROR', 2], [
      'DDOE', 2], ['STATUS', 3]];

  VAR
    init_defaults_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 3] of clt$parameter_descriptor
      := [

{ DEFAULT_VERSION DV }
    [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$integer_value, 0, 0ffff(16)]],

{ DELETE_DUMP_ON_ERROR DDOE }
    [[clc$optional], 1, clc$max_value_sets,1, 1, clc$value_range_allowed, [NIL, clc$integer_value, 0,
      nac$max_di_reset_code]],

{ STATUS }
    [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$variable_reference,
      clc$array_not_allowed, clc$status_value]]];

?? POP ??

    VAR
      error_list_count: 0 .. clc$max_value_sets,
      high_value: clt$value,
      index: 0 .. clc$max_value_sets,
      low_value: clt$value,
      reset_code_index: 0 .. nac$max_di_reset_code,
      value: clt$value;

    clp$scan_parameter_list (parameter_list, init_defaults_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF defaults_processed THEN
      osp$set_status_abnormal (nac$status_id, nae$defaults_set_twice, '', status);
      RETURN;
    IFEND;
    defaults_processed := TRUE;

    clp$get_value ('DEFAULT_VERSION', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    object_code_version := value.int.value;

    clp$get_set_count ('DELETE_DUMP_ON_ERROR', error_list_count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    FOR index := 1 TO error_list_count DO
      clp$get_value ('DELETE_DUMP_ON_ERROR', index, 1, clc$low, low_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      clp$get_value ('DELETE_DUMP_ON_ERROR', index, 1, clc$high, high_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      FOR reset_code_index := low_value.int.value TO high_value.int.value DO
        dump_error_list := dump_error_list - $nat$di_dump_error_list [reset_code_index];
      FOREND;
    FOREND;

  PROCEND define_boot_defaults;

MODEND nam$init_directive_processor;
