?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter : Process When Condition' ??
MODULE clm$process_when_condition;

{
{ PURPOSE:
{   This module contains the routines that search for and invoke when condition processing.
{

?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clc$exiting_condition
*copyc cle$ecc_command_processing
*copyc clt$established_handler_index
*copyc clt$when_condition
*copyc jme$resource_condition
*copyc jme$time_limit_condition
*copyc osc$unseen_mail_condition
*copyc ost$stack_frame_save_area
*copyc ost$status
*copyc pmt$condition
*copyc pmt$condition_information
?? POP ??
*copyc clp$create_procedure_variable
*copyc clp$echo_trace_information
*copyc clp$find_connected_files
*copyc clp$find_current_block
*copyc clp$find_task_block
*copyc clp$get_variable_value
*copyc clp$pop_input_stack
*copyc clp$pop_terminated_blocks
*copyc clp$process_command_file
*copyc clp$push_when_input_block
*copyc clp$put_job_command_response
*copyc clp$restore_work_area_positions
*copyc clp$save_work_area_positions
*copyc clp$trimmed_string_size
*copyc clv$processing_phase
*copyc mmp$verify_access
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$generate_message
*copyc osp$get_status_severity
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$system_error
*copyc pmp$continue_to_cause
*copyc sfp$get_job_limit_name
?? TITLE := 'clp$determine_when_condition', EJECT ??

  PROCEDURE [XDCL] clp$determine_when_condition
    (    condition: pmt$condition;
         condition_information: ^pmt$condition_information;
         save_area: ^ost$stack_frame_save_area;
     VAR when_condition: clt$when_condition_definition;
     VAR status: ost$status);

    VAR
      condition_information_status: ^ost$status;


    status.normal := TRUE;
    when_condition.name := osc$null_name;
    when_condition.status.normal := TRUE;
    when_condition.limit_name := osc$null_name;

    CASE condition.selector OF

    = ifc$interactive_condition =
      CASE condition.interactive_condition OF
      = ifc$job_reconnect =
        when_condition.name := clc$wc_reconnect;
      = ifc$pause_break =
        when_condition.name := clc$wc_pause;
      = ifc$terminal_connection_broken =
        when_condition.name := clc$wc_disconnect;
      = ifc$terminate_break =
        when_condition.name := clc$wc_terminate;
      ELSE
        ;
      CASEND;

    = jmc$job_resource_condition =
      when_condition.name := clc$wc_limit_fault;
      IF condition.job_resource_condition = jmc$time_limit_condition THEN
        when_condition.limit_name := 'CPU_TIME';
        osp$set_status_condition (jme$time_limit_condition, when_condition.status);
      ELSE
        sfp$get_job_limit_name (condition.job_resource_condition, when_condition.limit_name, status);
        IF NOT status.normal THEN
          when_condition.limit_name := 'UNKNOWN_LIMIT';
          status.normal := TRUE;
        IFEND;
        osp$set_status_abnormal ('CL', jme$resource_condition, when_condition.limit_name,
              when_condition.status);
      IFEND;

    = pmc$user_defined_condition =
      IF condition.user_condition_name = osc$unseen_mail_condition THEN
        when_condition.name := clc$wc_unseen_mail;
      ELSEIF (condition.user_condition_name <> clc$wc_exit) AND
            (condition.user_condition_name <> clc$wc_command_fault) AND
            (condition.user_condition_name <> clc$wc_execution_fault) THEN
        when_condition.name := condition.user_condition_name;
        IF (condition_information <> NIL) AND mmp$verify_access (^condition_information, mmc$va_read) THEN

{ Assume condition_information is a pointer to a ost$status record.

          condition_information_status := condition_information;
          when_condition.status := condition_information_status^;
        IFEND;
      IFEND;

    ELSE
      ;
    CASEND;

  PROCEND clp$determine_when_condition;
?? TITLE := 'clp$process_command_fault', EJECT ??

  PROCEDURE [XDCL] clp$process_command_fault
    (    condition_status: ost$status;
         input_block: ^clt$block;
     VAR retry_command: ^clt$command_line;
     VAR condition_processed_state: clt$condition_processed_state;
     VAR status: ost$status);

    VAR
      command: ^clt$command_line,
      command_name: clt$command_name,
      condition_definition: ^clt$when_condition_definition,
      handler_block: ^clt$block,
      handler_statements: ^clt$established_handler_stmnts;


    status.normal := TRUE;
    condition_processed_state := clc$no_handler_established;

    find_handler_block_for_input (input_block, handler_block);
    IF handler_block = NIL THEN
      handler_block := input_block;
      find_next_handler_block (inherited_input, handler_block);
    IFEND;

    condition_definition := NIL;

  /find_command_fault_handler/
    WHILE TRUE DO
      IF (handler_block = NIL) OR ((handler_block^.kind = clc$when_block) AND
            (handler_block^.when_condition^.name = clc$wc_command_fault)) THEN
        RETURN;
      IFEND;

      IF condition_definition = NIL THEN
        PUSH condition_definition;
        condition_definition^.name := clc$wc_command_fault;
        condition_definition^.status := condition_status;
        condition_definition^.limit_name := osc$null_name;
      IFEND;

      find_handler_in_block (any_established_handler, condition_definition^, handler_block,
            handler_statements);
      IF handler_statements <> NIL THEN
        EXIT /find_command_fault_handler/;
      IFEND;

      find_next_handler_block (inherited_input, handler_block);
    WHILEND /find_command_fault_handler/;

    process_when_condition (condition_definition^, TRUE, NIL, input_block^.previous_command.text,
          input_block^.previous_command_name, handler_statements, handler_block, retry_command,
          condition_processed_state, status);

  PROCEND clp$process_command_fault;
?? TITLE := 'clp$process_continued_condition', EJECT ??

  PROCEDURE [XDCL] clp$process_continued_condition
    (    when_block: ^clt$block;
         continue_when_condition_option: clt$condition_processed_state;
     VAR status: ost$status);

    VAR
      condition_definition: ^clt$when_condition_definition,
      handler_block: ^clt$block,
      handler_statements: ^clt$established_handler_stmnts,
      ignore_cond_processed_state: clt$condition_processed_state,
      ignore_retry_command: ^clt$command_line;


    status.normal := TRUE;
    handler_block := when_block^.static_link;

    condition_definition := NIL;

  /try_next_handler_block/
    WHILE TRUE DO
      find_next_handler_block (previous_block, handler_block);

      IF handler_block = NIL THEN
        IF (continue_when_condition_option = clc$continue_next_handler) AND
              (when_block^.when_condition^.default_handler <> NIL) THEN
          when_block^.when_condition^.default_handler^ (status);
        IFEND;
        RETURN;
      ELSEIF (handler_block^.kind = clc$when_block) AND (when_block^.when_condition^.name =
            handler_block^.when_condition^.name) AND (NOT when_block^.when_condition^.status.normal) THEN
        CYCLE /try_next_handler_block/;
      IFEND;

      IF condition_definition = NIL THEN
        PUSH condition_definition;
        condition_definition^.name := when_block^.when_condition^.name;
        condition_definition^.status := when_block^.when_condition^.status;
        condition_definition^.limit_name := when_block^.when_condition^.limit_name;
      IFEND;

      find_handler_in_block (any_established_handler, condition_definition^, handler_block,
            handler_statements);
      IF handler_statements = NIL THEN
        CYCLE /try_next_handler_block/;
      IFEND;

      process_when_condition (condition_definition^, FALSE, when_block^.when_condition^.default_handler,
            ^when_block^.when_condition^.command, when_block^.when_condition^.command_name,
            handler_statements, handler_block, ignore_retry_command, ignore_cond_processed_state, status);
      RETURN;
    WHILEND /try_next_handler_block/;

  PROCEND clp$process_continued_condition;
?? TITLE := 'clp$process_execution_fault', EJECT ??

  PROCEDURE [XDCL] clp$process_execution_fault
    (    condition_status: ost$status;
         input_block: ^clt$block;
     VAR retry_command: ^clt$command_line;
     VAR condition_processed_state: clt$condition_processed_state;
     VAR status: ost$status);

    VAR
      condition_definition: ^clt$when_condition_definition,
      handler_block: ^clt$block,
      handler_statements: ^clt$established_handler_stmnts;


    status.normal := TRUE;
    condition_processed_state := clc$no_handler_established;

    find_handler_block_for_input (input_block, handler_block);
    IF handler_block = NIL THEN
      handler_block := input_block;
      find_next_handler_block (previous_block, handler_block);
    IFEND;

    condition_definition := NIL;

  /find_execution_fault_handler/
    WHILE TRUE DO
      IF (handler_block = NIL) OR ((handler_block^.kind = clc$when_block) AND
            (handler_block^.when_condition^.name = clc$wc_execution_fault)) THEN
        RETURN;
      IFEND;

      IF condition_definition = NIL THEN
        PUSH condition_definition;
        condition_definition^.name := clc$wc_execution_fault;
        condition_definition^.status := condition_status;
        condition_definition^.limit_name := osc$null_name;
      IFEND;

      find_handler_in_block (specific_handler_only, condition_definition^, handler_block, handler_statements);
      IF handler_statements <> NIL THEN
        EXIT /find_execution_fault_handler/;
      IFEND;

      find_next_handler_block (previous_block, handler_block);
    WHILEND /find_execution_fault_handler/;

    process_when_condition (condition_definition^, TRUE, NIL, input_block^.previous_command.text,
          input_block^.previous_command_name, handler_statements, handler_block, retry_command,
          condition_processed_state, status);

  PROCEND clp$process_execution_fault;
?? TITLE := 'clp$process_exit_condition', EJECT ??

  PROCEDURE [XDCL] clp$process_exit_condition
    (    input_block: ^clt$block;
         exit_status: ost$status);

    VAR
      condition_definition: ^clt$when_condition_definition,
      handler_block: ^clt$block,
      handler_statements: ^clt$established_handler_stmnts,
      ignore_cond_processed_state: clt$condition_processed_state,
      ignore_retry_command: ^clt$command_line,
      ignore_status: ost$status;


    find_handler_block_for_input (input_block, handler_block);
    IF (handler_block = NIL) OR ((handler_block^.previous_block^.kind = clc$task_block) AND
          (handler_block^.previous_block^.task_kind = clc$job_monitor_task) AND
          (clv$processing_phase <> clc$command_phase)) THEN
      RETURN;
    IFEND;

    PUSH condition_definition;
    condition_definition^.name := clc$wc_exit;
    condition_definition^.status := exit_status;
    condition_definition^.limit_name := osc$null_name;

    find_handler_in_block (specific_handler_only, condition_definition^, handler_block, handler_statements);
    IF handler_statements = NIL THEN
      RETURN;
    IFEND;

    process_when_condition (condition_definition^, TRUE, NIL, NIL, osc$null_name, handler_statements,
          handler_block, ignore_retry_command, ignore_cond_processed_state, ignore_status);

  PROCEND clp$process_exit_condition;
?? TITLE := 'clp$process_when_cond_in_block', EJECT ??

  PROCEDURE [XDCL] clp$process_when_cond_in_block
    (    condition_definition: clt$when_condition_definition;
         input_block: ^clt$block;
         exit_on_continue_condition: boolean;
     VAR condition_processed: boolean;
     VAR status: ost$status);

    VAR
      command: ^clt$command_line,
      command_name: clt$command_name,
      condition_processed_state: clt$condition_processed_state,
      handler_block: ^clt$block,
      handler_statements: ^clt$established_handler_stmnts,
      ignore_retry_command: ^clt$command_line;


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

    find_handler_block_for_input (input_block, handler_block);
    IF handler_block = NIL THEN
      RETURN;
    IFEND;

    find_handler_in_block (any_established_handler, condition_definition, handler_block, handler_statements);
    IF handler_statements = NIL THEN
      RETURN;
    IFEND;

    find_current_command (command, command_name);

    process_when_condition (condition_definition, exit_on_continue_condition, NIL, command, command_name,
          handler_statements, handler_block, ignore_retry_command, condition_processed_state, status);
    IF NOT status.normal THEN
      condition_processed := FALSE;
    ELSE
      CASE condition_processed_state OF
      = clc$continue_next_handler, clc$continue_next_user_handler =
        condition_processed := NOT exit_on_continue_condition;
      ELSE
        condition_processed := TRUE;
      CASEND;
    IFEND;

  PROCEND clp$process_when_cond_in_block;
?? TITLE := 'clp$process_when_cond_in_task', EJECT ??
*copyc clh$process_when_cond_in_task

  PROCEDURE [XDCL] clp$process_when_cond_in_task
    (    condition_definition: clt$when_condition_definition;
         default_handler: ^procedure (VAR status: ost$status);
     VAR condition_processed: boolean;
     VAR status: ost$status);

    VAR
      command: ^clt$command_line,
      command_name: clt$command_name,
      handler_block: ^clt$block,
      handler_statements: ^clt$established_handler_stmnts,
      ignore_cond_processed_state: clt$condition_processed_state,
      ignore_retry_command: ^clt$command_line;


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

    clp$find_task_block (handler_block, status);
    IF NOT status.normal THEN
      osp$system_error ('Unable to get pointer to SCL Task Block', ^status);
    IFEND;

    WHILE TRUE DO

    /try_next_handler_block/
      BEGIN
        IF handler_block = NIL THEN
          RETURN;
        ELSEIF (handler_block^.kind = clc$when_block) AND (handler_block^.when_condition^.name =
              condition_definition.name) AND (NOT condition_definition.status.normal) THEN
          EXIT /try_next_handler_block/;
        IFEND;

        find_handler_in_block (any_established_handler, condition_definition, handler_block,
              handler_statements);
        IF handler_statements = NIL THEN
          EXIT /try_next_handler_block/;
        IFEND;

        find_current_command (command, command_name);

        process_when_condition (condition_definition, FALSE, default_handler, command, command_name,
              handler_statements, handler_block, ignore_retry_command, ignore_cond_processed_state, status);
        condition_processed := status.normal;
        RETURN;
      END /try_next_handler_block/;

      find_next_handler_block (previous_block, handler_block);
    WHILEND;

  PROCEND clp$process_when_cond_in_task;
?? TITLE := 'find_current_command', EJECT ??

  PROCEDURE [INLINE] find_current_command
    (VAR command: ^clt$command_line;
     VAR command_name: clt$command_name);

    VAR
      block: ^clt$block;


    clp$find_current_block (block);

    WHILE block <> NIL DO
      CASE block^.kind OF
      = clc$command_block, clc$command_proc_block =
        command := ^block^.line_parse.text^ (block^.source.index, block^.source.size);
        command_name := block^.label;
        RETURN;
      = clc$function_proc_block, clc$input_block, clc$when_block =
        command := block^.previous_command.text;
        command_name := block^.previous_command_name;
        RETURN;
      ELSE
        ;
      CASEND;
      block := block^.previous_block;
    WHILEND;

    command := NIL;
    command_name := osc$null_name;

  PROCEND find_current_command;
?? TITLE := 'find_handler_block_for_input', EJECT ??

  PROCEDURE [INLINE] find_handler_block_for_input
    (    input_block: ^clt$block;
     VAR handler_block: ^clt$block);


    handler_block := NIL;

    CASE input_block^.kind OF

    = clc$command_proc_block, clc$function_proc_block =
      handler_block := input_block;

    = clc$input_block =
      IF (input_block^.associated_utility <> NIL) OR ((input_block^.previous_block^.kind = clc$task_block) AND
            ((input_block^.previous_block^.task_kind = clc$task_statement_task) OR
            (input_block^.previous_block^.task_kind = clc$job_monitor_task))) THEN
        handler_block := input_block;
      IFEND;

    = clc$when_block =
      handler_block := input_block;

    ELSE
      ;
    CASEND;

  PROCEND find_handler_block_for_input;
?? TITLE := 'find_handler_in_block', EJECT ??

  PROCEDURE [INLINE] find_handler_in_block
    (    specific_or_generic: (specific_handler_only, any_established_handler);
         condition: clt$when_condition_definition;
         handler_block: ^clt$block;
     VAR handler_statements: ^clt$established_handler_stmnts);

    VAR
      current_ring: ost$valid_ring,
      handler_index: clt$established_handler_index,
      high_index: 0 .. clc$max_established_handlers,
      temp: integer,
      low_index: 1 .. clc$max_established_handlers + 1;


    current_ring := #RING (^current_ring);

    IF handler_block^.established_handler_info.specific_handler_count > 0 THEN
      low_index := 1;
      high_index := handler_block^.established_handler_info.specific_handler_count;

    /search_specific_handlers/
      REPEAT
        temp := low_index + high_index;
        handler_index := temp DIV 2;
        IF condition.name = handler_block^.established_handler_info.specific_handlers^ [handler_index].
              condition THEN

          handler_statements := handler_block^.established_handler_info.specific_handlers^ [handler_index].
                statements;
          IF handler_statements^.establishing_ring = current_ring THEN
            RETURN;
          IFEND;
          EXIT /search_specific_handlers/;

        ELSEIF condition.name > handler_block^.established_handler_info.specific_handlers^ [handler_index].
              condition THEN
          low_index := handler_index + 1;
        ELSE
          high_index := handler_index - 1;
        IFEND;
      UNTIL low_index > high_index {/search_specific_handlers/} ;
    IFEND;

    IF specific_or_generic = any_established_handler THEN
      IF (NOT condition.status.normal) AND (handler_block^.established_handler_info.any_fault_handler <> NIL)
            THEN
        handler_statements := handler_block^.established_handler_info.any_fault_handler;
        IF handler_statements^.establishing_ring = current_ring THEN
          RETURN;
        IFEND;
      IFEND;

      IF handler_block^.established_handler_info.any_condition_handler <> NIL THEN
        handler_statements := handler_block^.established_handler_info.any_condition_handler;
        IF handler_statements^.establishing_ring = current_ring THEN
          RETURN;
        IFEND;
      IFEND;
    IFEND;

    handler_statements := NIL;

  PROCEND find_handler_in_block;
?? TITLE := 'find_next_handler_block', EJECT ??

  PROCEDURE [INLINE] find_next_handler_block
    (    follow_linkage: (previous_block, inherited_input);
     VAR handler_block {input, output} : ^clt$block);


    WHILE TRUE DO
      IF follow_linkage = previous_block THEN
        handler_block := handler_block^.previous_block;
        IF handler_block = NIL THEN
          RETURN;
        IFEND;
      ELSEIF handler_block^.inherited_input.found THEN
        handler_block := handler_block^.inherited_input.block;
      ELSE
        handler_block := NIL;
        RETURN;
      IFEND;

      CASE handler_block^.kind OF
      = clc$command_proc_block, clc$function_proc_block, clc$when_block =
        RETURN;
      = clc$input_block =
        IF (handler_block^.associated_utility <> NIL) OR ((handler_block^.previous_block^.kind =
              clc$task_block) AND ((handler_block^.previous_block^.task_kind = clc$task_statement_task) OR
              (handler_block^.previous_block^.task_kind = clc$job_monitor_task))) THEN
          RETURN;
        IFEND;
      ELSE
        ;
      CASEND;
    WHILEND;

  PROCEND find_next_handler_block;
?? TITLE := 'process_when_condition', EJECT ??

  PROCEDURE process_when_condition
    (    condition_definition: clt$when_condition_definition;
         exit_on_continue_condition: boolean;
         default_handler: ^procedure (VAR status: ost$status);
         command: ^clt$command_line;
         command_name: clt$command_name;
         handler_statements: ^clt$established_handler_stmnts;
         handler_block: ^clt$block;
     VAR retry_command: ^clt$command_line;
     VAR condition_processed_state: clt$condition_processed_state;
     VAR status: ost$status);

    VAR
      connected_files: ^clt$connected_files,
      end_when_block: ^clt$block,
      ignore_status: ost$status,
      saved_work_area_positions: clt$saved_work_area_positions,
      severity: ost$status_severity,
      static_link_handle: clt$block_handle,
      when_block: ^clt$block;

?? NEWTITLE := 'condition_handler', EJECT ??

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

      VAR
        exit_control_block: ^clt$block,
        ignore_status: ost$status,
        run_time_status: ^ost$status;


      CASE condition.selector OF

      = pmc$block_exit_processing =

{ --- Handle block exit.

        IF when_block = NIL THEN
          RETURN;
        IFEND;

        clp$pop_terminated_blocks (when_block, status);
        clp$process_exit_condition (when_block, status);

        IF when_block^.input_can_be_echoed THEN
          clp$find_connected_files (connected_files);
          IF connected_files^.echo_count > 0 THEN
            clp$echo_trace_information ('CLC$ECHO_CONDITION_END', ^when_block^.when_condition^.name, NIL,
                  ^status, ignore_status);
          IFEND;
        IFEND;

        clp$restore_work_area_positions (saved_work_area_positions, ignore_status);

        IF (condition_processed_state = clc$continue_retry) AND
              ((condition_definition.name = clc$wc_command_fault) OR
              (condition_definition.name = clc$wc_execution_fault)) THEN
          get_retry_command;
        IFEND;

        clp$pop_input_stack (end_when_block, ignore_status);

      = pmc$user_defined_condition =
        IF condition.user_condition_name = clc$exiting_condition THEN

{ --- Handle exit initiated via command level EXIT statement.
{
{ This condition is raised in the task that "owns" the SCL block which is the
{ target of the EXIT statement.
{ This condition is specifically dealt with in the condition handlers that
{ cover processing of the various kinds of input, command and function blocks.
{ The condition_information for this condition is a pointer to the outermost
{ block which is being exited and has such a corresponding condition handler.
{ The handler which is "covering" this "exit_control_block" performs a
{ non-local (CYBIL) exit out of its establishing procedure.
{ Other such handlers simply "continue" the condition.

          exit_control_block := condition_information;

          IF (#OFFSET (exit_control_block) = #OFFSET (handler_block)) AND
                (condition_definition.name = clc$wc_exit) THEN

{ This instance of process_when_condition is already dealing with the EXIT
{ condition for the target block of the EXIT statement.  Therefore, the EXIT
{ statement should be treated as though its target was the WHEN/WHENEND block.

            EXIT process_when_condition;
          IFEND;

          IF #OFFSET (exit_control_block) <> #OFFSET (when_block) THEN
            pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
          IFEND;
          EXIT process_when_condition;

        ELSE

{ --- "Continue" any other user defined condition.

          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
          RETURN;
        IFEND;

      ELSE

{ --- "Continue" any other condition.

        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        RETURN;
      CASEND;

    PROCEND condition_handler;
?? TITLE := 'get_retry_command', EJECT ??

    PROCEDURE get_retry_command;

      VAR
        local_status: ost$status,
        variable_value: ^clt$data_value;


      clp$get_variable_value ('OSV$COMMAND', variable_value, local_status);
      IF local_status.normal AND (variable_value^.kind = clc$string) AND
            (variable_value^.string_value^ <> when_block^.when_condition^.command) THEN
        retry_command := variable_value^.string_value;
      IFEND;

    PROCEND get_retry_command;
?? TITLE := 'initialize_handler_variables', EJECT ??

    PROCEDURE initialize_handler_variables;

{ TYPE
{   name_string_type = string 0..osc$max_name_size
{ TYPEND

?? PUSH (LISTEXT := ON) ??

      VAR
        name_string_type: [STATIC, READ, cls$declaration_section] record
          header: clt$type_specification_header,
          qualifier: clt$string_type_qualifier,
        recend := [[1, 0, clc$string_type], [0, osc$max_name_size, FALSE]];

?? POP ??

{ TYPE
{   name_type = name
{ TYPEND

?? PUSH (LISTEXT := ON) ??

      VAR
        name_type: [STATIC, READ, cls$declaration_section] record
          header: clt$type_specification_header,
          qualifier: clt$name_type_qualifier,
        recend := [[1, 0, clc$name_type], [1, osc$max_name_size]];

?? POP ??

{ TYPE
{   status_type = status
{ TYPEND

?? PUSH (LISTEXT := ON) ??

      VAR
        status_type: [STATIC, READ, cls$declaration_section] record
          header: clt$type_specification_header,
        recend := [[1, 0, clc$status_type]];

?? POP ??

{ TYPE
{   string_type = string
{ TYPEND

?? PUSH (LISTEXT := ON) ??

      VAR
        string_type: [STATIC, READ, cls$declaration_section] record
          header: clt$type_specification_header,
          qualifier: clt$string_type_qualifier,
        recend := [[1, 0, clc$string_type], [0, clc$max_string_size, FALSE]];

?? POP ??

      VAR
        initial_value: clt$data_value;


      status.normal := TRUE;

      initial_value.kind := clc$name;
      initial_value.name_value := condition_definition.name;
      clp$create_procedure_variable ('OSV$CONDITION', clc$local_scope, clc$read_write,
            clc$immediate_evaluation, #SEQ (name_type), ^initial_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF condition_definition.name = clc$wc_limit_fault THEN
        initial_value.kind := clc$name;
        initial_value.name_value := condition_definition.limit_name;
        clp$create_procedure_variable ('OSV$LIMIT_NAME', clc$local_scope, clc$read_write,
              clc$immediate_evaluation, #SEQ (name_type), ^initial_value, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;

      initial_value.kind := clc$status;
      initial_value.status_value := ^condition_definition.status;
      clp$create_procedure_variable ('OSV$STATUS', clc$local_scope, clc$read_write,
            clc$immediate_evaluation, #SEQ (status_type), ^initial_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      initial_value.kind := clc$string;
      IF command = NIL THEN
        PUSH initial_value.string_value: [0];
      ELSE
        initial_value.string_value := ^command^ (1, clp$trimmed_string_size (command^));
      IFEND;
      clp$create_procedure_variable ('OSV$COMMAND', clc$local_scope, clc$read_write,
            clc$immediate_evaluation, #SEQ (string_type), ^initial_value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF command_name <> osc$null_name THEN

{ OSV$COMMAND_NAME is created just for backward compatibility.

        initial_value.kind := clc$string;
        initial_value.string_value := ^command_name (1, clp$trimmed_string_size (command_name));
        clp$create_procedure_variable ('OSV$COMMAND_NAME', clc$local_scope, clc$read_write,
              clc$immediate_evaluation, #SEQ (name_string_type), ^initial_value, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;

    PROCEND initialize_handler_variables;
?? OLDTITLE, EJECT ??

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

    clp$save_work_area_positions (saved_work_area_positions);

    when_block := NIL;
    #SPOIL (when_block);
    osp$establish_condition_handler (^condition_handler, TRUE);

  /call_handler/
    BEGIN
      static_link_handle.segment_offset := #OFFSET (handler_block);
      static_link_handle.assignment_counter := handler_block^.assignment_counter;

      clp$push_when_input_block (condition_definition, exit_on_continue_condition, default_handler, command,
            command_name, handler_statements, static_link_handle, when_block);

      initialize_handler_variables;
      IF NOT status.normal THEN
        clp$pop_input_stack (when_block, ignore_status);
        EXIT /call_handler/;
      IFEND;

      IF when_block^.input_can_be_echoed THEN
        clp$find_connected_files (connected_files);
        IF connected_files^.echo_count > 0 THEN
          clp$echo_trace_information ('CLC$ECHO_CONDITION_BEGIN', ^when_block^.when_condition^.name, NIL,
                ^condition_definition.status, ignore_status);
        IFEND;
      IFEND;

      clp$process_command_file (when_block, NIL, status);
      condition_processed_state := when_block^.when_condition^.condition_processed_state;
      IF status.normal AND (NOT when_block^.being_exited) THEN
        clp$find_current_block (end_when_block);
        IF end_when_block <> when_block THEN
          osp$set_status_abnormal ('CL', cle$unbalanced_block_structure, when_block^.kind_end_name, status);
          osp$append_status_parameter (osc$status_parameter_delimiter, end_when_block^.kind_end_name, status);
        IFEND;
      IFEND;

      clp$pop_terminated_blocks (when_block, status);
      clp$process_exit_condition (when_block, status);

      IF when_block^.input_can_be_echoed THEN
        clp$find_connected_files (connected_files);
        IF connected_files^.echo_count > 0 THEN
          clp$echo_trace_information ('CLC$ECHO_CONDITION_END', ^when_block^.when_condition^.name, NIL,
                ^status, ignore_status);
        IFEND;
      IFEND;

      clp$restore_work_area_positions (saved_work_area_positions, ignore_status);

      IF (condition_processed_state = clc$continue_retry) AND
            ((condition_definition.name = clc$wc_command_fault) OR
            (condition_definition.name = clc$wc_execution_fault)) THEN
        get_retry_command;
      IFEND;

      IF status.normal THEN
        clp$pop_input_stack (end_when_block, status);
      ELSE
        clp$pop_input_stack (end_when_block, ignore_status);
      IFEND;
    END /call_handler/;

    osp$disestablish_cond_handler;

    IF NOT status.normal THEN
      severity := osc$error_status;
      osp$get_status_severity (status.condition, severity, ignore_status);
      IF severity >= osc$error_status THEN
        clp$put_job_command_response (' --WHEN/WHENEND condition handler failed for following reason:',
              ignore_status);
        osp$generate_message (status, ignore_status);
        condition_processed_state := clc$no_handler_established;
      IFEND;
    IFEND;

  PROCEND process_when_condition;

MODEND clm$process_when_condition;
