?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter : Command List Manager' ??
MODULE clm$command_list_manager;

{
{ PURPOSE:
{   This module contains the requests used to manage the command list at both the job and task levels.
{

?? NEWTITLE := 'Global Declarations' ??
?? NEWTITLE := 'Command List', EJECT ??
*copyc clt$command_list_info
?? OLDTITLE, EJECT ??
*IF NOT $true(osv$unix)
?? PUSH (LISTEXT := ON) ??
*copyc ame$lfn_program_actions
*IFEND
*copyc cle$ecc_command_processing
*IF NOT $true(osv$unix)
*copyc cle$ecc_control_statement
*copyc cle$ecc_file_reference
*copyc cle$ecc_miscellaneous
*copyc cle$ecc_utilities
*copyc clt$command_library_search_info
*IFEND
*copyc clt$command_list_entry_file
*IF NOT $true(osv$unix)
*copyc clt$command_processor
*copyc clt$command_table
*IFEND
*copyc clt$environment_object_contents
*copyc clt$environment_object_size
*IF NOT $true(osv$unix)
*copyc clt$env_object_pop_reason
*copyc clt$env_object_push_reason
*copyc clt$function_table
*copyc clt$scl_procedure
*copyc clt$when_conditions
*copyc clv$local_catalog_handle_name
*copyc fse$path_exception_conditions
*copyc lle$load_map_diagnostics
*copyc lle$loader_status_conditions
*copyc llt$object_library_header
*copyc llt$program_description
*copyc osc$volume_unavailable_cond
*copyc ose$heap_full_exceptions
*copyc oss$job_paged_literal
*copyc oss$task_private
*copyc ost$caller_identifier
*IFEND
*copyc ost$message_template_module
*IF NOT $true(osv$unix)
*copyc ost$name
*IFEND
*copyc ost$status
*IF NOT $true(osv$unix)
*copyc pfe$error_condition_codes
*copyc pmt$program_name
?? POP ??
*copyc clp$access_command_file
*copyc clp$check_name_for_path_handle
*copyc clp$close_executable_cmnd_file
*copyc clp$convert_file_ref_to_string
*copyc clp$convert_str_to_path_handle
*copyc clp$environment_object_in_block
*copyc clp$extract_msg_module_contents
*IFEND
*copyc clp$find_command_list
*copyc clp$find_current_block
*IF NOT $true(osv$unix)
*copyc clp$find_task_block
*copyc clp$find_utility_block
*copyc clp$pop_environment
*copyc clp$push_environment
*copyc clp$reverse_list
*copyc clp$search_dictionary_for_code
*copyc clp$search_dictionary_for_name
*IFEND
*copyc clp$search_module_for_code
*copyc clp$search_module_for_name
*IF NOT $true(osv$unix)
*copyc clp$trimmed_string_size
*copyc clv$processing_phase
*copyc fmp$process_pt_request
*copyc fsp$convert_fs_structure_to_pf
*copyc fsv$evaluated_file_reference
*copyc lop$find_command_in_program
*copyc lop$find_function_in_program
*copyc mmp$reverify_access
*copyc osp$append_status_file
*copyc osp$append_status_parameter
*copyc osp$establish_condition_handler
*copyc osp$find_natural_language
*copyc osp$get_condition_status
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$system_error
*copyc osp$verify_system_privilege
*copyc osv$lower_to_upper
*copyc osv$task_private_heap
*IFEND
*copyc osv$task_shared_heap
*IF NOT $true(osv$unix)
*copyc pmp$abort
*copyc pmp$continue_to_cause
*copyc pmp$convert_entry_point_to_cmnd
*copyc pmp$get_library_dictionaries
*copyc pmp$load_from_library
*copyc pmp$log
?? TITLE := 'clp$check_valid_catalog', EJECT ??
*copyc clp$check_valid_catalog
?? TITLE := 'Message Cache Definitions', EJECT ??
*copyc clt$message_cache
*ELSE
*copyc clt$message_cache
*copyc clt$block
*IFEND
?? TITLE := 'Global Variables', EJECT ??

  VAR
*IF NOT $true(osv$unix)
    clv$task_command_library_list: [XDCL, oss$task_private] ^clt$command_library_list_entry := NIL;
*ELSE
    clv$task_command_library_list: [XDCL] ^clt$command_library_list_entry := NIL;
*IFEND

  VAR
*IF NOT $true(osv$unix)
    clv$message_cache: [XDCL, oss$task_private] clt$message_cache := [0, * ];
*ELSE
    clv$message_cache: [XDCL] clt$message_cache := [0, * ];
*IFEND

  VAR
*IF NOT $true(osv$unix)
    osv$built_in_message_templates: [XDCL, READ, oss$job_paged_literal] ^ost$message_template_module := NIL;
*ELSE
    osv$built_in_message_templates: [XREF] ^ost$message_template_module;
*IFEND

?? TITLE := 'clp$eo_size_command_list', EJECT ??

  FUNCTION [XDCL] clp$eo_size_command_list: clt$environment_object_size;


    clp$eo_size_command_list := #SIZE (clt$command_list);

  FUNCEND clp$eo_size_command_list;
?? TITLE := 'clp$eo_init_command_list', EJECT ??

  PROCEDURE [XDCL] clp$eo_init_command_list
    (    object: ^clt$environment_object_contents);

    VAR
      command_list: ^clt$command_list;


    command_list := object;

    command_list^.search_mode := clc$global_command_search;
    command_list^.entries.first_entry := NIL;
    command_list^.entries.entry_after_fence := NIL;
    command_list^.entries.last_entry := NIL;
    command_list^.system_command_library_lfn := osc$null_name;
    command_list^.system_library_contains.commands := FALSE;
    command_list^.system_library_contains.functions := FALSE;
    command_list^.system_library_contains.help_modules := FALSE;
    command_list^.system_library_contains.message_modules := FALSE;
    command_list^.system_library_contains.panels := FALSE;
    command_list^.number_of_utilities_added := 0;
    command_list^.deletion_made := FALSE;

  PROCEND clp$eo_init_command_list;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$eo_push_command_list', EJECT ??

  PROCEDURE [XDCL] clp$eo_push_command_list
    (    push_reason: clt$env_object_push_reason;
         new_object: ^clt$environment_object_contents;
         new_object_in_current_task: boolean;
         pushed_object_in_current_task: boolean;
         pushed_object: ^clt$environment_object_contents;
     VAR status: ost$status);

    VAR
      block: ^clt$block,
      copy_entry: boolean,
      old_command_list: ^clt$command_list,
      old_entry: ^clt$command_list_entry,
      new_command_list: ^clt$command_list,
      new_entry: ^clt$command_list_entry,
      task_block: ^clt$block;


    status.normal := TRUE;

    new_command_list := new_object;
    old_command_list := pushed_object;

    new_command_list^.search_mode := old_command_list^.search_mode;
    new_command_list^.entries.first_entry := NIL;
    new_command_list^.entries.last_entry := NIL;
    new_command_list^.system_command_library_lfn := old_command_list^.system_command_library_lfn;
    new_command_list^.system_library_contains := old_command_list^.system_library_contains;
    new_command_list^.number_of_utilities_added := 0;
    new_command_list^.deletion_made := FALSE;

    IF old_command_list^.entries.first_entry = NIL THEN
      RETURN;
    IFEND;

    IF push_reason = clc$eo_push_requested THEN
      task_block := NIL;
    ELSE
      clp$find_task_block (task_block, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    old_entry := old_command_list^.entries.first_entry;
    REPEAT
      IF (old_entry^.kind <> clc$sub_commands) OR (task_block = NIL) THEN
        copy_entry := TRUE;
      ELSE
        block := task_block;
        WHILE (block <> NIL) AND (block^.kind <> clc$utility_block) AND
              (#OFFSET (^block^.command_environment) <> #OFFSET (old_entry^.utility_info)) DO
          block := block^.previous_block;
        WHILEND;
        copy_entry := block <> NIL;
      IFEND;

      IF copy_entry THEN
        ALLOCATE new_entry IN osv$task_shared_heap^;
        new_entry^ := old_entry^;
        new_entry^.next_entry := NIL;
        IF new_command_list^.entries.first_entry = NIL THEN
          new_command_list^.entries.first_entry := new_entry;
        ELSE
          new_command_list^.entries.last_entry^.next_entry := new_entry;
        IFEND;
        new_command_list^.entries.last_entry := new_entry;
      IFEND;

      old_entry := old_entry^.next_entry;
    UNTIL old_entry = NIL;

    establish_fence (new_command_list^.search_mode, new_command_list^.entries.first_entry,
          new_command_list^.entries.entry_after_fence);

  PROCEND clp$eo_push_command_list;
?? TITLE := 'clp$eo_pop_command_list', EJECT ??

  PROCEDURE [XDCL] clp$eo_pop_command_list
    (    pop_reason: clt$env_object_pop_reason;
         object: ^clt$environment_object_contents;
         object_in_current_task: boolean;
         pushed_object_in_current_task: boolean;
         pushed_object: ^clt$environment_object_contents;
     VAR status: ost$status);

    VAR
      command_list: ^clt$command_list,
      current_entry: ^clt$command_list_entry,
      next_entry: ^clt$command_list_entry;


    status.normal := TRUE;

    command_list := object;

    IF (pop_reason = clc$eo_pop_requested) AND (command_list^.number_of_utilities_added > 0) THEN
      osp$set_status_condition (cle$cannot_pop_command_list, status);
      RETURN;
    ELSEIF command_list^.entries.first_entry = NIL THEN
      RETURN;
    IFEND;

    current_entry := command_list^.entries.first_entry;
    REPEAT
      next_entry := current_entry^.next_entry;
      FREE current_entry IN osv$task_shared_heap^;
      current_entry := next_entry;
    UNTIL current_entry = NIL;

    IF (pushed_object <> NIL) AND ((pop_reason = clc$eo_pop_requested) OR (pop_reason = clc$eo_pop_for_block))
          THEN
      command_list := pushed_object;
      update_command_list (FALSE, command_list, pushed_object_in_current_task, status);
    IFEND;

  PROCEND clp$eo_pop_command_list;
?? TITLE := 'clp$eo_updt_command_list', EJECT ??

  PROCEDURE [XDCL] clp$eo_updt_command_list
    (    synchronous_with_parent: boolean;
         synchronous_with_job: boolean;
         current_object: ^clt$environment_object_contents;
         current_object_in_current_task: boolean;
     VAR status: ost$status);

    VAR
      command_list: ^clt$command_list;


    status.normal := TRUE;

    IF synchronous_with_parent THEN
      command_list := current_object;
      update_command_list (TRUE, command_list, current_object_in_current_task, status);
    IFEND;

  PROCEND clp$eo_updt_command_list;
*IFEND
?? TITLE := 'establish_fence', EJECT ??

  PROCEDURE establish_fence
    (    search_mode: clt$command_search_modes;
         first_entry: ^clt$command_list_entry;
     VAR entry_after_fence: ^clt$command_list_entry);

    VAR
      utility_entry: ^clt$command_list_entry;


    entry_after_fence := first_entry;
    utility_entry := NIL;

    WHILE entry_after_fence <> NIL DO
      CASE entry_after_fence^.kind OF

      = clc$command_list_fence =
        entry_after_fence := entry_after_fence^.next_entry;
        RETURN;

      = clc$sub_commands =
        IF search_mode <> entry_after_fence^.utility_info^.previous_search_mode THEN
          entry_after_fence := entry_after_fence^.next_entry;
          RETURN;
        ELSEIF utility_entry = NIL THEN
          utility_entry := entry_after_fence;
        IFEND;

      ELSE
        ;
      CASEND;

      entry_after_fence := entry_after_fence^.next_entry;
    WHILEND;

    IF utility_entry <> NIL THEN
      entry_after_fence := utility_entry^.next_entry;
    ELSEIF first_entry <> NIL THEN
      entry_after_fence := first_entry^.next_entry;
    IFEND;

  PROCEND establish_fence;
*IF NOT $true(osv$unix)
?? TITLE := 'externalize_path_handle_name', EJECT ??

  PROCEDURE externalize_path_handle_name
    (    path_handle_name: fst$path_handle_name);

    VAR
      cl_path_handle: clt$path_handle,
      evaluated_file_reference: fst$evaluated_file_reference,
      ignore_cycle_description: ^fmt$cycle_description,
      ignore_process_pt_results: bat$process_pt_results,
      ignore_status: ost$status;


    clp$check_name_for_path_handle (path_handle_name, cl_path_handle);
    evaluated_file_reference := fsv$evaluated_file_reference;
    evaluated_file_reference.path_handle_info.path_handle_present := TRUE;
    evaluated_file_reference.path_handle_info.path_handle := cl_path_handle.regular_handle;
    fmp$process_pt_request ($bat$process_pt_work_list [bac$externalize_path_handle],
          {local_file_name=} osc$null_name, evaluated_file_reference, ignore_cycle_description,
          ignore_process_pt_results, ignore_status);

  PROCEND externalize_path_handle_name;
?? TITLE := 'clp$set_job_command_search_mode', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$set_job_command_search_mode
    (    search_mode: clt$command_search_modes;
     VAR status: ost$status);

    VAR
      block: ^clt$block,
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      ignore_cmnd_list_found_in_task: boolean,
      utility_block: ^clt$block,
      utility_block_in_current_task: boolean;


    status.normal := TRUE;

    IF (search_mode < LOWERVALUE (clt$command_search_modes)) OR
          (search_mode > UPPERVALUE (clt$command_search_modes)) THEN
      osp$set_status_abnormal ('CL', cle$unexpected_call_to, 'clp$set_job_command_search_mode', status);
      RETURN;
    IFEND;

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    clp$find_current_block (block);

    IF (caller_id.ring > osc$tsrv_ring) AND (block^.previous_block <> NIL) AND
          block^.previous_block^.use_command_search_mode THEN
      CASE command_list^.search_mode OF
      = clc$exclusive_command_search =
        osp$set_status_abnormal ('CL', cle$exclusve_mode_excludes_cmnd, '', status);
        RETURN;
      = clc$restricted_command_search =
        clp$find_utility_block (osc$null_name, utility_block, utility_block_in_current_task);
        IF (utility_block <> NIL) AND (utility_block_in_current_task OR
              utility_block^.command_environment.command_level) THEN
          osp$set_status_abnormal ('CL', cle$cannot_change_search_mode, '', status);
          RETURN;
        IFEND;
      ELSE {clc$global_command_search}
        ;
      CASEND;
    IFEND;

{ Change the search mode.

    command_list^.search_mode := search_mode;

{ Mark blocks so that the change takes effect for the requester.

    WHILE block <> NIL DO
      block^.use_command_search_mode := TRUE;
      CASE block^.kind OF
      = clc$command_proc_block, clc$function_proc_block, clc$utility_block =
        RETURN;
      = clc$task_block =
        IF NOT block^.synchronous_with_parent THEN
          RETURN;
        IFEND;
      ELSE
        ;
      CASEND;
      block := block^.previous_block;
    WHILEND;

  PROCEND clp$set_job_command_search_mode;
*IFEND
?? TITLE := 'clp$add_utility_to_command_list', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$add_utility_to_command_list
    (    utility_block: ^clt$block;
     VAR status: ost$status);

    VAR
      command_list: ^clt$command_list,
      ignore_cmnd_list_found_in_task: boolean,
      new_entry: ^clt$command_list_entry;


    status.normal := TRUE;

    ALLOCATE new_entry IN osv$task_shared_heap^;

    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);

    new_entry^.next_entry := command_list^.entries.first_entry;
    new_entry^.kind := clc$sub_commands;
    new_entry^.utility_name := utility_block^.label;
    new_entry^.utility_info := ^utility_block^.command_environment;
    new_entry^.utility_info^.previous_search_mode := command_list^.search_mode;

    command_list^.number_of_utilities_added := command_list^.number_of_utilities_added + 1;

{
{  The statement below ensures that the utility does not expand the search
{  mode, e.g. if it was restricted, it cannot be made global.
{  The code takes advantage of the fact that order of the elements of
{  the ordinal type clt$command_search_modes is: global, restricted,
{  exclusive.
{

    IF command_list^.search_mode <= utility_block^.command_search_mode THEN
      command_list^.search_mode := utility_block^.command_search_mode;
    IFEND;

    command_list^.entries.first_entry := new_entry;
    IF command_list^.entries.last_entry = NIL THEN
      command_list^.entries.last_entry := new_entry;
    IFEND;

    establish_fence (command_list^.search_mode, command_list^.entries.first_entry,
          command_list^.entries.entry_after_fence);

  PROCEND clp$add_utility_to_command_list;
?? TITLE := 'clp$delete_util_from_cmnd_list', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$delete_util_from_cmnd_list
    (    utility_block: ^clt$block;
     VAR status: ost$status);

    VAR
      auxiliary_libraries: ^clt$utility_auxiliary_libraries,
      command_list: ^clt$command_list,
      ignore_cmnd_list_found_in_task: boolean,
      index: integer,
      libraries: ^array [1 .. * ] of fst$path_handle_name,
      local_status: ost$status,
      previous_entry: ^clt$command_list_entry,
      old_entry: ^clt$command_list_entry;


    status.normal := TRUE;

    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    previous_entry := NIL;
    old_entry := command_list^.entries.first_entry;

  /find_entry/
    WHILE old_entry <> NIL DO
      IF (old_entry^.kind = clc$sub_commands) AND (#OFFSET (^utility_block^.command_environment) =
            #OFFSET (old_entry^.utility_info)) THEN
        EXIT /find_entry/;
      IFEND;
      previous_entry := old_entry;
      old_entry := old_entry^.next_entry;
    WHILEND /find_entry/;

    IF old_entry <> NIL THEN
      IF old_entry = command_list^.entries.last_entry THEN
        command_list^.entries.last_entry := previous_entry;
      IFEND;

      IF old_entry = command_list^.entries.first_entry THEN
        command_list^.entries.first_entry := old_entry^.next_entry;
      ELSE
        previous_entry^.next_entry := old_entry^.next_entry;
      IFEND;

      FREE old_entry IN osv$task_shared_heap^;

      libraries := utility_block^.command_environment.libraries;
      utility_block^.command_environment.libraries := NIL;
      auxiliary_libraries := utility_block^.command_environment.auxiliary_libraries;
      utility_block^.command_environment.auxiliary_libraries := NIL;

      IF libraries <> NIL THEN
        FOR index := 1 TO UPPERBOUND (libraries^) DO
*IF NOT $true(osv$unix)
          clp$close_command_library (libraries^ [index], local_status);
          IF (NOT local_status.normal) AND status.normal THEN
            status := local_status;
          IFEND;
*IFEND
        FOREND;
        FREE libraries IN osv$task_shared_heap^;
      IFEND;

      IF auxiliary_libraries <> NIL THEN
        FOR index := 1 TO UPPERBOUND (auxiliary_libraries^) DO
*IF NOT $true(osv$unix)
          clp$close_command_library (auxiliary_libraries^ [index].name, local_status);
          IF (NOT local_status.normal) AND status.normal THEN
            status := local_status;
          IFEND;
*IFEND
        FOREND;
        FREE auxiliary_libraries IN osv$task_shared_heap^;
      IFEND;

      command_list^.search_mode := utility_block^.command_environment.previous_search_mode;
      IF command_list^.number_of_utilities_added > 0 THEN
        command_list^.number_of_utilities_added := command_list^.number_of_utilities_added - 1;
      IFEND;

      establish_fence (command_list^.search_mode, command_list^.entries.first_entry,
            command_list^.entries.entry_after_fence);

    IFEND;

  PROCEND clp$delete_util_from_cmnd_list;
?? TITLE := 'clp$add_file_to_command_list', EJECT ??
*copy clh$add_file_to_command_list

  PROCEDURE [XDCL, #GATE] clp$add_file_to_command_list
    (    entry: clt$command_list_entry_file;
         append: boolean;
     VAR status: ost$status);

    VAR
      block: ^clt$block,
*IF NOT $true(osv$unix)
      caller_id: ost$caller_identifier,
      evaluated_file_reference: fst$evaluated_file_reference,
*IFEND
      ignore_cmnd_list_found_in_task: boolean,
      library_list_entry: ^clt$command_library_list_entry,
      local_file_name: fst$path_handle_name,
      command_list: ^clt$command_list,
      new_entry: ^clt$command_list_entry,
      new_entry_kind: clt$command_list_entry_kind,
*IF NOT $true(osv$unix)
      path_handle: clt$path_handle,
      path_handle_name: amt$local_file_name,
      pf_path: ^pft$path;
*ELSE
      path_handle_name: amt$local_file_name;
*IFEND


*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
    caller_id.ring := osc$user_ring;
*IFEND
    status.normal := TRUE;
    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    clp$find_current_block (block);

*IF NOT $true(osv$unix)
    IF (caller_id.ring > osc$tsrv_ring) AND (block^.previous_block <> NIL) AND
          block^.previous_block^.use_command_search_mode THEN
      CASE command_list^.search_mode OF
      = clc$exclusive_command_search =
        osp$set_status_abnormal ('CL', cle$exclusve_mode_excludes_cmnd, '', status);
        RETURN;
      = clc$restricted_command_search =
        osp$set_status_abnormal ('CL', cle$restricted_mode_cmnd_change, '', status);
        RETURN;
      ELSE {clc$global_command_search}
        ;
      CASEND;
    IFEND;
*IFEND

    CASE entry.kind OF
    = clc$command_list_entry_$system =
      new_entry_kind := clc$system_commands;
*IF NOT $true(osv$unix)
    = clc$command_list_entry_fence =
      new_entry_kind := clc$command_list_fence;
    ELSE {clc$command_list_entry_path}
      IF entry.path^ = ':$WORKING_CATALOG' THEN
        new_entry_kind := clc$working_catalog_commands
      ELSEIF (entry.path^ = ':$LOCAL') OR (entry.path^ = clv$local_catalog_handle_name) THEN
        new_entry_kind := clc$catalog_commands;
        local_file_name := clv$local_catalog_handle_name;
      ELSE
        clp$convert_str_to_path_handle (entry.path^, FALSE, FALSE, FALSE, path_handle_name,
              evaluated_file_reference, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        clp$open_command_library (caller_id.ring, path_handle_name, library_list_entry, local_file_name,
              status);
        IF status.normal THEN
          new_entry_kind := clc$library_commands;
        ELSEIF (status.condition <> pfe$path_too_short) AND (status.condition <> pfe$name_not_permanent_file)
                THEN
          RETURN;
        ELSE
          local_file_name := path_handle_name;
          PUSH pf_path: [1 .. evaluated_file_reference.number_of_path_elements];
          fsp$convert_fs_structure_to_pf (evaluated_file_reference, pf_path);
          clp$check_valid_catalog (pf_path^, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF evaluated_file_reference.cycle_reference.specification <> fsc$cycle_omitted THEN
            osp$set_status_abnormal ('CL', fse$catalogs_do_not_have_cycles, '', status);
            osp$append_status_file (osc$status_parameter_delimiter, entry.path^, status);
            RETURN;
          IFEND;
          IF evaluated_file_reference.path_handle_info.path_handle.open_position.specified THEN
            osp$set_status_abnormal ('CL', cle$file_position_not_allowed, '', status);
            RETURN;
          IFEND;
          new_entry_kind := clc$catalog_commands;
        IFEND;
      IFEND;
*IFEND
    CASEND;

    new_entry := command_list^.entries.first_entry;
    WHILE new_entry <> NIL DO
      IF new_entry^.kind = new_entry_kind THEN
        CASE new_entry_kind OF
*IF NOT $true(osv$unix)
        = clc$catalog_commands, clc$library_commands =
          IF new_entry^.local_file_name = local_file_name THEN
            osp$set_status_abnormal ('CL', cle$duplicate_command_list_ent, local_file_name, status);
            RETURN;
          IFEND;
        = clc$working_catalog_commands =
          osp$set_status_abnormal ('CL', cle$duplicate_work_cat_entry, '', status);
          RETURN;
        = clc$command_list_fence =
          osp$set_status_abnormal ('CL', cle$duplicate_fence_entry, '', status);
          RETURN;
        ELSE {clc$system_commands}
*ELSE
        = clc$system_commands =
*IFEND
          osp$set_status_abnormal ('CL', cle$duplicate_$system_entry, '', status);
          RETURN;
        CASEND;
      IFEND;
      new_entry := new_entry^.next_entry;
    WHILEND;

    ALLOCATE new_entry IN osv$task_shared_heap^;

    IF append THEN

{ Add new entry to end of list.

      new_entry^.next_entry := NIL;
      IF command_list^.entries.last_entry <> NIL THEN
        command_list^.entries.last_entry^.next_entry := new_entry;
      ELSE
        command_list^.entries.first_entry := new_entry;
      IFEND;
      command_list^.entries.last_entry := new_entry;

    ELSE

{ Add new entry to front of list.

      new_entry^.next_entry := command_list^.entries.first_entry;
      command_list^.entries.first_entry := new_entry;
      IF command_list^.entries.last_entry = NIL THEN
        command_list^.entries.last_entry := new_entry;
      IFEND;

    IFEND;

    new_entry^.kind := new_entry_kind;
    CASE new_entry_kind OF

*IF NOT $true(osv$unix)
    = clc$catalog_commands =
      new_entry^.local_file_name := local_file_name;
      new_entry^.unaccessible_entry := FALSE;

    = clc$library_commands =

{ Externalize the path_handle_name for the case where the command_library is
{ added in a child task, and left in the library list.  If the path_handle_name
{ is not externalized, it will disappear when the task ends and the library is closed.

      externalize_path_handle_name (local_file_name);
      new_entry^.local_file_name := local_file_name;

      initialize_library_contains (library_list_entry, new_entry^.library_contains);

      new_entry^.unaccessible_entry := FALSE;
      clv$message_cache.count := 0;

*IFEND
    = clc$system_commands =
      clv$message_cache.count := 0;

    ELSE
      ;
    CASEND;

    establish_fence (command_list^.search_mode, command_list^.entries.first_entry,
          command_list^.entries.entry_after_fence);

  PROCEND clp$add_file_to_command_list;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$delete_file_from_cmnd_list', EJECT ??
*copy clh$delete_file_from_cmnd_list

  PROCEDURE [XDCL, #GATE] clp$delete_file_from_cmnd_list
    (    entry: clt$command_list_entry_file;
     VAR status: ost$status);

    CONST
      fence = 'FENCE',
      system = '$SYSTEM',
      system_user = ':' CAT system CAT '.' CAT system,
      working_catalog = ':$WORKING_CATALOG';

    VAR
      block: ^clt$block,
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      done: boolean,
      first_time: boolean,
      original_file_name: fst$path_handle_name,
      local_file_name: fst$path_handle_name,
      path: fst$path,
      path_size: fst$path_size,
      evaluated_file_reference: fst$evaluated_file_reference,
      cmnd_list_found_in_current_task: boolean,
      previous_entry: ^clt$command_list_entry,
      old_entry: ^clt$command_list_entry,
      local_status: ost$status;


    first_time := FALSE;
    status.normal := TRUE;
*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    clp$find_command_list (command_list, cmnd_list_found_in_current_task);
    clp$find_current_block (block);

    IF (caller_id.ring > osc$tsrv_ring) AND (block^.previous_block <> NIL) AND
          block^.previous_block^.use_command_search_mode THEN
      CASE command_list^.search_mode OF
      = clc$exclusive_command_search =
        osp$set_status_abnormal ('CL', cle$exclusve_mode_excludes_cmnd, '', status);
        RETURN;
      = clc$restricted_command_search =
        osp$set_status_abnormal ('CL', cle$restricted_mode_cmnd_change, '', status);
        RETURN;
      ELSE {clc$global_command_search}
        ;
      CASEND;
    IFEND;

    IF entry.kind = clc$command_list_entry_$system THEN
      local_file_name := system;
    ELSEIF entry.kind = clc$command_list_entry_fence THEN
      local_file_name := fence;
    ELSEIF entry.path^ = working_catalog THEN
      local_file_name := working_catalog;
    ELSE
      clp$convert_str_to_path_handle (entry.path^, FALSE, TRUE, FALSE, local_file_name,
            evaluated_file_reference, status);
      first_time := TRUE;

      IF NOT status.normal THEN

{ If a problem comes up with obsolete path handle names in the command list, then STATUS
{ should be checked for CLE$SYSTEM_ERROR, and if true, set LOCAL_FILE_NAME = ENTRY.NAME^,
{ PATH = ' ', PATH_SIZE = 1, and STATUS.NORMAL = TRUE

        RETURN;
      ELSE
        clp$convert_file_ref_to_string (evaluated_file_reference, FALSE, path, path_size, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;
    IFEND;
    original_file_name := local_file_name;

    REPEAT
      done := TRUE;
      previous_entry := NIL;
      old_entry := command_list^.entries.first_entry;

    /find_entry/
      WHILE old_entry <> NIL DO
        CASE old_entry^.kind OF
        = clc$library_commands, clc$catalog_commands =
          IF old_entry^.local_file_name = local_file_name THEN
            EXIT /find_entry/;
          IFEND;
        = clc$working_catalog_commands =
          IF local_file_name = working_catalog THEN
            EXIT /find_entry/;
          IFEND;
        = clc$system_commands =
          IF (local_file_name = system) OR (path (1, path_size) = system_user) THEN
            EXIT /find_entry/;
          IFEND;
        = clc$command_list_fence =
          IF local_file_name = fence THEN
            EXIT /find_entry/;
          IFEND;
        ELSE
          ;
        CASEND;
        previous_entry := old_entry;
        old_entry := old_entry^.next_entry;
      WHILEND /find_entry/;
      IF (old_entry = NIL) AND (first_time) THEN
        clp$convert_str_to_path_handle (entry.path^, FALSE, FALSE, FALSE, local_file_name,
              evaluated_file_reference, status);
        first_time := FALSE;
        done := FALSE;
      IFEND;
    UNTIL done;

    IF old_entry = NIL THEN
      local_file_name := original_file_name;
      IF (local_file_name = system) OR (path (1, path_size) = system_user) THEN
        osp$set_status_abnormal ('CL', cle$entry_not_in_command_list, system, status);
      ELSEIF (local_file_name = fence) OR (local_file_name = working_catalog) THEN
        osp$set_status_abnormal ('CL', cle$entry_not_in_command_list, local_file_name, status);
      ELSE
        osp$set_status_abnormal ('CL', cle$not_in_command_list, local_file_name, status);
      IFEND;
      RETURN;
    IFEND;

    IF old_entry = command_list^.entries.last_entry THEN
      command_list^.entries.last_entry := previous_entry;
    IFEND;

    IF old_entry = command_list^.entries.first_entry THEN
      command_list^.entries.first_entry := old_entry^.next_entry;
    ELSE
      previous_entry^.next_entry := old_entry^.next_entry;
    IFEND;

    CASE old_entry^.kind OF
    = clc$library_commands =
      clp$close_command_library (old_entry^.local_file_name, status);
      clv$message_cache.count := 0;
    = clc$system_commands =
      clv$message_cache.count := 0;
    ELSE
      ;
    CASEND;

    FREE old_entry IN osv$task_shared_heap^;

    IF NOT cmnd_list_found_in_current_task THEN
      command_list^.deletion_made := TRUE;
    IFEND;

    establish_fence (command_list^.search_mode, command_list^.entries.first_entry,
          command_list^.entries.entry_after_fence);

  PROCEND clp$delete_file_from_cmnd_list;
?? TITLE := 'clp$delete_all_from_cmnd_list', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$delete_all_from_cmnd_list
    (VAR status: ost$status);

    VAR
      block: ^clt$block,
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      cmnd_list_found_in_current_task: boolean,
      free_old_entry: boolean,
      next_entry: ^clt$command_list_entry,
      old_entry: ^clt$command_list_entry,
      local_status: ost$status;


    status.normal := TRUE;
*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    clp$find_command_list (command_list, cmnd_list_found_in_current_task);
    clp$find_current_block (block);

    IF (caller_id.ring > osc$tsrv_ring) AND (block^.previous_block <> NIL) AND
          block^.previous_block^.use_command_search_mode THEN
      CASE command_list^.search_mode OF
      = clc$exclusive_command_search =
        osp$set_status_abnormal ('CL', cle$exclusve_mode_excludes_cmnd, '', status);
        RETURN;
      = clc$restricted_command_search =
        osp$set_status_abnormal ('CL', cle$restricted_mode_cmnd_change, '', status);
        RETURN;
      ELSE
        ;
      CASEND;
    IFEND;

    old_entry := command_list^.entries.first_entry;
    command_list^.entries.first_entry := NIL;
    command_list^.entries.last_entry := NIL;

    WHILE old_entry <> NIL DO
      next_entry := old_entry^.next_entry;
      free_old_entry := TRUE;
      CASE old_entry^.kind OF
      = clc$library_commands =
        clp$close_command_library (old_entry^.local_file_name, local_status);
        IF status.normal AND (NOT local_status.normal) THEN
          status := local_status;
        IFEND;
        clv$message_cache.count := 0;
      = clc$system_commands =
        clv$message_cache.count := 0;
      = clc$sub_commands =
        old_entry^.next_entry := NIL;
        IF command_list^.entries.first_entry = NIL THEN
          command_list^.entries.first_entry := old_entry;
        ELSE
          command_list^.entries.last_entry^.next_entry := old_entry;
        IFEND;
        command_list^.entries.last_entry := old_entry;
        free_old_entry := FALSE;
      ELSE
        ;
      CASEND;
      IF free_old_entry THEN
        FREE old_entry IN osv$task_shared_heap^;
      IFEND;
      old_entry := next_entry;
    WHILEND;

    IF NOT cmnd_list_found_in_current_task THEN
      command_list^.deletion_made := TRUE;
    IFEND;

    IF command_list^.entries.first_entry <> NIL THEN
      osp$set_status_abnormal ('CL', cle$utility_left_in_cmnd_list, '', status);
    IFEND;

    establish_fence (command_list^.search_mode, command_list^.entries.first_entry,
          command_list^.entries.entry_after_fence);

  PROCEND clp$delete_all_from_cmnd_list;
?? TITLE := 'clp$establish_sys_command_lib', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$establish_sys_command_lib
    (    file: ^fst$file_reference;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      cmnd_list_found_in_current_task: boolean,
      evaluated_file_reference: fst$evaluated_file_reference,
      library_list_entry: ^clt$command_library_list_entry,
      path_handle_name: amt$local_file_name,
      previous_system_command_library: amt$local_file_name,
      validated_file_name: fst$path_handle_name,
      local_status: ost$status;


*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    status.normal := TRUE;

    clp$find_command_list (command_list, cmnd_list_found_in_current_task);

    previous_system_command_library := command_list^.system_command_library_lfn;

    IF (file <> NIL) AND (file^ = previous_system_command_library) THEN
      RETURN;
    IFEND;

    command_list^.system_command_library_lfn := osc$null_name;
    clv$message_cache.count := 0;

    IF previous_system_command_library <> osc$null_name THEN
      clp$close_command_library (previous_system_command_library, status);

      IF NOT cmnd_list_found_in_current_task THEN
        command_list^.deletion_made := TRUE;
      IFEND;

      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    IF file = NIL THEN
      RETURN;
    IFEND;

    clp$convert_str_to_path_handle (file^, FALSE, FALSE, FALSE, path_handle_name, evaluated_file_reference,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$open_command_library (caller_id.ring, path_handle_name, library_list_entry, validated_file_name,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Externalize the path_handle_name for the case where the command_library is
{ added in a child task, and left in the library list.  If the path_handle_name
{ is not externalized, it will disappear when the task ends and the library is closed.

    externalize_path_handle_name (validated_file_name);
    command_list^.system_command_library_lfn := validated_file_name;

    initialize_library_contains (library_list_entry, command_list^.system_library_contains);

  PROCEND clp$establish_sys_command_lib;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$get_system_message_mod_ptr', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$get_system_message_mod_ptr
    (VAR message_template: ^ost$message_template_module);

    osp$verify_system_privilege;
    message_template := osv$built_in_message_templates;

  PROCEND clp$get_system_message_mod_ptr;
*IFEND
?? TITLE := 'clp$push_dynamic_command_list', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$push_dynamic_command_list
    (VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      command_block: ^clt$block,
      command_list: ^clt$command_list,
      command_list_entry: ^clt$command_list_entry,
      ignore_cmnd_list_found_in_task: boolean,
      ignore_file_name: fst$path_handle_name,
      ignore_status: ^ost$status,
      library_list_entry: ^clt$command_library_list_entry,
      previous_entry: ^clt$command_list_entry;


    status.normal := TRUE;

    clp$find_current_block (command_block);

  /search/
    WHILE command_block <> NIL DO
      CASE command_block^.kind OF
      = clc$command_block =
        CASE command_block^.command_kind OF
        = clc$command_is_include_file, clc$command_is_include_line =
          ;
        ELSE
          EXIT /search/;
        CASEND;
      = clc$command_proc_block, clc$function_proc_block =
        EXIT /search/;
      = clc$task_block =
        IF NOT command_block^.synchronous_with_parent THEN
          command_block := NIL;
          EXIT /search/;
        IFEND;
      ELSE
        ;
      CASEND;
      command_block := command_block^.previous_block;
    WHILEND /search/;

    IF command_block = NIL THEN
      osp$set_status_abnormal ('CL', cle$unexpected_call_to, 'PUSH_COMMANDS', status);
      RETURN;
    ELSEIF command_block^.source.kind = clc$sub_commands THEN
      osp$set_status_abnormal ('CL', cle$cannot_move_utility_entry, '', status);
      RETURN;
    IFEND;

    clp$push_environment (clc$command_list, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);

    previous_entry := NIL;
    command_list_entry := command_list^.entries.first_entry;

  /find_entry/
    WHILE command_list_entry <> NIL DO
      IF command_list_entry^.kind = command_block^.source.kind THEN
        CASE command_list_entry^.kind OF
        = clc$catalog_commands, clc$library_commands =
          IF command_list_entry^.local_file_name = command_block^.source.local_file_name THEN
            EXIT /find_entry/;
          IFEND;
        = clc$system_commands, clc$working_catalog_commands =
          EXIT /find_entry/;
        ELSE
          ;
        CASEND;
      IFEND;
      previous_entry := command_list_entry;
      command_list_entry := command_list_entry^.next_entry;
    WHILEND /find_entry/;

  /create_new_entry/
    BEGIN
      IF command_list_entry <> NIL THEN
        IF command_list_entry = command_list^.entries.first_entry THEN
          EXIT /create_new_entry/;
        ELSE
          previous_entry^.next_entry := command_list_entry^.next_entry;
          IF command_list_entry = command_list^.entries.last_entry THEN
            command_list^.entries.last_entry := previous_entry;
          IFEND;
        IFEND;
      ELSE
        IF command_block^.source.kind = clc$library_commands THEN
*IF NOT $true(osv$unix)
          #CALLER_ID (caller_id);
*ELSE
          caller_id.ring := osc$user_ring;
*IFEND
          clp$open_command_library (caller_id.ring, command_block^.source.local_file_name, library_list_entry,
                ignore_file_name, status);
          IF NOT status.normal THEN
            PUSH ignore_status;
            clp$pop_environment (clc$command_list, ignore_status^);
            RETURN;
          IFEND;
        IFEND;

        ALLOCATE command_list_entry IN osv$task_shared_heap^;

        command_list_entry^.kind := command_block^.source.kind;
        command_list_entry^.next_entry := NIL;
        CASE command_block^.source.kind OF
        = clc$catalog_commands =
          command_list_entry^.local_file_name := command_block^.source.local_file_name;
        = clc$library_commands =
          command_list_entry^.local_file_name := command_block^.source.local_file_name;
          initialize_library_contains (library_list_entry, command_list_entry^.library_contains);
          command_list_entry^.unaccessible_entry := FALSE;
        ELSE
          ;
        CASEND;
        IF command_list^.entries.last_entry = NIL THEN
          command_list^.entries.last_entry := command_list_entry;
        IFEND;
      IFEND;

      command_list_entry^.next_entry := command_list^.entries.first_entry;
      command_list^.entries.first_entry := command_list_entry;

      CASE command_list_entry^.kind OF
      = clc$library_commands, clc$system_commands =
        clv$message_cache.count := 0;
      ELSE
        ;
      CASEND;
    END /create_new_entry/;

    establish_fence (command_list^.search_mode, command_list^.entries.first_entry,
          command_list^.entries.entry_after_fence);

  PROCEND clp$push_dynamic_command_list;
?? TITLE := 'clp$open_command_library', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$open_command_library
    (    caller_ring: ost$valid_ring;
         local_file_name: amt$local_file_name;
     VAR library_list_entry: ^clt$command_library_list_entry;
     VAR validated_file_name: fst$path_handle_name;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = mmc$segment_access_condition =
        IF condition.segment_access_condition.identifier = mmc$sac_io_read_error THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
          EXIT clp$open_command_library;
        IFEND;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$open_command_library;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      i: llt$entry_point_index,
      ignore_status: ost$status,
      ring_attributes: amt$ring_attributes,
      ignore_opened_executable_file: boolean,
      ignore_file_contents: clt$file_contents,
      ignore_file_has_fap: boolean,
      can_be_echoed: boolean,
      ignore_device_class: rmt$device_class,
      ignore_line_layout: clt$line_layout,
      current_entry: ^clt$command_library_list_entry,
      dictionaries: llt$library_dictionary_pointers,
      new_library_contents: ^SEQ ( * ),
      version: string (4),
      file_id: amt$file_identifier,
      caller_id: ost$caller_identifier;


    status.normal := TRUE;
    validated_file_name := local_file_name;

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    IF caller_ring > caller_id.ring THEN
      caller_id.ring := caller_ring;
    IFEND;

    current_entry := clv$task_command_library_list;
    WHILE (current_entry <> NIL) AND (current_entry^.local_file_name <> local_file_name) DO
      current_entry := current_entry^.next_entry;
    WHILEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

    IF current_entry = NIL THEN
      clp$access_command_file (clc$command_library, caller_id.ring, local_file_name, file_id,
            new_library_contents, ignore_opened_executable_file, can_be_echoed, ignore_line_layout,
            ignore_file_contents, ring_attributes, ignore_file_has_fap, ignore_device_class,
            validated_file_name, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF validated_file_name <> local_file_name THEN
        current_entry := clv$task_command_library_list;
        WHILE (current_entry <> NIL) AND (current_entry^.local_file_name <> validated_file_name) DO
          current_entry := current_entry^.next_entry;
        WHILEND;
        IF current_entry <> NIL THEN
          clp$close_executable_cmnd_file (file_id, status);
          IF status.normal THEN
            library_list_entry := current_entry;
          IFEND;
          RETURN;
        IFEND;
      IFEND;

      pmp$get_library_dictionaries (new_library_contents, dictionaries, status);
      IF NOT status.normal THEN
        clp$close_executable_cmnd_file (file_id, ignore_status);
        RETURN;
      IFEND;

      IF dictionaries.library_version = 'V1.0' THEN
        ALLOCATE dictionaries.command_dictionary: [1 .. UPPERBOUND (dictionaries.entry_point_dictionary^)] IN
              osv$task_private_heap^;
        FOR i := 1 TO UPPERBOUND (dictionaries.entry_point_dictionary^) DO
          pmp$convert_entry_point_to_cmnd (dictionaries.entry_point_dictionary^ [i], i,
                dictionaries.command_dictionary^ [i]);
        FOREND;
      ELSEIF dictionaries.library_version > llc$object_library_version THEN
        clp$close_executable_cmnd_file (file_id, ignore_status);
        osp$set_status_abnormal ('CL', lle$wrong_library_version, llc$object_library_version, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, validated_file_name, status);
        RETURN;
      IFEND;

      ALLOCATE current_entry IN osv$task_private_heap^;

      current_entry^.next_entry := clv$task_command_library_list;
      current_entry^.local_file_name := validated_file_name;
      current_entry^.used_for_dynamic_load := FALSE;
      current_entry^.file_id := file_id;
      current_entry^.ring_attributes := ring_attributes;
      current_entry^.contents := new_library_contents;
      current_entry^.can_be_echoed := can_be_echoed;
      current_entry^.dictionaries := dictionaries;
      clv$task_command_library_list := current_entry;
    ELSEIF NOT mmp$reverify_access (#LOC (current_entry^.contents)) THEN
        osp$set_status_abnormal ('CL', cle$command_search_aborted, local_file_name, status);
    IFEND;

    library_list_entry := current_entry;

  PROCEND clp$open_command_library;
?? TITLE := 'check_if_library_still_in_use', EJECT ??

  PROCEDURE [INLINE] check_if_library_still_in_use
    (    local_file_name: amt$local_file_name;
     VAR library_still_in_use: boolean);

    VAR
      block: ^clt$block,
      command_list: ^clt$command_list,
      current_command_list_entry: ^clt$command_list_entry,
      first_task: record
        case found: boolean of
        = TRUE =
          block: ^clt$block,
        casend,
      recend,
      index: integer,
      scan_command_lists: boolean;


    clp$find_current_block (block);
    first_task.found := FALSE;
    scan_command_lists := TRUE;

  /check_command_lists/
    WHILE scan_command_lists DO
      IF (block^.kind = clc$task_block) AND (NOT first_task.found) THEN
        first_task.found := TRUE;
        first_task.block := block;
      IFEND;

      IF (block^.environment_object_info <> NIL) AND
            block^.environment_object_info^.defined [clc$eo_command_list] THEN
        command_list := clp$environment_object_in_block (clc$eo_command_list, block);
        IF local_file_name = command_list^.system_command_library_lfn THEN
          library_still_in_use := TRUE;
          RETURN;
        IFEND;

        current_command_list_entry := command_list^.entries.first_entry;

      /search_for_file_name/
        WHILE current_command_list_entry <> NIL DO
          CASE current_command_list_entry^.kind OF
          = clc$library_commands =
            IF current_command_list_entry^.local_file_name = local_file_name THEN
              EXIT /search_for_file_name/;
            IFEND;
          = clc$sub_commands =
            IF current_command_list_entry^.utility_info^.libraries <> NIL THEN
              FOR index := 1 TO UPPERBOUND (current_command_list_entry^.utility_info^.libraries^) DO
                IF current_command_list_entry^.utility_info^.libraries^ [index] = local_file_name THEN
                  EXIT /search_for_file_name/;
                IFEND;
              FOREND;
            IFEND;
            IF current_command_list_entry^.utility_info^.auxiliary_libraries <> NIL THEN
              FOR index := 1 TO UPPERBOUND (current_command_list_entry^.utility_info^.auxiliary_libraries^) DO
                IF current_command_list_entry^.utility_info^.auxiliary_libraries^ [index].name =
                      local_file_name THEN
                  EXIT /search_for_file_name/;
                IFEND;
              FOREND;
            IFEND;
          ELSE
            ;
          CASEND;
          current_command_list_entry := current_command_list_entry^.next_entry;
        WHILEND /search_for_file_name/;

        IF current_command_list_entry <> NIL THEN
          library_still_in_use := TRUE;
          RETURN;
        IFEND;

        IF first_task.found AND ((first_task.block <> block) OR
              NOT first_task.block^.synchronous_with_parent) THEN
          scan_command_lists := FALSE;
        IFEND;
      IFEND;

      IF NOT first_task.found THEN
        IF ((block^.kind IN $clt$block_kinds [clc$input_block, clc$command_proc_block,
              clc$function_proc_block, clc$when_block]) AND (block^.input.kind = clc$file_input) AND
              (block^.input.local_file_name = local_file_name)) THEN
          library_still_in_use := TRUE;
          RETURN;
        IFEND;
      IFEND;

      block := block^.previous_block;

    WHILEND /check_command_lists/;

    library_still_in_use := FALSE;

  PROCEND check_if_library_still_in_use;
?? TITLE := 'clp$close_command_library', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$close_command_library
    (    local_file_name: amt$local_file_name;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$close_command_library;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      library_still_in_use: boolean,
      previous_library_list_entry: ^^clt$command_library_list_entry,
      current_library_list_entry: ^clt$command_library_list_entry;


    status.normal := TRUE;
    osp$establish_condition_handler (^abort_handler, FALSE);

    check_if_library_still_in_use (local_file_name, library_still_in_use);
    IF library_still_in_use THEN
      RETURN;
    IFEND;

    previous_library_list_entry := ^clv$task_command_library_list;
    current_library_list_entry := clv$task_command_library_list;
    WHILE (current_library_list_entry <> NIL) AND (current_library_list_entry^.local_file_name <>
          local_file_name) DO
      previous_library_list_entry := ^current_library_list_entry^.next_entry;
      current_library_list_entry := current_library_list_entry^.next_entry;
    WHILEND;
    IF (current_library_list_entry = NIL) OR current_library_list_entry^.used_for_dynamic_load THEN
      RETURN;
    IFEND;

    clp$close_executable_cmnd_file (current_library_list_entry^.file_id, status);

    previous_library_list_entry^ := current_library_list_entry^.next_entry;
    IF current_library_list_entry^.dictionaries.library_version = 'V1.0' THEN
      FREE current_library_list_entry^.dictionaries.command_dictionary IN osv$task_private_heap^;
    IFEND;
    FREE current_library_list_entry IN osv$task_private_heap^;

  PROCEND clp$close_command_library;
?? TITLE := 'update_command_list', EJECT ??

  PROCEDURE update_command_list
    (    erasing_a_task: boolean;
         command_list: ^clt$command_list;
         command_list_in_current_task: boolean;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT update_command_list;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;

    IF command_list_in_current_task THEN
      clv$message_cache.count := 0;
    IFEND;

    IF erasing_a_task AND NOT command_list^.deletion_made THEN
      RETURN;
    IFEND;

    command_list^.deletion_made := NOT command_list_in_current_task;

    osp$establish_condition_handler (^abort_handler, FALSE);

    update_command_library_list (status);

  PROCEND update_command_list;
?? TITLE := 'clp$update_command_library_list', EJECT ??

  PROCEDURE [INLINE] update_command_library_list
    (VAR status: ost$status);

    VAR
      library_still_in_use: boolean,
      previous_library_list_entry: ^^clt$command_library_list_entry,
      current_library_list_entry: ^clt$command_library_list_entry,
      local_status: ost$status;


    status.normal := TRUE;

    previous_library_list_entry := ^clv$task_command_library_list;
    current_library_list_entry := clv$task_command_library_list;

  /scan_library_list/
    WHILE current_library_list_entry <> NIL DO

    /check_library_still_in_use/
      BEGIN
        IF current_library_list_entry^.used_for_dynamic_load THEN
          EXIT /check_library_still_in_use/;
        IFEND;

        check_if_library_still_in_use (current_library_list_entry^.local_file_name, library_still_in_use);
        IF library_still_in_use THEN
          EXIT /check_library_still_in_use/;
        IFEND;

        clp$close_executable_cmnd_file (current_library_list_entry^.file_id, local_status);
        IF status.normal AND (NOT local_status.normal) THEN
          status := local_status;
        IFEND;

        previous_library_list_entry^ := current_library_list_entry^.next_entry;
        FREE current_library_list_entry IN osv$task_private_heap^;
        current_library_list_entry := previous_library_list_entry^;
        CYCLE /scan_library_list/;

      END /check_library_still_in_use/;

      previous_library_list_entry := ^current_library_list_entry^.next_entry;
      current_library_list_entry := current_library_list_entry^.next_entry;
    WHILEND /scan_library_list/;

  PROCEND update_command_library_list;
?? TITLE := 'clp$search_command_library', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$search_command_library
    (    command_or_function_name: ost$name;
         command_or_function: clt$command_or_function;
         searching_command_list: boolean;
     VAR work_area {input, output} : ^clt$work_area;
     VAR local_file_name {input, output} : amt$local_file_name;
     VAR file_id: amt$file_identifier;
     VAR ring_attributes: amt$ring_attributes;
     VAR can_be_echoed: boolean;
     VAR search_info: clt$command_library_search_info;
     VAR command_or_function_found: boolean;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$system_conditions, mmc$segment_access_condition =
        IF (condition.selector = mmc$segment_access_condition) AND
              (condition.segment_access_condition.identifier = mmc$sac_io_read_error) THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
        ELSE
          osp$set_status_abnormal ('CL', cle$command_search_aborted, local_file_name, status);
          IF searching_command_list THEN
            clp$set_unaccessible_entry (local_file_name, TRUE, status);
          IFEND;
        IFEND;
        EXIT clp$search_command_library;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$search_command_library;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      application_member_header: ^llt$application_member_header,
      caller_id: ost$caller_identifier,
      command_dictionary_item: ^llt$command_dictionary_item,
      command_list: ^clt$command_list,
      function_dictionary_item: ^llt$function_dictionary_item,
      ignore_cmnd_list_found_in_task: boolean,
      library_list_entry: ^clt$command_library_list_entry,
      library_module: ^SEQ ( * ),
      member_header: ^llt$library_member_header,
      validated_file_name: fst$path_handle_name;


    status.normal := TRUE;
    command_or_function_found := FALSE;
    library_list_entry := NIL;
    #SPOIL (library_list_entry);
*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

{
{ Do not search if we are running below ring 3.  In this case,
{ assume we did not find the command in the library.
{

    IF caller_id.ring < osc$tsrv_ring THEN
      RETURN;
    IFEND;

    IF local_file_name = osc$null_name THEN
      clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
      local_file_name := command_list^.system_command_library_lfn;
      #SPOIL (local_file_name);
      IF local_file_name = osc$null_name THEN
        RETURN;
      IFEND;
    IFEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

    clp$open_command_library (caller_id.ring, local_file_name, library_list_entry, validated_file_name,
          status);
    IF validated_file_name <> osc$null_name THEN
      local_file_name := validated_file_name;
      #SPOIL (local_file_name);
    IFEND;
    IF searching_command_list THEN
      clp$set_unaccessible_entry (local_file_name, TRUE, status);
    IFEND;
    IF (NOT status.normal) OR (library_list_entry = NIL) THEN
      RETURN;
    IFEND;

    IF caller_id.ring > library_list_entry^.ring_attributes.r3 THEN
      RETURN;
    IFEND;

    IF command_or_function = clc$command THEN
      IF library_list_entry^.dictionaries.command_dictionary = NIL THEN
        RETURN;
      IFEND;
      search_command_library (library_list_entry^.dictionaries.command_dictionary, command_or_function_name,
            command_dictionary_item);
      command_or_function_found := command_dictionary_item <> NIL;
      IF command_or_function_found THEN
        IF ((caller_id.ring < library_list_entry^.ring_attributes.r1) OR
              (caller_id.ring > library_list_entry^.ring_attributes.r2)) AND
              (command_dictionary_item^.kind <> llc$gate) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        ELSEIF command_dictionary_item^.kind = llc$local_to_library THEN
          command_or_function_found := local_cmnd_or_func_callable (local_file_name);
        IFEND;
      IFEND;
      IF NOT command_or_function_found THEN
        RETURN;
      IFEND;

      search_info.command_or_function_module := NIL;
      search_info.command_or_function_kind := command_dictionary_item^.kind;
      search_info.ordinal := command_dictionary_item^.ordinal;
      search_info.module_kind := command_dictionary_item^.module_kind;
      search_info.log_option := command_dictionary_item^.log_option;
      search_info.library_privilege := 'OBJECT';
      CASE search_info.module_kind OF

      = llc$command_procedure, llc$applic_command_procedure =
        IF command_dictionary_item^.module_kind = llc$applic_command_procedure THEN
          application_member_header := #PTR (command_dictionary_item^.applic_command_header,
                library_list_entry^.contents^);
          search_info.command_or_function_module := #PTR (application_member_header^.library_member_header.
                member, library_list_entry^.contents^);
          search_info.application_identifier := application_member_header^.application_identifier;
        ELSE
          member_header := #PTR (command_dictionary_item^.command_header, library_list_entry^.contents^);
          search_info.command_or_function_module := #PTR (member_header^.member,
                library_list_entry^.contents^);
          search_info.application_identifier.name := osc$null_name;
        IFEND;

      = llc$program_description, llc$applic_program_description =
        IF command_dictionary_item^.module_kind = llc$applic_program_description THEN
          application_member_header := #PTR (command_dictionary_item^.applic_program_header,
                library_list_entry^.contents^);
          library_module := #PTR (application_member_header^.library_member_header.member,
                library_list_entry^.contents^);
          search_info.application_identifier := application_member_header^.application_identifier;
        ELSE
          member_header := #PTR (command_dictionary_item^.program_header, library_list_entry^.contents^);
          library_module := #PTR (member_header^.member, library_list_entry^.contents^);
          search_info.application_identifier.name := osc$null_name;
        IFEND;
        IF caller_id.ring <= library_list_entry^.ring_attributes.r2 THEN
          search_info.command_or_function_module := library_module;
        ELSE
          NEXT search_info.command_or_function_module: [[REP #SIZE (library_module^) OF cell]] IN work_area;
          IF search_info.command_or_function_module = NIL THEN
            osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
            RETURN;
          IFEND;
          search_info.command_or_function_module^ := library_module^;
        IFEND;

      = llc$command_description, llc$applic_command_description =
        IF command_dictionary_item^.module_kind = llc$applic_command_description THEN
          application_member_header := #PTR (command_dictionary_item^.applic_command_description_hdr,
                library_list_entry^.contents^);
          library_module := #PTR (application_member_header^.library_member_header.member,
                library_list_entry^.contents^);
          search_info.application_identifier := application_member_header^.application_identifier;
        ELSE
          member_header := #PTR (command_dictionary_item^.command_description_header,
                library_list_entry^.contents^);
          library_module := #PTR (member_header^.member, library_list_entry^.contents^);
          search_info.application_identifier.name := osc$null_name;
        IFEND;
        IF caller_id.ring <= library_list_entry^.ring_attributes.r2 THEN
          search_info.command_or_function_module := library_module;
        ELSE
          NEXT search_info.command_or_function_module: [[REP #SIZE (library_module^) OF cell]] IN work_area;
          IF search_info.command_or_function_module = NIL THEN
            osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
            RETURN;
          IFEND;
          search_info.command_or_function_module^ := library_module^;
        IFEND;

      = llc$load_module =
        ;

      ELSE
        command_or_function_found := FALSE;
        RETURN;
      CASEND;

    ELSE {clc$function}
      IF library_list_entry^.dictionaries.function_dictionary = NIL THEN
        RETURN;
      IFEND;
      search_function_library (library_list_entry^.dictionaries.function_dictionary, command_or_function_name,
            function_dictionary_item);
      command_or_function_found := function_dictionary_item <> NIL;
      IF command_or_function_found THEN
        IF ((caller_id.ring < library_list_entry^.ring_attributes.r1) OR
              (caller_id.ring > library_list_entry^.ring_attributes.r2)) AND
              (function_dictionary_item^.kind <> llc$gate) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        ELSEIF function_dictionary_item^.kind = llc$local_to_library THEN
          command_or_function_found := local_cmnd_or_func_callable (local_file_name);
        IFEND;
      IFEND;
      IF NOT command_or_function_found THEN
        RETURN;
      IFEND;

      search_info.command_or_function_module := NIL;
      search_info.command_or_function_kind := function_dictionary_item^.kind;
      search_info.ordinal := function_dictionary_item^.ordinal;
      search_info.module_kind := function_dictionary_item^.module_kind;
      CASE search_info.module_kind OF

      = llc$function_procedure =
        member_header := #PTR (function_dictionary_item^.function_header, library_list_entry^.contents^);
        search_info.command_or_function_module := #PTR (member_header^.member, library_list_entry^.contents^);

      = llc$function_description =
        member_header := #PTR (function_dictionary_item^.function_description_header,
              library_list_entry^.contents^);
        library_module := #PTR (member_header^.member, library_list_entry^.contents^);
        IF caller_id.ring <= library_list_entry^.ring_attributes.r2 THEN
          search_info.command_or_function_module := library_module;
        ELSE
          NEXT search_info.command_or_function_module: [[REP #SIZE (library_module^) OF cell]] IN work_area;
          IF search_info.command_or_function_module = NIL THEN
            osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
            RETURN;
          IFEND;
          search_info.command_or_function_module^ := library_module^;
        IFEND;

      ELSE
        command_or_function_found := FALSE;
        RETURN;
      CASEND;
    IFEND;

    IF search_info.command_or_function_module <> NIL THEN
      RESET search_info.command_or_function_module;
    IFEND;
    file_id := library_list_entry^.file_id;
    ring_attributes := library_list_entry^.ring_attributes;
    can_be_echoed := library_list_entry^.can_be_echoed;

  PROCEND clp$search_command_library;
?? TITLE := 'search_command_library', EJECT ??

  PROCEDURE [INLINE] search_command_library
    (    command_dictionary: ^llt$command_dictionary;
         command_name: ost$name;
     VAR command_dictionary_item: ^llt$command_dictionary_item);

    VAR
*IF $true(osv$unix)
      lower: 1 .. llc$max_commands_in_library,
*ELSE
      lower: 1 .. llc$max_commands_in_library + 1,
*IFEND
      upper: 0 .. llc$max_commands_in_library,
      temp: integer,
      index: llt$command_index;


    command_dictionary_item := NIL;
    lower := 1;
    upper := UPPERBOUND (command_dictionary^);


  /binary_search/
    WHILE (lower <= upper) DO
      temp := lower + upper;
      index := temp DIV 2;
      IF command_name = command_dictionary^ [index].name THEN
        command_dictionary_item := ^command_dictionary^ [index];
        EXIT /binary_search/;
      ELSEIF command_name > command_dictionary^ [index].name THEN
        lower := index + 1;
      ELSE
        upper := index - 1;
      IFEND;
    WHILEND /binary_search/;

  PROCEND search_command_library;
?? TITLE := 'local_cmnd_or_func_callable', EJECT ??

  FUNCTION [UNSAFE] local_cmnd_or_func_callable
    (    library: amt$local_file_name): boolean;

    VAR
      block: ^clt$block;


    clp$find_current_block (block);

  /search/
    WHILE block <> NIL DO
      CASE block^.kind OF
      = clc$command_block =
        CASE block^.command_kind OF
        = clc$command_is_include_file, clc$command_is_include_line =
          ;
        ELSE
          EXIT /search/;
        CASEND;
      = clc$command_proc_block, clc$function_block, clc$function_proc_block =
        EXIT /search/;
      ELSE
        ;
      CASEND;
      block := block^.previous_block;
    WHILEND /search/;

    local_cmnd_or_func_callable := (block <> NIL) AND (block^.source.kind = clc$library_commands) AND
          (library = block^.source.local_file_name);

  FUNCEND local_cmnd_or_func_callable;
?? TITLE := 'clp$find_cmnd_or_func_in_prog', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$find_cmnd_or_func_in_prog
    (    command_or_function_name: ost$name;
         command_or_function: clt$command_or_function;
     VAR work_area {input, output} : ^clt$work_area;
     VAR local_file_name: amt$local_file_name;
     VAR ring_attributes: amt$ring_attributes;
     VAR search_info: clt$command_library_search_info;
     VAR status: ost$status);

    VAR
      application_member_header: ^llt$application_member_header,
      caller_id: ost$caller_identifier,
      command_dictionary_item: llt$command_dictionary_item,
      function_dictionary_item: llt$function_dictionary_item,
      library: ^SEQ ( * ),
      library_module: ^SEQ ( * ),
      library_privilege: ost$name,
      member_header: ^llt$library_member_header;


    status.normal := TRUE;
*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

    IF command_or_function = clc$command THEN
      lop$find_command_in_program (command_or_function_name, command_dictionary_item, library,
            local_file_name, ring_attributes, library_privilege, status);
      IF NOT status.normal THEN
        osp$set_status_abnormal ('CL', cle$unable_to_call_command, command_or_function_name, status);
        RETURN;
      ELSEIF caller_id.ring > ring_attributes.r3 THEN
        RETURN;
      IFEND;

      search_info.command_or_function_module := NIL;
      search_info.command_or_function_kind := command_dictionary_item.kind;
      search_info.ordinal := command_dictionary_item.ordinal;
      search_info.module_kind := command_dictionary_item.module_kind;
      search_info.log_option := command_dictionary_item.log_option;
      search_info.library_privilege := library_privilege;
      CASE search_info.module_kind OF

      = llc$command_procedure, llc$applic_command_procedure =

{! The following check of rings (that the caller is within the execute bracket of the file) is temporary.
{! Someday (maybe) code will be added to switch rings when the caller is outside the execute bracket.

        IF (caller_id.ring < ring_attributes.r1) OR (caller_id.ring > ring_attributes.r2) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        IFEND;
        IF search_info.module_kind = llc$applic_command_procedure THEN
          application_member_header := #PTR (command_dictionary_item.applic_command_header, library^);
          search_info.command_or_function_module := #PTR (application_member_header^.library_member_header.
                member, library^);
          search_info.application_identifier := application_member_header^.application_identifier;
        ELSE
          member_header := #PTR (command_dictionary_item.command_header, library^);
          search_info.command_or_function_module := #PTR (member_header^.member, library^);
          search_info.application_identifier.name := osc$null_name;
        IFEND;

      = llc$program_description, llc$applic_program_description =
        IF ((caller_id.ring < ring_attributes.r1) OR (caller_id.ring > ring_attributes.r2)) AND
              (search_info.command_or_function_kind <> llc$gate) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        IFEND;
        IF command_dictionary_item.module_kind = llc$applic_program_description THEN
          application_member_header := #PTR (command_dictionary_item.applic_program_header, library^);
          library_module := #PTR (application_member_header^.library_member_header.member, library^);
          search_info.application_identifier := application_member_header^.application_identifier;
        ELSE
          member_header := #PTR (command_dictionary_item.program_header, library^);
          library_module := #PTR (member_header^.member, library^);
          search_info.application_identifier.name := osc$null_name;
        IFEND;
        IF caller_id.ring <= ring_attributes.r2 THEN
          search_info.command_or_function_module := library_module;
        ELSE
          NEXT search_info.command_or_function_module: [[REP #SIZE (library_module^) OF cell]] IN work_area;
          IF search_info.command_or_function_module = NIL THEN
            osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
            RETURN;
          IFEND;
          search_info.command_or_function_module^ := library_module^;
        IFEND;

      = llc$command_description, llc$applic_command_description =
        IF (caller_id.ring < ring_attributes.r1) OR ((caller_id.ring > ring_attributes.r2) AND
              (search_info.command_or_function_kind <> llc$gate)) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        IFEND;
        IF command_dictionary_item.module_kind = llc$applic_command_description THEN
          application_member_header := #PTR (command_dictionary_item.applic_command_description_hdr,
                library^);
          library_module := #PTR (application_member_header^.library_member_header.member, library^);
          search_info.application_identifier := application_member_header^.application_identifier;
        ELSE
          member_header := #PTR (command_dictionary_item.command_description_header, library^);
          library_module := #PTR (member_header^.member, library^);
          search_info.application_identifier.name := osc$null_name;
        IFEND;
        IF caller_id.ring <= ring_attributes.r2 THEN
          search_info.command_or_function_module := library_module;
        ELSE
          NEXT search_info.command_or_function_module: [[REP #SIZE (library_module^) OF cell]] IN work_area;
          IF search_info.command_or_function_module = NIL THEN
            osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
            RETURN;
          IFEND;
          search_info.command_or_function_module^ := library_module^;
        IFEND;

      = llc$load_module =
        IF ((caller_id.ring < ring_attributes.r1) OR (caller_id.ring > ring_attributes.r2)) AND
              (search_info.command_or_function_kind <> llc$gate) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        IFEND;

      ELSE
        osp$set_status_abnormal ('CL', cle$unable_to_call_command, command_or_function_name, status);
        RETURN;
      CASEND;

    ELSE {clc$function}
      lop$find_function_in_program (command_or_function_name, function_dictionary_item, library,
            local_file_name, ring_attributes, status);
      IF NOT status.normal THEN
        osp$set_status_abnormal ('CL', cle$unable_to_call_command, command_or_function_name, status);
        RETURN;
      ELSEIF caller_id.ring > ring_attributes.r3 THEN
        RETURN;
      IFEND;

      search_info.command_or_function_module := NIL;
      search_info.command_or_function_kind := function_dictionary_item.kind;
      search_info.ordinal := function_dictionary_item.ordinal;
      search_info.module_kind := function_dictionary_item.module_kind;
      CASE search_info.module_kind OF

      = llc$function_procedure =

{! The following check of rings (that the caller is within the execute bracket of the file) is temporary.
{! Someday (maybe) code will be added to switch rings when the caller is outside the execute bracket.

        IF (caller_id.ring < ring_attributes.r1) OR (caller_id.ring > ring_attributes.r2) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        IFEND;
        member_header := #PTR (function_dictionary_item.function_header, library^);
        search_info.command_or_function_module := #PTR (member_header^.member, library^);

      = llc$function_description =
        IF (caller_id.ring < ring_attributes.r1) OR ((caller_id.ring > ring_attributes.r2) AND
              (search_info.command_or_function_kind <> llc$gate)) THEN
          osp$set_status_abnormal ('CL', cle$command_file_not_callable, local_file_name, status);
          RETURN;
        IFEND;
        member_header := #PTR (function_dictionary_item.function_description_header, library^);
        library_module := #PTR (member_header^.member, library^);
        IF caller_id.ring <= ring_attributes.r2 THEN
          search_info.command_or_function_module := library_module;
        ELSE
          NEXT search_info.command_or_function_module: [[REP #SIZE (library_module^) OF cell]] IN work_area;
          IF search_info.command_or_function_module = NIL THEN
            osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
            RETURN;
          IFEND;
          search_info.command_or_function_module^ := library_module^;
        IFEND;

      ELSE
        osp$set_status_abnormal ('CL', cle$unable_to_call_command, command_or_function_name, status);
        RETURN;
      CASEND;
    IFEND;

    IF search_info.command_or_function_module <> NIL THEN
      RESET search_info.command_or_function_module;
    IFEND;

  PROCEND clp$find_cmnd_or_func_in_prog;
?? TITLE := 'search_function_library', EJECT ??

  PROCEDURE [INLINE] search_function_library
    (    function_dictionary: ^llt$function_dictionary;
         function_name: ost$name;
     VAR function_dictionary_item: ^llt$function_dictionary_item);

    VAR
*IF $true(osv$unix)
      lower: 1 .. llc$max_functions_in_library,
*ELSE
      lower: 1 .. llc$max_functions_in_library + 1,
*IFEND
      upper: 0 .. llc$max_functions_in_library,
      temp: integer,
      index: llt$function_index;


    function_dictionary_item := NIL;
    lower := 1;
    upper := UPPERBOUND (function_dictionary^);

  /binary_search/
    WHILE (lower <= upper) DO
      temp := lower + upper;
      index := temp DIV 2;
      IF function_name = function_dictionary^ [index].name THEN
        function_dictionary_item := ^function_dictionary^ [index];
        EXIT /binary_search/;
      ELSEIF function_name > function_dictionary^ [index].name THEN
        lower := index + 1;
      ELSE
        upper := index - 1;
      IFEND;
    WHILEND /binary_search/;

  PROCEND search_function_library;
*IFEND
?? TITLE := 'clp$clear_message_cache', EJECT ??

  PROCEDURE [XDCL] clp$clear_message_cache;


    clv$message_cache.count := 0;

  PROCEND clp$clear_message_cache;
?? TITLE := 'clp$search_msg_library_via_name', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$search_msg_library_via_name
    (    caller_ring: ost$valid_ring;
         name: ost$status_condition_name;
         search_by_language: boolean;
         search_cache: boolean;
     VAR local_file_name {input, output} : amt$local_file_name;
     VAR code: ost$status_condition_code;
     VAR severity: ost$message_module_severity;
     VAR template: ^ost$message_template;
     VAR entry_found: boolean;
     VAR saved_default: boolean;
     VAR status: ost$status);

*IF NOT $true(osv$unix)
?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$system_conditions, mmc$segment_access_condition =
        IF (condition.selector = mmc$segment_access_condition) AND
              (condition.segment_access_condition.identifier = mmc$sac_io_read_error) THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
        ELSE
          pmp$log ('Unable to lookup status name due to system condition or segment access condition',
                handler_status);
        IFEND;
        entry_found := FALSE;
        EXIT clp$search_msg_library_via_name;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          entry_found := FALSE;
          EXIT clp$search_msg_library_via_name;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? TITLE := 'search_cache_for_name', EJECT ??

    PROCEDURE [INLINE] search_cache_for_name;

      VAR
        i: 1 .. clc$message_cache_size;


      entry_found := FALSE;
      cache_index := 0;

      FOR i := 1 TO clv$message_cache.count DO
        IF name = clv$message_cache.buffer [i].name THEN
          cache_index := i;
          IF (NOT search_by_language) OR (clv$message_cache.buffer [i].template <> NIL) THEN
            entry_found := mmp$reverify_access (#LOC (clv$message_cache.buffer [i].template));
            IF entry_found THEN
              code := clv$message_cache.buffer [i].code;
              severity := clv$message_cache.buffer [i].severity;
              template := clv$message_cache.buffer [i].template;
            ELSE
              clv$message_cache.count := 0;
            IFEND;
          IFEND;
          RETURN;
        IFEND;
      FOREND;

    PROCEND search_cache_for_name;
?? TITLE := 'update_cache', EJECT ??

    PROCEDURE [INLINE] update_cache;

      VAR
        i: 1 .. clc$message_cache_size;


      IF NOT search_cache THEN
        cache_index := 0;

      /search_cache_buffer/
        FOR i := 1 TO clv$message_cache.count DO
          IF name = clv$message_cache.buffer [i].name THEN
            cache_index := i;
            EXIT /search_cache_buffer/;
          IFEND;
        FOREND /search_cache_buffer/;
      IFEND;

      IF cache_index = 0 THEN
        IF clv$message_cache.count < clc$message_cache_size THEN
          clv$message_cache.count := clv$message_cache.count + 1;
        IFEND;
        FOR cache_index := clv$message_cache.count DOWNTO 2 DO
          clv$message_cache.buffer [cache_index] := clv$message_cache.buffer [cache_index - 1];
        FOREND;
        cache_index := 1;
        clv$message_cache.buffer [cache_index].name := name;
      IFEND;
      clv$message_cache.buffer [cache_index].code := code;
      clv$message_cache.buffer [cache_index].severity := severity;
      IF language = natural_language^ THEN
        clv$message_cache.buffer [cache_index].template := template;
      ELSE
*IF NOT $true(osv$unix)
        clv$message_cache.buffer [cache_index].template := NIL;
*ELSE
        clv$message_cache.buffer [cache_index].template := osc$null_name;
*IFEND
      IFEND;

    PROCEND update_cache;
?? OLDTITLE, EJECT ??
*IFEND

    VAR
      natural_language: ^ost$natural_language,
*IF NOT $true(osv$unix)
      caller_id: ost$caller_identifier,
*IFEND
      cache_index: 0 .. clc$message_cache_size,
      message_module: ^ost$message_template_module,
*IF NOT $true(osv$unix)
      message_module_dictionary: ^llt$message_module_dictionary,
      member_header: ^llt$library_member_header,
      ignore_status: ost$status,
      index: llt$message_module_index,
      command_list: ^clt$command_list,
      language: ost$natural_language,
      ignore_validated_file_name: fst$path_handle_name,
      library_list_entry: ^clt$command_library_list_entry;
*ELSE
      language: ost$natural_language,
      ignore_status: ost$status;
*IFEND


    status.normal := TRUE;
    entry_found := FALSE;
*IF NOT $true(osv$unix)
    library_list_entry := NIL;
    #SPOIL (library_list_entry);

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

{
{ Do not search a library if we are running below ring 3.  In this case,
{ assume we did not find the entry in the library.
{

    IF (caller_id.ring < osc$tsrv_ring) AND (local_file_name <> osc$null_name) THEN
      RETURN;
    IFEND;

    IF caller_ring > caller_id.ring THEN
      caller_id.ring := caller_ring;
    IFEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

    IF search_cache THEN
      search_cache_for_name;
      IF entry_found THEN
        RETURN;
      IFEND;
    IFEND;

    osp$find_natural_language (natural_language);

  /search_library/
    BEGIN
      IF local_file_name = osc$null_name THEN
*ELSE
        language := osc$us_english;
*IFEND
        message_module := osv$built_in_message_templates;
        IF message_module <> NIL THEN
          clp$search_module_for_name (message_module, name, language, code, severity, template, entry_found,
                ignore_status);
          IF entry_found AND search_by_language AND (language <> natural_language^) AND
                (language = osc$default_natural_language) THEN
            saved_default := TRUE;
            entry_found := FALSE;
          IFEND;
        IFEND;
*IF NOT $true(osv$unix)
        EXIT /search_library/;
      IFEND;

      clp$open_command_library (caller_id.ring, local_file_name, library_list_entry,
            ignore_validated_file_name, status);
      IF (NOT status.normal) OR (library_list_entry = NIL) OR
            ((library_list_entry <> NIL) AND (NOT mmp$reverify_access (#LOC (library_list_entry^.contents))))
            THEN
        EXIT /search_library/;
      IFEND;

      message_module_dictionary := library_list_entry^.dictionaries.message_module_dictionary;
      IF (message_module_dictionary = NIL) OR (caller_id.ring > library_list_entry^.ring_attributes.r2) THEN
        EXIT /search_library/;
      IFEND;

      clp$search_dictionary_for_name (library_list_entry^.contents, message_module_dictionary,
            natural_language^, search_by_language, name, code, severity, template, entry_found,
            saved_default);
    END /search_library/;

    IF entry_found THEN
      update_cache;
    IFEND;
*IFEND

  PROCEND clp$search_msg_library_via_name;
?? TITLE := 'clp$search_msg_library_via_code', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$search_msg_library_via_code
    (    caller_ring: ost$valid_ring;
         code: ost$status_condition_code;
         search_by_language: boolean;
         search_cache: boolean;
     VAR local_file_name {input, output} : amt$local_file_name;
     VAR name {input, output} : ost$status_condition_name;
     VAR severity {input, output} : ost$message_module_severity;
     VAR template {input, output} : ^ost$message_template;
     VAR entry_found: boolean;
     VAR saved_default: boolean;
     VAR status: ost$status);

*IF NOT $true(osv$unix)
?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$system_conditions, mmc$segment_access_condition =
        IF (condition.selector = mmc$segment_access_condition) AND
              (condition.segment_access_condition.identifier = mmc$sac_io_read_error) THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
        ELSE
          pmp$log ('Unable to lookup status code due to system condition or segment access condition',
                handler_status);
        IFEND;
        entry_found := FALSE;
        EXIT clp$search_msg_library_via_code;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          entry_found := FALSE;
          EXIT clp$search_msg_library_via_code;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? TITLE := 'search_cache_for_code', EJECT ??

    PROCEDURE [INLINE] search_cache_for_code;

      VAR
        i: 1 .. clc$message_cache_size;


      entry_found := FALSE;
      cache_index := 0;

      FOR i := 1 TO clv$message_cache.count DO
        IF code = clv$message_cache.buffer [i].code THEN
          cache_index := i;
          IF (NOT search_by_language) OR (clv$message_cache.buffer [i].template <> NIL) THEN
            entry_found := mmp$reverify_access (#LOC (clv$message_cache.buffer [i].template));
            IF entry_found THEN
              name := clv$message_cache.buffer [i].name;
              severity := clv$message_cache.buffer [i].severity;
              template := clv$message_cache.buffer [i].template;
            ELSE
              clv$message_cache.count := 0;
            IFEND;
          IFEND;
          RETURN;
        IFEND;
      FOREND;

    PROCEND search_cache_for_code;
?? TITLE := 'update_cache', EJECT ??

    PROCEDURE [INLINE] update_cache;

      VAR
        i: 1 .. clc$message_cache_size;


      IF NOT search_cache THEN
        cache_index := 0;

      /search_cache_buffer/
        FOR i := 1 TO clv$message_cache.count DO
          IF name = clv$message_cache.buffer [i].name THEN
            cache_index := i;
            EXIT /search_cache_buffer/;
          IFEND;
        FOREND /search_cache_buffer/;
      IFEND;

      IF cache_index = 0 THEN
        IF clv$message_cache.count < clc$message_cache_size THEN
          clv$message_cache.count := clv$message_cache.count + 1;
        IFEND;
        FOR cache_index := clv$message_cache.count DOWNTO 2 DO
          clv$message_cache.buffer [cache_index] := clv$message_cache.buffer [cache_index - 1];
        FOREND;
        cache_index := 1;
        clv$message_cache.buffer [cache_index].code := code;
      IFEND;
      clv$message_cache.buffer [cache_index].name := name;
      clv$message_cache.buffer [cache_index].severity := severity;
      IF language = natural_language^ THEN
        clv$message_cache.buffer [cache_index].template := template;
      ELSE
*IF NOT $true(osv$unix)
        clv$message_cache.buffer [cache_index].template := NIL;
*ELSE
        clv$message_cache.buffer [cache_index].template := osc$null_name;
*IFEND
      IFEND;

    PROCEND update_cache;
?? OLDTITLE, EJECT ??
*IFEND

    VAR
      natural_language: ^ost$natural_language,
*IF NOT $true(osv$unix)
      caller_id: ost$caller_identifier,
*IFEND
      cache_index: 0 .. clc$message_cache_size,
      message_module: ^ost$message_template_module,
*IF NOT $true(osv$unix)
      message_module_dictionary: ^llt$message_module_dictionary,
      member_header: ^llt$library_member_header,
      ignore_status: ost$status,
      index: llt$message_module_index,
      command_list: ^clt$command_list,
      language: ost$natural_language,
      ignore_validated_file_name: fst$path_handle_name,
      library_list_entry: ^clt$command_library_list_entry;
*ELSE
      language: ost$natural_language,
      ignore_status: ost$status;
*IFEND


    status.normal := TRUE;
    entry_found := FALSE;
*IF NOT $true(osv$unix)
    library_list_entry := NIL;
    #SPOIL (library_list_entry);

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

{
{ Do not search a library if we are running below ring 3.  In this case,
{ assume we did not find the entry in the library.
{

    IF (caller_id.ring < osc$tsrv_ring) AND (local_file_name <> osc$null_name) THEN
      RETURN;
    IFEND;

    IF caller_ring > caller_id.ring THEN
      caller_id.ring := caller_ring;
    IFEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

    IF search_cache THEN
      search_cache_for_code;
      IF entry_found THEN
        RETURN;
      IFEND;
    IFEND;

    osp$find_natural_language (natural_language);

  /search_library/
    BEGIN
      IF local_file_name = osc$null_name THEN
*ELSE
        language := osc$us_english;
*IFEND
        message_module := osv$built_in_message_templates;
        IF message_module <> NIL THEN
          clp$search_module_for_code (message_module, code, language, name, severity, template, entry_found,
                ignore_status);
*IF NOT $true(osv$unix)
          IF entry_found AND search_by_language AND (language <> natural_language^) AND
                (language = osc$default_natural_language) THEN
            saved_default := TRUE;
            entry_found := FALSE;
          IFEND;
*IFEND
        IFEND;
*IF NOT $true(osv$unix)
        EXIT /search_library/;
      IFEND;

      clp$open_command_library (caller_id.ring, local_file_name, library_list_entry,
            ignore_validated_file_name, status);
      IF (NOT status.normal) OR (library_list_entry = NIL) OR
            ((library_list_entry <> NIL) AND (NOT mmp$reverify_access (#LOC (library_list_entry^.contents))))
            THEN
        EXIT /search_library/;
      IFEND;

      message_module_dictionary := library_list_entry^.dictionaries.message_module_dictionary;
      IF (message_module_dictionary = NIL) OR (caller_id.ring > library_list_entry^.ring_attributes.r2) THEN
        EXIT /search_library/;
      IFEND;

      clp$search_dictionary_for_code (library_list_entry^.contents, message_module_dictionary,
            natural_language^, search_by_language, code, name, severity, template, entry_found,
            saved_default);
    END /search_library/;

    IF entry_found THEN
      update_cache;
    IFEND;
*IFEND

  PROCEND clp$search_msg_library_via_code;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$search_for_help_module', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$search_for_help_module
    (    caller_ring: ost$valid_ring;
         name: pmt$program_name;
     VAR local_file_name {input, output} : amt$local_file_name;
     VAR entry_found: boolean;
     VAR help_module: ^ost$message_template_module;
     VAR language: ost$natural_language;
     VAR online_manual: ost$online_manual_name;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$system_conditions, mmc$segment_access_condition =
        osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
        EXIT clp$search_for_help_module;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$search_for_help_module;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      caller_id: ost$caller_identifier,
*IF $true(osv$unix)
      lower: 1 .. llc$max_help_modules_in_library,
*ELSE
      lower: 1 .. llc$max_help_modules_in_library + 1,
*IFEND
      upper: 0 .. llc$max_help_modules_in_library,
      help_module_dictionary: ^llt$help_module_dictionary,
      member_header: ^llt$library_member_header,
      header: ^ost$mtm_header,
      index: llt$help_module_index,
      ignore_condition_codes: ^ost$mtm_condition_codes,
      ignore_condition_names: ^ost$mtm_condition_names,
      ignore_validated_file_name: fst$path_handle_name,
      command_list: ^clt$command_list,
      temp: integer,
      library_list_entry: ^clt$command_library_list_entry;


    status.normal := TRUE;
    entry_found := FALSE;
    library_list_entry := NIL;
    #SPOIL (library_list_entry);

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

{
{ Do not search if we are running below ring 3.  In this case,
{ assume we did not find the entry in the library.
{

    IF caller_id.ring < osc$tsrv_ring THEN
      RETURN;
    IFEND;

    IF caller_ring > caller_id.ring THEN
      caller_id.ring := caller_ring;
    IFEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

  /search_library/
    BEGIN

      clp$open_command_library (caller_id.ring, local_file_name, library_list_entry,
            ignore_validated_file_name, status);
      IF (NOT status.normal) OR (library_list_entry = NIL) THEN
        EXIT /search_library/;
      IFEND;

      help_module_dictionary := library_list_entry^.dictionaries.help_module_dictionary;
      IF (help_module_dictionary = NIL) OR (caller_id.ring > library_list_entry^.ring_attributes.r2) THEN
        EXIT /search_library/;
      IFEND;

      lower := 1;
      upper := UPPERBOUND (help_module_dictionary^);
      ignore_condition_codes := NIL;
      ignore_condition_names := NIL;

    /search_dictionary/
      WHILE (lower <= upper) DO
        temp := lower + upper;
        index := temp DIV 2;
        IF help_module_dictionary^ [index].name = name THEN
          entry_found := TRUE;
          member_header := #PTR (help_module_dictionary^ [index].help_header, library_list_entry^.contents^);
          help_module := #PTR (member_header^.member, library_list_entry^.contents^);
          RESET help_module;
          clp$extract_msg_module_contents (help_module, header, ignore_condition_codes,
                ignore_condition_names);
          language := header^.language;
          online_manual := header^.online_manual_name;
          EXIT /search_dictionary/;
        ELSEIF help_module_dictionary^ [index].name > name THEN
          upper := index - 1;
        ELSE
          lower := index + 1;
        IFEND;
      WHILEND /search_dictionary/;
    END /search_library/;

  PROCEND clp$search_for_help_module;
?? TITLE := 'clp$set_unaccessible_entry', EJECT ??

  PROCEDURE [INLINE] clp$set_unaccessible_entry
    (    local_file_name: amt$local_file_name;
         reset_status: boolean;
     VAR status: {input, output} ost$status);

    VAR
      command_list: ^clt$command_list,
      ignore_cmnd_list_found_in_task: boolean,
      new_entry: ^clt$command_list_entry;


    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    new_entry := command_list^.entries.first_entry;
    WHILE new_entry <> NIL DO
      IF (new_entry^.kind = clc$library_commands) AND (new_entry^.local_file_name = local_file_name) THEN
        IF NOT status.normal THEN
          IF NOT new_entry^.unaccessible_entry THEN
            new_entry^.unaccessible_entry := TRUE;
          ELSEIF reset_status THEN
            status.normal := TRUE;
          IFEND;
        ELSEIF new_entry^.unaccessible_entry THEN
          new_entry^.unaccessible_entry := FALSE;
        IFEND;
        RETURN;
      IFEND;
      new_entry := new_entry^.next_entry;
    WHILEND;

  PROCEND clp$set_unaccessible_entry;
?? TITLE := 'clp$find_command_entries', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$find_command_entries
    (    local_file_name: amt$local_file_name;
     VAR work_area {input, output} : ^clt$work_area;
     VAR ring_attributes: amt$ring_attributes;
     VAR command_entries: ^llt$command_dictionary;
     VAR function_entries: ^llt$function_dictionary;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = mmc$segment_access_condition =
        IF condition.segment_access_condition.identifier = mmc$sac_io_read_error THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
          EXIT clp$find_command_entries;
        IFEND;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$find_command_entries;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      caller_id: ost$caller_identifier,
      ignore_validated_file_name: fst$path_handle_name,
      library_list_entry: ^clt$command_library_list_entry;


    status.normal := TRUE;
*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

    clp$open_command_library (caller_id.ring, local_file_name, library_list_entry, ignore_validated_file_name,
          status);
    clp$set_unaccessible_entry (local_file_name, FALSE, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

    ring_attributes := library_list_entry^.ring_attributes;

    IF library_list_entry^.dictionaries.command_dictionary = NIL THEN
      command_entries := NIL;
    ELSEIF library_list_entry^.ring_attributes.r2 >= caller_id.ring THEN
      command_entries := library_list_entry^.dictionaries.command_dictionary;
    ELSE
      NEXT command_entries: [1 .. UPPERBOUND (library_list_entry^.dictionaries.command_dictionary^)] IN
            work_area;
      IF command_entries = NIL THEN
        osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
        RETURN;
      IFEND;
      command_entries^ := library_list_entry^.dictionaries.command_dictionary^;
    IFEND;

    IF library_list_entry^.dictionaries.function_dictionary = NIL THEN
      function_entries := NIL;
    ELSEIF library_list_entry^.ring_attributes.r2 >= caller_id.ring THEN
      function_entries := library_list_entry^.dictionaries.function_dictionary;
    ELSE
      NEXT function_entries: [1 .. UPPERBOUND (library_list_entry^.dictionaries.function_dictionary^)] IN
            work_area;
      IF function_entries = NIL THEN
        osp$set_status_abnormal ('CL', cle$work_area_overflow, '', status);
        RETURN;
      IFEND;
      function_entries^ := library_list_entry^.dictionaries.function_dictionary^;
    IFEND;

  PROCEND clp$find_command_entries;
?? TITLE := 'clp$load_system_entry_point', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$load_system_entry_point
    (    name: pmt$program_name;
         kind: pmt$loaded_address_kind;
     VAR loaded_address: pmt$loaded_address;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$load_system_entry_point;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      ignore_cmnd_list_found_in_task: boolean,
      ring_for_load: ost$valid_ring,
      ignore_validated_file_name: fst$path_handle_name,
      library_list_entry: ^clt$command_library_list_entry;


    status.normal := TRUE;
    loaded_address.kind := kind;
    IF kind = pmc$procedure_address THEN
      loaded_address.pointer_to_procedure := NIL;
    ELSE
      loaded_address.pointer_to_data := NIL;
    IFEND;

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    osp$establish_condition_handler (^abort_handler, FALSE);

    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    IF command_list^.system_command_library_lfn = osc$null_name THEN
      RETURN;
    IFEND;

    clp$open_command_library (caller_id.ring, command_list^.system_command_library_lfn, library_list_entry,
          ignore_validated_file_name, status);
    IF (NOT status.normal) OR (caller_id.ring > library_list_entry^.ring_attributes.r3) OR
          (caller_id.ring < library_list_entry^.ring_attributes.r1) THEN
      RETURN;
    IFEND;

    IF caller_id.ring > library_list_entry^.ring_attributes.r2 THEN
      ring_for_load := library_list_entry^.ring_attributes.r2;
    ELSE
      ring_for_load := caller_id.ring;
    IFEND;

    library_list_entry^.used_for_dynamic_load := TRUE;

    pmp$load_from_library (name, ring_for_load, 0, kind, library_list_entry^.contents,
          command_list^.system_command_library_lfn, loaded_address, status);

  PROCEND clp$load_system_entry_point;
?? TITLE := 'clp$load_from_library', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$load_from_library
    (    name: pmt$program_name;
         kind: pmt$loaded_address_kind;
         local_file_name: amt$local_file_name;
     VAR loaded_address: pmt$loaded_address;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$load_from_library;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      caller_id: ost$caller_identifier,
      library_list_entry: ^clt$command_library_list_entry,
      ring_for_load: ost$valid_ring,
      validated_file_name: fst$path_handle_name;


    status.normal := TRUE;
    loaded_address.kind := kind;
    IF kind = pmc$procedure_address THEN
      loaded_address.pointer_to_procedure := NIL;
    ELSE
      loaded_address.pointer_to_data := NIL;
    IFEND;

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND
    osp$establish_condition_handler (^abort_handler, FALSE);

    clp$open_command_library (caller_id.ring, local_file_name, library_list_entry, validated_file_name,
          status);
    IF (NOT status.normal) OR (caller_id.ring > library_list_entry^.ring_attributes.r3) OR
          (caller_id.ring < library_list_entry^.ring_attributes.r1) THEN
      RETURN;
    IFEND;

    IF caller_id.ring > library_list_entry^.ring_attributes.r2 THEN
      ring_for_load := library_list_entry^.ring_attributes.r2;
    ELSE
      ring_for_load := caller_id.ring;
    IFEND;

    library_list_entry^.used_for_dynamic_load := TRUE;

    pmp$load_from_library (name, ring_for_load, 0, kind, library_list_entry^.contents, validated_file_name,
          loaded_address, status);

  PROCEND clp$load_from_library;
?? TITLE := 'clp$find_form', EJECT ??
*copyc clh$find_form

  PROCEDURE [XDCL, #GATE] clp$find_form
    (    form_name: ost$name;
     VAR p_form_module: ^SEQ ( * );
     VAR status: ost$status);

    VAR
      auxiliary_library_index: integer,
      block_in_current_task: boolean,
      caller_id: ost$caller_identifier,
      ignore_cmnd_list_found_in_task: boolean,
      local_library_name: amt$local_file_name,
      p_command_list: ^clt$command_list,
      p_command_list_entry: ^clt$command_list_entry,
      system_library_searched: boolean,
      utility_block: ^clt$block;

    status.normal := TRUE;
    p_form_module := NIL;

*IF NOT $true(osv$unix)
    #CALLER_ID (caller_id);
*ELSE
    caller_id.ring := osc$user_ring;
*IFEND

{
{ Do not search if we are running below ring 3.  In this case,
{ assume we did not find the form module in the library.
{

    IF caller_id.ring < osc$tsrv_ring THEN
      RETURN;
    IFEND;

    clp$find_command_list (p_command_list, ignore_cmnd_list_found_in_task);
    p_command_list_entry := p_command_list^.entries.first_entry;

    system_library_searched := FALSE;

    WHILE p_command_list_entry <> NIL DO
      CASE p_command_list_entry^.kind OF

      = clc$library_commands =
        IF p_command_list_entry^.library_contains.panels THEN
          local_library_name := p_command_list_entry^.local_file_name;
          find_form_name (caller_id.ring, form_name, local_library_name, p_form_module, status);
        IFEND;

      = clc$system_commands =
        IF (p_command_list^.system_command_library_lfn <> osc$null_name) AND
              p_command_list^.system_library_contains.panels THEN
          local_library_name := p_command_list^.system_command_library_lfn;
          find_form_name (caller_id.ring, form_name, local_library_name, p_form_module, status);
        IFEND;

        system_library_searched := TRUE;

      = clc$sub_commands =
        clp$find_utility_block (p_command_list_entry^.utility_name, utility_block,
              block_in_current_task);

        IF (utility_block <> NIL) AND block_in_current_task THEN
          IF utility_block^.command_environment.auxiliary_libraries <> NIL THEN
            FOR auxiliary_library_index := 1 TO UPPERBOUND (utility_block^.command_environment.
                  auxiliary_libraries^) DO
              IF utility_block^.command_environment.auxiliary_libraries^ [auxiliary_library_index].
                    contains.panels THEN
                local_library_name := utility_block^.command_environment.auxiliary_libraries^
                      [auxiliary_library_index].name;
                find_form_name (caller_id.ring, form_name, local_library_name, p_form_module, status);
                IF ((NOT status.normal) OR (p_form_module <> NIL)) THEN
                  RETURN;
                IFEND;
              IFEND;
            FOREND;
          IFEND;
        IFEND;

      ELSE
        ;
      CASEND;

      IF ((NOT status.normal) OR (p_form_module <> NIL)) THEN
        RETURN;
      IFEND;

      p_command_list_entry := p_command_list_entry^.next_entry;
    WHILEND;

    IF (NOT system_library_searched) AND (p_command_list^.system_command_library_lfn <> osc$null_name) AND
          p_command_list^.system_library_contains.panels THEN
      local_library_name := osc$null_name;
      find_form_name (caller_id.ring, form_name, local_library_name, p_form_module, status);
      IF ((NOT status.normal) OR (p_form_module <> NIL)) THEN
        RETURN;
      IFEND;
    IFEND;

  PROCEND clp$find_form;
?? TITLE := 'find_form_name', EJECT ??

  PROCEDURE find_form_name
    (    caller_ring: ost$valid_ring;
         form_name: ost$name;
     VAR local_file_name {input, output} : amt$local_file_name;
     VAR p_form_module: ^SEQ ( * );
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = mmc$segment_access_condition =
        IF condition.segment_access_condition.identifier = mmc$sac_io_read_error THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
          EXIT find_form_name;
        IFEND;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT find_form_name;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? TITLE := 'search_form_directory', EJECT ??

    PROCEDURE [INLINE] search_form_directory;

      VAR
        index: llt$command_index,
        lower: llt$command_index,
        temp: integer,
        upper: -1 .. llc$max_commands_in_library;


      lower := 1;
      upper := UPPERBOUND (p_panel_dictionary^);

    /binary_search/
      WHILE (lower <= upper) DO
        temp := lower + upper;
        index := temp DIV 2;
        p_panel_dictionary_item := ^p_panel_dictionary^ [index];

        IF (form_name = p_panel_dictionary_item^.name) THEN
          p_library_member_header := #PTR (p_panel_dictionary_item^.panel_header, p_panel_sequence^);
          p_form_module := #PTR (p_library_member_header^.member, p_panel_sequence^);
          RESET p_form_module;
          RETURN;

        ELSEIF form_name > p_panel_dictionary_item^.name THEN
          lower := index + 1;

        ELSE
          upper := index - 1;
        IFEND;
      WHILEND /binary_search/;

    PROCEND search_form_directory;
?? OLDTITLE, EJECT ??

    VAR
      ignore_validated_file_name: fst$path_handle_name,
      index: llt$message_module_index,
      p_library_list_entry: ^clt$command_library_list_entry,
      p_library_member_header: ^llt$library_member_header,
      p_panel_dictionary: ^llt$panel_dictionary,
      p_panel_dictionary_item: ^llt$panel_dictionary_item,
      p_panel_sequence: ^SEQ ( * );


    status.normal := TRUE;
    p_library_list_entry := NIL;
    #SPOIL (p_library_list_entry);
    p_form_module := NIL;

    clp$open_command_library (caller_ring, local_file_name, p_library_list_entry, ignore_validated_file_name,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$establish_condition_handler (^abort_handler, FALSE);

    p_panel_dictionary := p_library_list_entry^.dictionaries.panel_dictionary;
    IF p_panel_dictionary = NIL THEN
      RETURN;
    IFEND;

    IF caller_ring > p_library_list_entry^.ring_attributes.r2 THEN
      RETURN;
    IFEND;

    p_panel_sequence := p_library_list_entry^.contents;
    search_form_directory;

  PROCEND find_form_name;
?? TITLE := 'clp$find_scl_proc_in_library', EJECT ??
*copyc clh$find_scl_proc_in_library

  PROCEDURE [XDCL, #GATE] clp$find_scl_proc_in_library
    (    object_library: ^SEQ ( * );
         object_library_name: amt$local_file_name;
         procedure_name: ost$name;
     VAR scl_procedure: ^clt$scl_procedure;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);


      CASE condition.selector OF
      = mmc$segment_access_condition =
        IF condition.segment_access_condition.identifier = mmc$sac_io_read_error THEN
          osp$set_status_from_condition ('CL', condition, save_area, status, handler_status);
          EXIT clp$find_scl_proc_in_library;
        IFEND;
      = pmc$user_defined_condition =
        IF condition.user_condition_name = osc$volume_unavailable_cond THEN
          osp$get_condition_status (condition_information, status);
          EXIT clp$find_scl_proc_in_library;
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

    VAR
      command_dictionary_item: ^llt$command_dictionary_item,
      command_header: ^llt$library_member_header,
      function_dictionary_item: ^llt$function_dictionary_item,
      function_header: ^llt$library_member_header,
      i: llt$entry_point_index,
      ignore_status: ost$status,
      dictionaries: llt$library_dictionary_pointers,
      translated_procedure_name: ost$name;


    status.normal := TRUE;
    scl_procedure := NIL;

    osp$establish_condition_handler (^abort_handler, FALSE);
    pmp$get_library_dictionaries (object_library, dictionaries, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF dictionaries.library_version = 'V1.0' THEN
      PUSH dictionaries.command_dictionary: [1 .. UPPERBOUND (dictionaries.entry_point_dictionary^)];
      FOR i := 1 TO UPPERBOUND (dictionaries.entry_point_dictionary^) DO
        pmp$convert_entry_point_to_cmnd (dictionaries.entry_point_dictionary^ [i], i,
              dictionaries.command_dictionary^ [i]);
      FOREND;
    ELSEIF dictionaries.library_version > llc$object_library_version THEN
      osp$set_status_abnormal ('CL', lle$wrong_library_version, llc$object_library_version, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, object_library_name, status);
      RETURN;
    IFEND;

    #TRANSLATE (osv$lower_to_upper, procedure_name, translated_procedure_name);

    IF dictionaries.command_dictionary <> NIL THEN
      search_command_library (dictionaries.command_dictionary, translated_procedure_name,
            command_dictionary_item);
      IF command_dictionary_item <> NIL THEN
        command_header := #PTR (command_dictionary_item^.command_header, object_library^);
        scl_procedure := #PTR (command_header^.member, object_library^);
        RESET scl_procedure;
        RETURN;
      IFEND;
    IFEND;

    IF dictionaries.function_dictionary <> NIL THEN
      search_function_library (dictionaries.function_dictionary, translated_procedure_name,
            function_dictionary_item);
      IF function_dictionary_item <> NIL THEN
        function_header := #PTR (function_dictionary_item^.function_header, object_library^);
        scl_procedure := #PTR (function_header^.member, object_library^);
        RESET scl_procedure;
      IFEND;
    IFEND;

  PROCEND clp$find_scl_proc_in_library;
?? TITLE := 'initialize_library_contains', EJECT ??

  PROCEDURE [INLINE] initialize_library_contains
    (    library_list_entry: ^clt$command_library_list_entry;
     VAR library_contains: clt$command_library_contains);


    library_contains.commands := library_list_entry^.dictionaries.command_dictionary <> NIL;
    library_contains.functions := library_list_entry^.dictionaries.function_dictionary <> NIL;
    library_contains.help_modules := library_list_entry^.dictionaries.help_module_dictionary <> NIL;
    library_contains.message_modules := library_list_entry^.dictionaries.message_module_dictionary <> NIL;
    library_contains.panels := library_list_entry^.dictionaries.panel_dictionary <> NIL;

  PROCEND initialize_library_contains;
*IFEND

MODEND clm$command_list_manager;
