?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter : Signal Handler Module' ??
MODULE clm$scl_signal_handler;

{
{ PURPOSE:
{
{   This module contains the procedures that send and receive signals
{   on behalf of the SCL interpreter.
{
{   The only SCL signal currently defined is used when processing the EXIT
{   control statement if the "target block" of the exit belongs to an
{   ancester of the task issuing the EXIT statement.  The handler for this
{   signal receives control in the "target task", terminates its synchronous
{   child task (which may in turn have to terminate its descendents), then
{   causes the CLC$EXITING_CONDITION in the "target task".
{

?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clc$exiting_condition
*copyc clt$block
*copyc clt$scl_signal
*copyc ost$global_task_id
*copyc ost$status
?? POP ??
*copyc pmp$cause_task_condition
*copyc pmp$get_global_task_id
*copyc pmp$log
*copyc pmp$send_signal
*copyc pmp$terminate
?? TITLE := 'clp$scl_signal_handler', EJECT ??
*copyc clh$scl_signal_handler

  PROCEDURE [XDCL] clp$scl_signal_handler
    (    originator: ost$global_task_id;
         signal: pmt$signal);

    VAR
      ignore_status: ost$status,
      scl_signal: clt$scl_signal;


    scl_signal.signal := signal;
    CASE scl_signal.identifier OF

    = clc$scl_signal =
      CASE scl_signal.contents.kind OF

      = clc$signal_exiting =
        pmp$terminate (scl_signal.contents.child_task_id, ignore_status);
        IF scl_signal.contents.exit_control_block <> NIL THEN
          pmp$cause_task_condition (clc$exiting_condition, scl_signal.contents.exit_control_block,
                {notify_scl=} FALSE, {notify_debug=} FALSE, {propagate_to_parent=} FALSE,
                {call_default_handler=} FALSE, ignore_status);
        IFEND;

      ELSE
        pmp$log ('--  Unexpected SCL signal kind: signal ignored', ignore_status);
      CASEND;

    ELSE
      pmp$log ('--  Unexpected SCL signal identifier: signal ignored', ignore_status);
    CASEND;

  PROCEND clp$scl_signal_handler;
?? TITLE := 'clp$send_exiting_signal', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$send_exiting_signal
    (    target_task_id: pmt$task_id;
         targets_child_task_id: pmt$task_id;
         exit_control_block: ^clt$block;
     VAR status: ost$status);

    VAR
      scl_signal: clt$scl_signal,
      target_gtid: ost$global_task_id;


    pmp$get_global_task_id (target_task_id, target_gtid, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    scl_signal.identifier := clc$scl_signal;
    scl_signal.contents.kind := clc$signal_exiting;
    scl_signal.contents.child_task_id := targets_child_task_id;
    scl_signal.contents.exit_control_block := exit_control_block;

    pmp$send_signal (target_gtid, scl_signal.signal, status);

  PROCEND clp$send_exiting_signal;

MODEND clm$scl_signal_handler;
