?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Job Management: Queue File Output Internal Interfaces' ??
MODULE qfm$queue_file_output_manager;

{ PURPOSE:
{   This module contains the Queue File Management system core interfaces for managing files in the
{ output queue and the Known Output List (KOL).
{
{ DESIGN:
{   These procedures execute in ring one and can be called from ring 3.  These procedures access
{ the ring one table the Known Output List (KOL).  It is contained in mainframe pageable.  A signature
{ lock is used in order to ensure synchronous access to the KOL.

?? NEWTITLE := 'Global Declarations Referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc jmc$job_management_id
*copyc jmc$kol_maximum_entries
*copyc jmc$maximum_output_count
*copyc jmc$output_queue_full_message
*copyc jme$queued_file_conditions
*copyc jmt$clock_time
*copyc jmt$destination_usage
*copyc jmt$job_attributes
*copyc jmt$known_output_list
*copyc jmt$known_output_list_entry
*copyc jmt$kol_entry_kind
*copyc jmt$kol_entry_kind_set
*copyc jmt$kol_index
*copyc jmt$name
*copyc jmt$name_list
*copyc jmt$output_attribute_options
*copyc jmt$output_count_range
*copyc jmt$output_counts
*copyc jmt$output_descriptor
*copyc jmt$output_state
*copyc jmt$output_state_set
*copyc jmt$output_status_count
*copyc jmt$output_status_options
*copyc jmt$output_status_results
*copyc jmt$output_system_id
*copyc jmt$output_system_label
*copyc jmt$queue_file_password
*copyc jmt$release_output_file_list
*copyc jmt$reprint_disposition
*copyc jmt$results_keys
*copyc jmt$system_supplied_name
*copyc jmt$work_area
*copyc oss$mainframe_pageable
*copyc oss$mainframe_paged_literal
*copyc ost$byte
*copyc ost$global_task_id
*copyc ost$halfword
*copyc ost$signature_lock
*copyc ost$status
*copyc ost$user_identification
?? POP ??
*copyc dpp$put_critical_message
*copyc osp$clear_mainframe_sig_lock
*copyc osp$monitor_fault_to_status
*copyc osp$set_mainframe_sig_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$test_sig_lock
*copyc pmp$get_executing_task_gtid
*copyc pmp$get_mainframe_id
*copyc pmp$ready_task
*copyc pmp$zero_out_table
*copyc syp$continue_to_cause
*copyc syp$disestablish_cond_handler
*copyc syp$establish_condition_handler
?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

  VAR
    jmv$output_file_recovery_option: [XDCL, #GATE, oss$mainframe_pageable] ost$byte := 0,
    jmv$time_to_purge_expired_file: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    jmv$time_to_purge_printed_file: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    jmv$time_to_ready_deferred_file: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    jmv$known_output_list: [XDCL, #GATE, oss$mainframe_pageable] jmt$known_output_list,
    jmv$kol_p: [XDCL, #GATE, oss$mainframe_pageable] ^array [1 .. * ] of jmt$known_output_list_entry := NIL,
    jmv$maximum_known_outputs: [XDCL, #GATE, oss$mainframe_pageable] ost$halfword := 150,
    qfv$current_kol_limit: [XDCL, #GATE, oss$mainframe_pageable] jmt$kol_index := 0,
    qfv$kol_lock: [XDCL, oss$mainframe_pageable] ost$signature_lock;

?? TITLE := 'convert_state_to_entry_kind', EJECT ??

{ PURPOSE:
{   The purpose of this request is to convert an output state to its Known Output List entry-kind
{ equivalent.

  PROCEDURE convert_state_to_entry_kind
    (    output_state: jmt$output_state;
     VAR kol_entry_kind: jmt$kol_entry_kind;
     VAR status: ost$status);

    status.normal := TRUE;
    CASE output_state OF
    = jmc$deferred_output =
      kol_entry_kind := jmc$kol_deferred_entry;

    = jmc$queued_output =
      kol_entry_kind := jmc$kol_queued_entry;

    = jmc$initiated_output =
      kol_entry_kind := jmc$kol_initiated_entry;

    = jmc$terminated_output =
      kol_entry_kind := jmc$kol_terminated_entry;

    = jmc$completed_output =
      kol_entry_kind := jmc$kol_completed_entry;
    ELSE
      osp$set_status_abnormal (jmc$job_management_id, jme$invalid_output_state, '', status);
    CASEND;
  PROCEND convert_state_to_entry_kind;
?? OLDTITLE ??
?? NEWTITLE := 'expand_kol', EJECT ??

{ PURPOSE:
{   The purpose of this request is to extend the initialized portion of the
{ Known Output List (KOL).  If the KOL is at its limit, this request does nothing.
{
{ CAUTION:  This request cannot be performed in a loop in ring one.  If
{           several entries must be added to the KOL this request must be
{           called from ring 3.  The reason for this is because pages
{           assigned in ring 1 do not get backing store until the ring is
{           exited.  So if too many new pages are added to the KOL, memory
{           may be exhausted and the system will crash or hang.

  PROCEDURE expand_kol;

    CONST
      expand_increment = 100;

    VAR
      kol_index: jmt$kol_index,
      new_kol_limit: jmt$kol_index;

    IF qfv$current_kol_limit < jmc$kol_maximum_entries THEN
      IF qfv$current_kol_limit + expand_increment > jmc$kol_maximum_entries THEN
        new_kol_limit := jmc$kol_maximum_entries;
      ELSE
        new_kol_limit := qfv$current_kol_limit + expand_increment;
      IFEND;
      FOR kol_index := qfv$current_kol_limit + 1 TO new_kol_limit - 1 DO
        jmv$kol_p^ [kol_index].forward_link := kol_index + 1;
        jmv$kol_p^ [kol_index].reverse_link := kol_index - 1;
        jmv$kol_p^ [kol_index].entry_kind := jmc$kol_unused_entry;
      FOREND;
      jmv$kol_p^ [new_kol_limit].forward_link := jmc$kol_undefined_index;
      jmv$kol_p^ [new_kol_limit].reverse_link := new_kol_limit - 1;
      jmv$kol_p^ [new_kol_limit].entry_kind := jmc$kol_unused_entry;

      jmv$known_output_list.state_data [jmc$kol_unused_entry].number_of_entries :=
            jmv$known_output_list.state_data [jmc$kol_unused_entry].number_of_entries + new_kol_limit -
            qfv$current_kol_limit;
      IF jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry = jmc$kol_undefined_index THEN
        jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry := qfv$current_kol_limit + 1;
        jmv$kol_p^ [qfv$current_kol_limit + 1].reverse_link := jmc$kol_undefined_index;
        jmv$known_output_list.state_data [jmc$kol_unused_entry].last_entry := new_kol_limit;

      ELSE
        jmv$kol_p^ [qfv$current_kol_limit + 1].reverse_link := jmv$known_output_list.
              state_data [jmc$kol_unused_entry].last_entry;
        jmv$kol_p^ [jmv$known_output_list.state_data [jmc$kol_unused_entry].last_entry].forward_link :=
              qfv$current_kol_limit + 1;
        jmv$known_output_list.state_data [jmc$kol_unused_entry].last_entry := new_kol_limit;
      IFEND;
      qfv$current_kol_limit := new_kol_limit;
    IFEND;
  PROCEND expand_kol;
?? OLDTITLE ??
?? NEWTITLE := 'find_destination_usage', EJECT ??

{ PURPOSE:
{   The purpose of this request is to find the specified destination_usage in the application table
{ and return with the application index.  If there is no application registered for the destination_usage
{ specified the value jmc$unassigned_output_index is returned.
{
{ DESIGN:
{   Starting with the index of the last application assigned, search backwards through the chain until
{ the destination_usage is found or there are no more applications to search.
{
{ NOTES:
{   The Known Output List (KOL) MUST be locked when this request is made.

  PROCEDURE find_destination_usage
    (    destination_usage: jmt$destination_usage;
     VAR application_index: jmt$output_application_index);

    application_index := UPPERBOUND (jmv$known_output_list.application_table);

    WHILE (jmv$known_output_list.application_table [application_index].destination_usage <>
          destination_usage) AND (application_index <> jmc$unassigned_output_index) DO
      application_index := application_index - 1;
    WHILEND;
  PROCEND find_destination_usage;
?? TITLE := 'find_output_file_by_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to find a file assigned to a particular application by using its
{ system_file_name.
{
{ DESIGN:
{   Search the Known Output List (KOL) for the file that has been assigned to the application specified.
{ If the entry in the KOL is not found, return a kol_index of jmc$kol_undefined_index.
{
{ NOTES:
{   The KOL must be locked when this request is issued.

  PROCEDURE find_output_file_by_application
    (    system_file_name: jmt$system_supplied_name;
         application_index: jmt$output_application_index;
     VAR kol_index: jmt$kol_index);

    VAR
      application_state: jmt$kol_application_state;

  /search_for_the_specified_file/
    FOR application_state := SUCC (jmc$kol_application_unused) TO UPPERVALUE (application_state) DO
      kol_index := jmv$known_output_list.application_table [application_index].state_data [application_state].
            first_entry;
      WHILE kol_index <> jmc$kol_undefined_index DO
        IF jmv$kol_p^ [kol_index].system_file_name = system_file_name THEN
          EXIT /search_for_the_specified_file/;
        ELSE
          kol_index := jmv$kol_p^ [kol_index].application_forward_link;
        IFEND;
      WHILEND;
    FOREND /search_for_the_specified_file/;
  PROCEND find_output_file_by_application;
?? OLDTITLE ??
?? NEWTITLE := 'kol_search', EJECT ??

{ PURPOSE:
{   The purpose of this request is to search the Known Output List (KOL) for the specified system_file_name
{ and returns the file's kol_index.  A kol_index of jmc$kol_undefined_index is returned if the output file
{ is not found.
{
{ NOTES:
{   The KOL must be locked when this request is issued.

  PROCEDURE kol_search
    (    system_file_name: jmt$system_supplied_name;
         entry_kind_set: jmt$kol_entry_kind_set;
     VAR kol_index: jmt$kol_index);

    VAR
      kol_entry_kind: jmt$kol_entry_kind;

    kol_index := jmc$kol_undefined_index;

  /kol_search_each_entry_kind/
    FOR kol_entry_kind := SUCC (LOWERVALUE (kol_entry_kind)) TO UPPERVALUE (kol_entry_kind) DO
      IF kol_entry_kind IN entry_kind_set THEN
        kol_index := jmv$known_output_list.state_data [kol_entry_kind].first_entry;

        WHILE kol_index <> jmc$kol_undefined_index DO
          IF (jmv$kol_p^ [kol_index].system_file_name = system_file_name) THEN
            EXIT /kol_search_each_entry_kind/;
          ELSE
            kol_index := jmv$kol_p^ [kol_index].forward_link;
          IFEND;
        WHILEND;
      IFEND;
    FOREND /kol_search_each_entry_kind/;
  PROCEND kol_search;
?? OLDTITLE ??
?? NEWTITLE := 'notify_output_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to ready an output application's control task.
{
{ NOTES:
{   The Known Output List (KOL) should be locked when this request is issued in order to ensure that
{ the global_task_id in the KOL's application table is valid.  If it isn't, the results will be to
{ cause a task to become ready before its scheduled time.  This is not generally a problem.
{ With this in mind, it is okay to make this request without the KOL locked, but it is preferred to
{ have the structure locked.

  PROCEDURE notify_output_application
    (    application_index: jmt$output_application_index);

    VAR
      ignore_status: ost$status;

    IF application_index <> jmc$unassigned_output_index THEN
      pmp$ready_task (jmv$known_output_list.application_table [application_index].global_task_id,
            ignore_status);
    IFEND;
  PROCEND notify_output_application;
?? TITLE := 'relink_kol_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to relink a Known Output List (KOL) entry from one application state
{ thread to another.
{
{ DESIGN:
{   Upon entry to the procedure, the KOL entry contains the destination_usage and application_state that
{ defines the application thread that the entry belongs to.  The entry is removed from this thread and
{ added to the thread described by the destination_usage and destination_state supplied on the request.
{
{ NOTES:
{   The KOL must be locked when this request is issued.

  PROCEDURE relink_kol_application
    (    kol_index: jmt$kol_index;
         destination_application_index: jmt$output_application_index;
         destination_state: jmt$kol_application_state);

    VAR
      source_state: jmt$kol_application_state,
      source_application_index: jmt$output_application_index;

    find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, source_application_index);
    source_state := jmv$kol_p^ [kol_index].application_state;

    CASE source_state OF
    = jmc$kol_application_unused =
      ;

    ELSE

{ Delete the entry from its application thread.

      IF jmv$kol_p^ [kol_index].application_reverse_link = jmc$kol_undefined_index THEN
        jmv$known_output_list.application_table [source_application_index].state_data [source_state].
              first_entry := jmv$kol_p^ [kol_index].application_forward_link;
      ELSE
        jmv$kol_p^ [jmv$kol_p^ [kol_index].application_reverse_link].
              application_forward_link := jmv$kol_p^ [kol_index].application_forward_link;
      IFEND;

      IF jmv$kol_p^ [kol_index].application_forward_link = jmc$kol_undefined_index THEN
        jmv$known_output_list.application_table [source_application_index].state_data [source_state].
              last_entry := jmv$kol_p^ [kol_index].application_reverse_link;
      ELSE
        jmv$kol_p^ [jmv$kol_p^ [kol_index].application_forward_link].
              application_reverse_link := jmv$kol_p^ [kol_index].application_reverse_link;
      IFEND;

{ Decrement the count for the application/state thread

      jmv$known_output_list.application_table [source_application_index].state_data [source_state].
            number_of_entries := jmv$known_output_list.application_table [source_application_index].
            state_data [source_state].number_of_entries - 1;
    CASEND;


    CASE destination_state OF

    = jmc$kol_application_unused =

{ Make the entry unused.

      jmv$kol_p^ [kol_index].application_reverse_link := jmc$kol_undefined_index;
      jmv$kol_p^ [kol_index].application_forward_link := jmc$kol_undefined_index;

    ELSE

{ Insert the entry at the end of the destination thread.

      IF jmv$known_output_list.application_table [destination_application_index].
            state_data [destination_state].last_entry = jmc$kol_undefined_index THEN
        jmv$kol_p^ [kol_index].application_reverse_link := jmc$kol_undefined_index;
        jmv$kol_p^ [kol_index].application_forward_link := jmc$kol_undefined_index;
        jmv$known_output_list.application_table [destination_application_index].
              state_data [destination_state].first_entry := kol_index;
        jmv$known_output_list.application_table [destination_application_index].
              state_data [destination_state].last_entry := kol_index;
      ELSE
        jmv$kol_p^ [kol_index].application_reverse_link := jmv$known_output_list.
              application_table [destination_application_index].state_data [destination_state].last_entry;
        jmv$kol_p^ [jmv$known_output_list.application_table [destination_application_index].
              state_data [destination_state].last_entry].application_forward_link := kol_index;
        jmv$kol_p^ [kol_index].application_forward_link := jmc$kol_undefined_index;
        jmv$known_output_list.application_table [destination_application_index].
              state_data [destination_state].last_entry := kol_index;
      IFEND;

{ Increment the count of the number of entries in the state

      jmv$known_output_list.application_table [destination_application_index].state_data [destination_state].
            number_of_entries := jmv$known_output_list.application_table [destination_application_index].
            state_data [destination_state].number_of_entries + 1;
    CASEND;

    jmv$kol_p^ [kol_index].application_state := destination_state;

  PROCEND relink_kol_application;
?? TITLE := 'relink_kol_entry', EJECT ??

{ PURPOSE:
{   The purpose of this request is to relink a Known Output List (KOL) entry from one entry state chain to
{ another.
{
{ DESIGN:
{   The entry state in the KOL entry is used to determine the state thread that the entry is currently in.
{ The entry state chain is maintained as a doubly linked list so it can be searched backwards.
{
{ NOTES:
{   The KOL must be locked when this request is issued.

  PROCEDURE relink_kol_entry
    (    kol_index: jmt$kol_index;
         destination_entry_kind: jmt$kol_entry_kind);

    VAR
      source_entry_kind: jmt$kol_entry_kind,
      insertion_index: jmt$kol_index;

    source_entry_kind := jmv$kol_p^ [kol_index].entry_kind;

{ Delete the entry from its thread

    IF jmv$kol_p^ [kol_index].reverse_link = jmc$kol_undefined_index THEN
      jmv$known_output_list.state_data [source_entry_kind].first_entry := jmv$kol_p^ [kol_index].forward_link;
    ELSE
      jmv$kol_p^ [jmv$kol_p^ [kol_index].reverse_link].forward_link := jmv$kol_p^ [kol_index].forward_link;
    IFEND;

    IF jmv$kol_p^ [kol_index].forward_link = jmc$kol_undefined_index THEN
      jmv$known_output_list.state_data [source_entry_kind].last_entry := jmv$kol_p^ [kol_index].reverse_link;
    ELSE
      jmv$kol_p^ [jmv$kol_p^ [kol_index].forward_link].reverse_link := jmv$kol_p^ [kol_index].reverse_link;
    IFEND;

{ Decrement the count of the number of entries in the state

    jmv$known_output_list.state_data [source_entry_kind].number_of_entries :=
          jmv$known_output_list.state_data [source_entry_kind].number_of_entries - 1;

{ Add the entry to the destination thread

    CASE destination_entry_kind OF

    = jmc$kol_unused_entry =

{ First, zero out the entry so "clag" doesn't show up

      pmp$zero_out_table (^jmv$kol_p^ [kol_index], #SIZE (jmv$kol_p^ [kol_index]));

{ Insert in the "unused" thread.  Trace backwards to find the next previous unused entry to insert after.

      insertion_index := kol_index - 1;
      WHILE (insertion_index <> jmc$kol_undefined_index) AND
            (jmv$kol_p^ [insertion_index].entry_kind <> jmc$kol_unused_entry) DO
        insertion_index := insertion_index - 1;
      WHILEND;
      IF insertion_index = jmc$kol_undefined_index THEN

{ Insert at the "head" of the unused thread

        jmv$kol_p^ [kol_index].reverse_link := jmc$kol_undefined_index;
        jmv$kol_p^ [kol_index].forward_link := jmv$known_output_list.state_data [jmc$kol_unused_entry].
              first_entry;
        jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry := kol_index;
        IF jmv$kol_p^ [kol_index].forward_link <> jmc$kol_undefined_index THEN
          jmv$kol_p^ [jmv$kol_p^ [kol_index].forward_link].reverse_link := kol_index;
        IFEND;
      ELSE

{ Insert in the unused thread.

        jmv$kol_p^ [kol_index].reverse_link := insertion_index;
        jmv$kol_p^ [kol_index].forward_link := jmv$kol_p^ [insertion_index].forward_link;
        jmv$kol_p^ [jmv$kol_p^ [kol_index].forward_link].reverse_link := kol_index;
        jmv$kol_p^ [insertion_index].forward_link := kol_index;
      IFEND;

    ELSE

{ Insert at the end of the destination thread.

      IF jmv$known_output_list.state_data [destination_entry_kind].last_entry = jmc$kol_undefined_index THEN
        jmv$kol_p^ [kol_index].reverse_link := jmc$kol_undefined_index;
        jmv$kol_p^ [kol_index].forward_link := jmc$kol_undefined_index;
        jmv$known_output_list.state_data [destination_entry_kind].first_entry := kol_index;
        jmv$known_output_list.state_data [destination_entry_kind].last_entry := kol_index;
      ELSE
        jmv$kol_p^ [kol_index].reverse_link := jmv$known_output_list.state_data [destination_entry_kind].
              last_entry;
        jmv$kol_p^ [jmv$known_output_list.state_data [destination_entry_kind].last_entry].forward_link :=
              kol_index;
        jmv$kol_p^ [kol_index].forward_link := jmc$kol_undefined_index;
        jmv$known_output_list.state_data [destination_entry_kind].last_entry := kol_index;
      IFEND;
    CASEND;

{ Increment the count for the destination thread.

    jmv$known_output_list.state_data [destination_entry_kind].number_of_entries :=
          jmv$known_output_list.state_data [destination_entry_kind].number_of_entries + 1;

    jmv$kol_p^ [kol_index].entry_kind := destination_entry_kind;
  PROCEND relink_kol_entry;
?? TITLE := 'validate_application_access', EJECT ??

{ PURPOSE:
{    This request will validate that the executing task is the legitimate user of the destination usage
{  specified.  The index into the application table for the specified destination_usage is returned.
{
{ NOTES:
{   The Known Output List (KOL) must be locked when this request is issued.

  PROCEDURE validate_application_access
    (    destination_usage: jmt$destination_usage;
     VAR application_index: jmt$output_application_index;
     VAR status: ost$status);

    VAR
      global_task_id: ost$global_task_id;

    status.normal := TRUE;
    find_destination_usage (destination_usage, application_index);
    IF application_index = jmc$unassigned_output_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$destination_usage_incorrect, destination_usage,
            status);
    ELSE
      pmp$get_executing_task_gtid (global_task_id);
      IF global_task_id <> jmv$known_output_list.application_table [application_index].global_task_id THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$application_not_permitted, destination_usage,
              status);
      IFEND;
    IFEND;
  PROCEND validate_application_access;
?? TITLE := '[XDCL, #GATE] qfp$acquire_modified_output', EJECT ??
*copy qfh$acquire_modified_output

  PROCEDURE [XDCL, #GATE] qfp$acquire_modified_output
    (    output_destination_usage: jmt$destination_usage;
     VAR output_descriptor: jmt$output_descriptor;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    validate_application_access (output_destination_usage, application_index, status);
    IF status.normal THEN
      kol_index := jmv$known_output_list.application_table [application_index].
            state_data [jmc$kol_application_modified].first_entry;
      IF kol_index <> jmc$kol_undefined_index THEN
        output_descriptor.system_file_name := jmv$kol_p^ [kol_index].system_file_name;
        output_descriptor.user_file_name := jmv$kol_p^ [kol_index].user_file_name;
        relink_kol_application (kol_index, application_index, jmc$kol_application_acquired);
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$output_queue_is_empty, '', status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$acquire_modified_output;
?? TITLE := '[XDCL, #GATE] qfp$acquire_new_output', EJECT ??
*copyc qfh$acquire_new_output

  PROCEDURE [XDCL, #GATE] qfp$acquire_new_output
    (    output_destination_usage: jmt$destination_usage;
     VAR output_descriptor: jmt$output_descriptor;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    validate_application_access (output_destination_usage, application_index, status);
    IF status.normal THEN
      kol_index := jmv$known_output_list.application_table [application_index].
            state_data [jmc$kol_application_new].first_entry;
      IF kol_index <> jmc$kol_undefined_index THEN
        output_descriptor.system_file_name := jmv$kol_p^ [kol_index].system_file_name;
        output_descriptor.user_file_name := jmv$kol_p^ [kol_index].user_file_name;
        relink_kol_application (kol_index, application_index, jmc$kol_application_acquired);
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$output_queue_is_empty, '', status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$acquire_new_output;
?? TITLE := '[XDCL, #GATE] qfp$change_output_attributes', EJECT ??
*copyc qfh$change_output_attributes

{ NOTES:
{   Only deferred or queued output files can have their attributes changed.

  PROCEDURE [XDCL, #GATE] qfp$change_output_attributes
    (    system_label: jmt$output_system_label;
         earliest_clock_time_to_print: jmt$clock_time;
         latest_clock_time_to_print: jmt$clock_time;
         purge_delay_clock_time: jmt$clock_time;
         current_clock_time: jmt$clock_time;
         reprint_disposition: jmt$reprint_disposition;
     VAR notify_application: boolean;
     VAR application_gtid: ost$global_task_id;
     VAR delete_output_file: boolean;
     VAR status: ost$status);

    VAR
      deferred_file: boolean,
      entry_kind: jmt$kol_entry_kind,
      kol_index: jmt$kol_index,
      output_application_index: jmt$output_application_index,
      time_deferred_file: boolean;

    status.normal := TRUE;
    delete_output_file := FALSE;
    notify_application := FALSE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

  /find_entry_in_kol/
    FOR entry_kind := LOWERVALUE (entry_kind) TO UPPERVALUE (entry_kind) DO
      IF entry_kind IN $jmt$kol_entry_kind_set [jmc$kol_deferred_entry, jmc$kol_queued_entry,
            jmc$kol_completed_entry] THEN
        kol_index := jmv$known_output_list.state_data [entry_kind].first_entry;
        WHILE (kol_index <> jmc$kol_undefined_index) DO
          IF (jmv$kol_p^ [kol_index].system_file_name = system_label.system_file_name) THEN
            EXIT /find_entry_in_kol/;
          ELSE
            kol_index := jmv$kol_p^ [kol_index].forward_link;
          IFEND;
        WHILEND;
      IFEND;
    FOREND /find_entry_in_kol/;

    IF kol_index <> jmc$kol_undefined_index THEN
      time_deferred_file := current_clock_time < earliest_clock_time_to_print;
      deferred_file := time_deferred_file OR system_label.output_deferred_by_operator OR
            system_label.output_deferred_by_user;
      jmv$kol_p^ [kol_index].output_controller := system_label.output_controller;
      jmv$kol_p^ [kol_index].next_destination_usage := system_label.output_destination_usage;
      jmv$kol_p^ [kol_index].earliest_clock_time_to_print := earliest_clock_time_to_print;
      jmv$kol_p^ [kol_index].latest_clock_time_to_print := latest_clock_time_to_print;
      jmv$kol_p^ [kol_index].purge_delay := purge_delay_clock_time;
      jmv$kol_p^ [kol_index].output_deferred_by_operator := system_label.output_deferred_by_operator;
      jmv$kol_p^ [kol_index].output_deferred_by_user := system_label.output_deferred_by_user;

{ If the application state is not NEW, then the file has been acquired by the application
{ In this case, if the file is deferred or the destination usage has changed, mark
{ the file as terminated for the application.  When the application releases the file
{ it will be placed in the proper state.

      IF (jmv$kol_p^ [kol_index].entry_kind = jmc$kol_completed_entry) AND
            (reprint_disposition = jmc$rd_no_change) THEN
        jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
        IF purge_delay_clock_time < jmv$time_to_purge_printed_file THEN
          jmv$time_to_purge_printed_file := purge_delay_clock_time;
        IFEND;
      ELSEIF (jmv$kol_p^ [kol_index].entry_kind = jmc$kol_completed_entry) AND
            (reprint_disposition = jmc$rd_discard_file) THEN
        find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, output_application_index);
        relink_kol_application (kol_index, output_application_index, jmc$kol_application_unused);
        relink_kol_entry (kol_index, jmc$kol_unused_entry);
        delete_output_file := TRUE;
      ELSE

{ The file has not printed or it has printed and reprint was requested.

        IF deferred_file AND (jmv$kol_p^ [kol_index].application_state <= jmc$kol_application_new) THEN
          IF time_deferred_file AND (earliest_clock_time_to_print < jmv$time_to_ready_deferred_file) THEN
            jmv$time_to_ready_deferred_file := earliest_clock_time_to_print;
          IFEND;
          find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage, output_application_index);
          relink_kol_application (kol_index, output_application_index, jmc$kol_application_unused);
          jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
          relink_kol_entry (kol_index, jmc$kol_deferred_entry);
        ELSE
          IF jmv$kol_p^ [kol_index].application_state > jmc$kol_application_new THEN
            find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, output_application_index);
            IF (NOT deferred_file) AND (jmv$kol_p^ [kol_index].destination_usage =
                  jmv$kol_p^ [kol_index].next_destination_usage) THEN
              relink_kol_application (kol_index, output_application_index, jmc$kol_application_modified);
            ELSE
              relink_kol_application (kol_index, output_application_index, jmc$kol_application_terminated);
            IFEND;
          ELSE
            find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage, output_application_index);
            relink_kol_application (kol_index, output_application_index, jmc$kol_application_new);
            jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
            relink_kol_entry (kol_index, jmc$kol_queued_entry);
          IFEND;

{ At this point, the queue file is still attached.  Wait until the file is returned
{ (by the caller of this procedure) to notify the application so that when the application
{ tries to acquire the file, it will not have to wait.  This is done because of a potential
{ timing problem that occurs when change_output_attributes and another output queue file
{ command (such as change_output_attributes, or terminate_output) are executed
{ in a short timeframe.

          IF output_application_index <> jmc$unassigned_output_index THEN
            notify_application := TRUE;
            application_gtid := jmv$known_output_list.application_table [output_application_index].
                  global_task_id;
          IFEND;
        IFEND;
        IF latest_clock_time_to_print < jmv$time_to_purge_expired_file THEN
          jmv$time_to_purge_expired_file := latest_clock_time_to_print;
        IFEND;
      IFEND;
    ELSE
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_label.system_file_name,
            status);
    IFEND;

    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$change_output_attributes;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$get_application_name', EJECT ??

  PROCEDURE [XDCL, #GATE] qfp$get_application_name
    (    output_destination_usage: jmt$destination_usage;
     VAR application_name: ost$name);

    VAR
      application_index: jmt$output_application_index;

    application_name := osc$null_name;
    osp$set_mainframe_sig_lock (qfv$kol_lock);
    find_destination_usage (output_destination_usage, application_index);
    IF application_index <> jmc$unassigned_output_index THEN
      application_name := jmv$known_output_list.application_table [application_index].application_name;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$get_application_name;
?? TITLE := '[XDCL, #GATE] qfp$get_output_attributes', EJECT ??
*copy qfh$get_output_attributes

  PROCEDURE [XDCL, #GATE] qfp$get_output_attributes
    (    user_identification: ost$user_identification;
         privileged_job: boolean;
         attribute_options_p: ^jmt$output_attribute_options;
         output_names_p: ^jmt$name_list;
     VAR number_of_outputs_found: jmt$output_status_count;
     VAR status: ost$status);

    VAR
      option_index: integer,
      name_index: integer,
      names_size: integer,
      output_state: jmt$output_state,
      output_state_set: jmt$output_state_set,
      kol_entry_kind: jmt$kol_entry_kind,
      kol_index: jmt$kol_index,
      qualified_entry_found: boolean;

    status.normal := TRUE;
    number_of_outputs_found := 0;
    IF output_names_p <> NIL THEN
      names_size := UPPERBOUND (output_names_p^);
    ELSE
      names_size := 0;
    IFEND;

    output_state_set := -$jmt$output_state_set [];

    osp$set_mainframe_sig_lock (qfv$kol_lock);

  /search_each_entry_kind/
    FOR output_state := LOWERVALUE (jmt$output_state) TO UPPERVALUE (jmt$output_state) DO
      IF output_state IN output_state_set THEN
        convert_state_to_entry_kind (output_state, kol_entry_kind, status);
        IF NOT status.normal THEN
          EXIT /search_each_entry_kind/;
        IFEND;

        kol_index := jmv$known_output_list.state_data [kol_entry_kind].first_entry;

      /search_each_entry/
        WHILE kol_index <> jmc$kol_undefined_index DO
          IF (jmv$kol_p^ [kol_index].login_user_identification = user_identification) OR
                (jmv$kol_p^ [kol_index].output_controller = user_identification) OR privileged_job THEN

            qualified_entry_found := TRUE;
            IF attribute_options_p <> NIL THEN

            /attribute_option_check/
              FOR option_index := 1 TO UPPERBOUND (attribute_options_p^) DO
                CASE attribute_options_p^ [option_index].key OF

                = jmc$control_family =
                  IF attribute_options_p^ [option_index].control_family <>
                        jmv$kol_p^ [kol_index].output_controller.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /attribute_option_check/;
                  IFEND;

                = jmc$control_user =
                  IF attribute_options_p^ [option_index].control_user <>
                        jmv$kol_p^ [kol_index].output_controller.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /attribute_option_check/;
                  IFEND;

                = jmc$login_family =
                  IF attribute_options_p^ [option_index].login_family <>
                        jmv$kol_p^ [kol_index].login_user_identification.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /attribute_option_check/;
                  IFEND;

                = jmc$login_user =
                  IF attribute_options_p^ [option_index].login_user <>
                        jmv$kol_p^ [kol_index].login_user_identification.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /attribute_option_check/;
                  IFEND;

                = jmc$name_list =
                  IF attribute_options_p^ [option_index].name_list <> NIL THEN
                    qualified_entry_found := FALSE;

                  /search_for_name/
                    FOR name_index := 1 TO UPPERBOUND (attribute_options_p^ [option_index].name_list^) DO
                      CASE attribute_options_p^ [option_index].name_list^ [name_index].kind OF
                      = jmc$system_supplied_name =
                        IF attribute_options_p^ [option_index].name_list^ [name_index].system_supplied_name =
                              jmv$kol_p^ [kol_index].system_file_name THEN
                          qualified_entry_found := TRUE;
                          EXIT /search_for_name/;
                        IFEND;

                      = jmc$user_supplied_name =
                        IF attribute_options_p^ [option_index].name_list^ [name_index].user_supplied_name =
                              jmv$kol_p^ [kol_index].user_file_name THEN
                          qualified_entry_found := TRUE;
                          EXIT /search_for_name/;
                        IFEND;
                      CASEND;
                    FOREND /search_for_name/;

                    IF NOT qualified_entry_found THEN
                      EXIT /attribute_option_check/;
                    IFEND;
                  IFEND;

                = jmc$null_attribute =
                  ;

                ELSE
                  ;
                CASEND;
              FOREND /attribute_option_check/;
            IFEND;

            IF qualified_entry_found THEN
              number_of_outputs_found := number_of_outputs_found + 1;
              IF names_size >= number_of_outputs_found THEN
                output_names_p^ [number_of_outputs_found].kind := jmc$system_supplied_name;
                output_names_p^ [number_of_outputs_found].system_supplied_name :=
                      jmv$kol_p^ [kol_index].system_file_name;
              IFEND;
            IFEND;
          IFEND;

          kol_index := jmv$kol_p^ [kol_index].forward_link;
        WHILEND /search_each_entry/;
      IFEND;
    FOREND /search_each_entry_kind/;

    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$get_output_attributes;
?? TITLE := '[XDCL, #GATE] qfp$get_output_counts', EJECT ??
*copyc qfh$get_output_counts

  PROCEDURE [XDCL, #GATE] qfp$get_output_counts
    (VAR output_counts: jmt$output_counts;
     VAR status: ost$status);

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kol_lock);

    output_counts.state_data [jmc$deferred_output] := jmv$known_output_list.
          state_data [jmc$kol_deferred_entry].number_of_entries;
    output_counts.state_data [jmc$queued_output] := jmv$known_output_list.state_data [jmc$kol_queued_entry].
          number_of_entries;
    output_counts.state_data [jmc$initiated_output] := jmv$known_output_list.
          state_data [jmc$kol_initiated_entry].number_of_entries;
    output_counts.state_data [jmc$terminated_output] := jmv$known_output_list.
          state_data [jmc$kol_terminated_entry].number_of_entries;
    output_counts.state_data [jmc$completed_output] := jmv$known_output_list.
          state_data [jmc$kol_completed_entry].number_of_entries;

    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$get_output_counts;
?? TITLE := '[XDCL, #GATE] qfp$get_output_status', EJECT ??
*copy qfh$get_output_status

  PROCEDURE [XDCL, #GATE] qfp$get_output_status
    (    user_identification: ost$user_identification;
         privileged_job: boolean;
         status_options: ^jmt$output_status_options;
         status_results_keys_p: ^jmt$results_keys;
     VAR work_area_p: ^jmt$work_area;
     VAR number_of_outputs_found: jmt$output_status_count;
     VAR status: ost$status);

    VAR
      option_index: integer,
      name_index: integer,
      result_index: integer,
      output_state: jmt$output_state,
      output_state_set: jmt$output_state_set,
      kol_entry_kind: jmt$kol_entry_kind,
      kol_index: jmt$kol_index,
      qualified_entry_found: boolean,
      work_area_full: boolean;

?? NEWTITLE := 'add_file_to_work_area', EJECT ??

{ PURPOSE:
{   The purpose of this request is to add a file to the output status results
{   sequence supplied on the request.

    PROCEDURE add_file_to_work_area
      (    status_results_keys_p: ^jmt$results_keys;
       VAR work_area_p: ^jmt$work_area;
       VAR work_area_full: boolean);

      VAR
        boolean_p: ^boolean,
        ignore_status: ost$status,
        output_state_p: ^jmt$output_state,
        mainframe_id_p: ^pmt$mainframe_id,
        name_value_p: ^ost$name,
        system_supplied_name_p: ^jmt$system_supplied_name;

      IF status_results_keys_p <> NIL THEN

      /fill_in_each_status_result/
        FOR result_index := 1 TO UPPERBOUND (status_results_keys_p^) DO
          CASE status_results_keys_p^ [result_index] OF
          = jmc$client_mainframe_id =
            NEXT mainframe_id_p IN work_area_p;
            IF mainframe_id_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            pmp$get_mainframe_id (mainframe_id_p^, ignore_status);

          = jmc$control_family =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].output_controller.family;

          = jmc$control_user =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].output_controller.user;

          = jmc$login_family =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].login_user_identification.family;

          = jmc$login_user =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].login_user_identification.user;

          = jmc$null_attribute =
            ;

          = jmc$output_deferred_by_operator =
            NEXT boolean_p IN work_area_p;
            IF boolean_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            boolean_p^ := jmv$kol_p^ [kol_index].output_deferred_by_operator;

          = jmc$output_deferred_by_user =
            NEXT boolean_p IN work_area_p;
            IF boolean_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            boolean_p^ := jmv$kol_p^ [kol_index].output_deferred_by_user;

          = jmc$output_destination_usage =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].destination_usage;

          = jmc$output_state =
            NEXT output_state_p IN work_area_p;
            IF output_state_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            output_state_p^ := output_state;

          = jmc$system_file_name =
            NEXT system_supplied_name_p IN work_area_p;
            IF system_supplied_name_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            system_supplied_name_p^ := jmv$kol_p^ [kol_index].system_file_name;

          = jmc$system_job_name =
            NEXT system_supplied_name_p IN work_area_p;
            IF system_supplied_name_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            system_supplied_name_p^ := jmv$kol_p^ [kol_index].system_job_name;

          = jmc$user_file_name =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].user_file_name;

          = jmc$user_job_name =
            NEXT name_value_p IN work_area_p;
            IF name_value_p = NIL THEN
              work_area_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kol_p^ [kol_index].user_job_name;

          ELSE
          CASEND;
        FOREND /fill_in_each_status_result/;
      IFEND;
    PROCEND add_file_to_work_area;
?? OLDTITLE ??
?? NEWTITLE := 'handle_core_condition', EJECT ??

    PROCEDURE handle_core_condition
      (    monitor_fault: ost$monitor_fault;
           minimum_save_area_p: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        lock_status: ost$signature_lock_status;

      osp$test_sig_lock (qfv$kol_lock, lock_status);
      IF lock_status = osc$sls_locked_by_current_task THEN
        osp$clear_mainframe_sig_lock (qfv$kol_lock);
      IFEND;
      syp$continue_to_cause (monitor_fault, minimum_save_area_p, syc$condition_processed, continue);
      osp$monitor_fault_to_status (monitor_fault, minimum_save_area_p, status);
      EXIT qfp$get_output_status;
    PROCEND handle_core_condition;
?? OLDTITLE ??
?? EJECT ??
    syp$establish_condition_handler (^handle_core_condition);
    status.normal := TRUE;
    number_of_outputs_found := 0;
    work_area_full := work_area_p = NIL;

    output_state_set := -$jmt$output_state_set [];
    IF status_options <> NIL THEN
      FOR option_index := 1 TO UPPERBOUND (status_options^) DO
        IF status_options^ [option_index].key = jmc$output_state_set THEN
          output_state_set := status_options^ [option_index].output_state_set;
        IFEND;
      FOREND;
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kol_lock);

  /search_each_entry_kind/
    FOR output_state := LOWERVALUE (output_state) TO UPPERVALUE (output_state) DO
      IF output_state IN output_state_set THEN
        convert_state_to_entry_kind (output_state, kol_entry_kind, status);
        IF NOT status.normal THEN
          EXIT /search_each_entry_kind/;
        IFEND;

        kol_index := jmv$known_output_list.state_data [kol_entry_kind].first_entry;

      /search_each_entry/
        WHILE kol_index <> jmc$kol_undefined_index DO
          IF (jmv$kol_p^ [kol_index].login_user_identification = user_identification) OR
                (jmv$kol_p^ [kol_index].output_controller = user_identification) OR privileged_job THEN

            qualified_entry_found := TRUE;
            IF status_options <> NIL THEN

            /status_option_check/
              FOR option_index := 1 TO UPPERBOUND (status_options^) DO
                CASE status_options^ [option_index].key OF
                = jmc$control_family =
                  IF status_options^ [option_index].control_family <> jmv$kol_p^ [kol_index].
                        output_controller.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$control_user =
                  IF status_options^ [option_index].control_user <>
                        jmv$kol_p^ [kol_index].output_controller.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$login_family =
                  IF status_options^ [option_index].login_family <>
                        jmv$kol_p^ [kol_index].login_user_identification.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$login_user =
                  IF status_options^ [option_index].login_user <>
                        jmv$kol_p^ [kol_index].login_user_identification.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$name_list =
                  IF status_options^ [option_index].name_list <> NIL THEN
                    qualified_entry_found := FALSE;

                  /search_for_name/
                    FOR name_index := 1 TO UPPERBOUND (status_options^ [option_index].name_list^) DO
                      CASE status_options^ [option_index].name_list^ [name_index].kind OF
                      = jmc$system_supplied_name =
                        IF status_options^ [option_index].name_list^ [name_index].system_supplied_name =
                              jmv$kol_p^ [kol_index].system_file_name THEN
                          qualified_entry_found := TRUE;
                          EXIT /search_for_name/;
                        IFEND;

                      = jmc$user_supplied_name =
                        IF status_options^ [option_index].name_list^ [name_index].user_supplied_name =
                              jmv$kol_p^ [kol_index].user_file_name THEN
                          qualified_entry_found := TRUE;
                          EXIT /search_for_name/;
                        IFEND;
                      CASEND;
                    FOREND /search_for_name/;

                    IF NOT qualified_entry_found THEN
                      EXIT /status_option_check/;
                    IFEND;
                  IFEND;

                = jmc$null_attribute =
                  ;

                = jmc$output_deferred_by_operator =
                  IF status_options^ [option_index].output_deferred_by_operator <>
                        jmv$kol_p^ [kol_index].output_deferred_by_operator THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$output_deferred_by_user =
                  IF status_options^ [option_index].output_deferred_by_user <>
                        jmv$kol_p^ [kol_index].output_deferred_by_user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$output_destination_usage =
                  IF status_options^ [option_index].output_destination_usage <>
                        jmv$kol_p^ [kol_index].destination_usage THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$output_state_set =
                  ;

                = jmc$system_job_name =
                  IF status_options^ [option_index].system_job_name <> jmv$kol_p^ [kol_index].
                        system_job_name THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$user_job_name =
                  IF status_options^ [option_index].user_job_name <> jmv$kol_p^ [kol_index].user_job_name THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                ELSE
                CASEND;
              FOREND /status_option_check/;
            IFEND;

            IF qualified_entry_found THEN
              IF (NOT work_area_full) THEN
                add_file_to_work_area (status_results_keys_p, work_area_p, work_area_full);
              IFEND;
              number_of_outputs_found := number_of_outputs_found + 1;
            IFEND;
          IFEND;

          kol_index := jmv$kol_p^ [kol_index].forward_link;
        WHILEND /search_each_entry/;
      IFEND;
    FOREND /search_each_entry_kind/;

    osp$clear_mainframe_sig_lock (qfv$kol_lock);
    syp$disestablish_cond_handler;
  PROCEND qfp$get_output_status;
?? TITLE := '[XDCL, #GATE] qfp$purge_expired_file', EJECT ??
*copy qfh$purge_expired_file

  PROCEDURE [XDCL, #GATE] qfp$purge_expired_file
    (VAR system_file_name_to_delete: jmt$system_supplied_name;
     VAR output_destination_usage: jmt$destination_usage);

    VAR
      current_clock_value: jmt$clock_time,
      entry_kind: jmt$kol_entry_kind,
      kol_index: jmt$kol_index,
      next_kol_index: jmt$kol_index,
      output_application_index: jmt$output_application_index;

    system_file_name_to_delete := '';
    current_clock_value := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    jmv$time_to_purge_expired_file := jmc$latest_clock_time;

  /search_for_expired_files/
    FOR entry_kind := LOWERVALUE (entry_kind) TO UPPERVALUE (entry_kind) DO
      IF entry_kind IN $jmt$kol_entry_kind_set [jmc$kol_deferred_entry, jmc$kol_queued_entry,
            jmc$kol_initiated_entry] THEN
        kol_index := jmv$known_output_list.state_data [entry_kind].first_entry;
        WHILE kol_index <> jmc$kol_undefined_index DO
          next_kol_index := jmv$kol_p^ [kol_index].forward_link;
          IF jmv$kol_p^ [kol_index].latest_clock_time_to_print < current_clock_value THEN
            IF jmv$kol_p^ [kol_index].application_state > jmc$kol_application_new THEN
              IF entry_kind < jmc$kol_initiated_entry THEN
                find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, output_application_index);
                relink_kol_application (kol_index, output_application_index, jmc$kol_application_terminated);
                notify_output_application (output_application_index);
              IFEND;
              relink_kol_entry (kol_index, jmc$kol_terminated_entry);
            ELSE
              IF system_file_name_to_delete = '' THEN
                system_file_name_to_delete := jmv$kol_p^ [kol_index].system_file_name;
                output_destination_usage := jmv$kol_p^ [kol_index].destination_usage;
                find_destination_usage (output_destination_usage, output_application_index);
                relink_kol_application (kol_index, output_application_index, jmc$kol_application_unused);
                relink_kol_entry (kol_index, jmc$kol_unused_entry);
              ELSE
                jmv$time_to_purge_expired_file := jmv$kol_p^ [kol_index].latest_clock_time_to_print;
                EXIT /search_for_expired_files/;
              IFEND;
            IFEND;
          ELSE
            IF jmv$kol_p^ [kol_index].latest_clock_time_to_print < jmv$time_to_purge_expired_file THEN
              jmv$time_to_purge_expired_file := jmv$kol_p^ [kol_index].latest_clock_time_to_print;
            IFEND;
          IFEND;
          kol_index := next_kol_index;
        WHILEND;
      IFEND;
    FOREND /search_for_expired_files/;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$purge_expired_file;
?? TITLE := '[XDCL, #GATE] qfp$purge_printed_file', EJECT ??
*copy qfh$purge_printed_file

  PROCEDURE [XDCL, #GATE] qfp$purge_printed_file
    (VAR system_file_name_to_delete: jmt$system_supplied_name;
     VAR output_destination_usage: jmt$destination_usage);

    VAR
      current_clock_value: jmt$clock_time,
      kol_index: jmt$kol_index,
      next_kol_index: jmt$kol_index,
      output_application_index: jmt$output_application_index;

    system_file_name_to_delete := '';
    current_clock_value := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    jmv$time_to_purge_printed_file := jmc$latest_clock_time;

    kol_index := jmv$known_output_list.state_data [jmc$kol_completed_entry].first_entry;

  /search_for_printed_files/
    WHILE kol_index <> jmc$kol_undefined_index DO
      next_kol_index := jmv$kol_p^ [kol_index].forward_link;
      IF jmv$kol_p^ [kol_index].purge_delay < current_clock_value THEN
        IF system_file_name_to_delete = '' THEN
          system_file_name_to_delete := jmv$kol_p^ [kol_index].system_file_name;
          output_destination_usage := jmv$kol_p^ [kol_index].destination_usage;
          relink_kol_entry (kol_index, jmc$kol_unused_entry);
        ELSE
          jmv$time_to_purge_printed_file := jmv$kol_p^ [kol_index].purge_delay;
          EXIT /search_for_printed_files/;
        IFEND;
      ELSE
        IF jmv$kol_p^ [kol_index].purge_delay < jmv$time_to_purge_printed_file THEN
          jmv$time_to_purge_printed_file := jmv$kol_p^ [kol_index].purge_delay;
        IFEND;
      IFEND;
      kol_index := next_kol_index;
    WHILEND /search_for_printed_files/;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$purge_printed_file;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$print_file', EJECT ??
*copy qfh$print_file

  PROCEDURE [XDCL, #GATE] qfp$print_file
    (    system_label: jmt$output_system_label;
         earliest_clock_time_to_print: jmt$clock_time;
         latest_clock_time_to_print: jmt$clock_time;
         current_clock_time: jmt$clock_time;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      ignore_status_p: ^ost$status,
      kol_index: jmt$kol_index,
      time_deferred_file: boolean;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kol_lock);

{ Make sure that the name is not already in the KOL.

    kol_search (system_label.system_file_name, -$jmt$kol_entry_kind_set [], kol_index);
    IF kol_index <> jmc$kol_undefined_index THEN
      osp$clear_mainframe_sig_lock (qfv$kol_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$duplicate_name, system_label.system_file_name,
            status);
      RETURN;
    IFEND;

    IF jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry = jmc$kol_undefined_index THEN
      expand_kol;
    IFEND;

{ Check for room in the Known Output List (KOL).  The distribution of entries in
{ the KOL is defined as follows:
{
{    #available = MAXIMUM - qfv$current_kol_limit + #initialized_unused_entries
{    #used_entries = MAXIMUM - #available = qfv$current_kol_limit - #initialized_unused_entries
{
{ If the #used_entries >= jmv$maxiumum_known_outputs (logical bound) then the file cannot be
{ placed in the KOL.

    IF (qfv$current_kol_limit - jmv$known_output_list.state_data [jmc$kol_unused_entry].number_of_entries >=
          jmv$maximum_known_outputs) THEN
      osp$set_status_condition (jme$maximum_output, status);
      PUSH ignore_status_p;
      dpp$put_critical_message (jmc$output_queue_full_message, ignore_status_p^);
    ELSE
      kol_index := jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry;

      jmv$kol_p^ [kol_index].system_file_name := system_label.system_file_name;
      jmv$kol_p^ [kol_index].user_file_name := system_label.user_file_name;
      jmv$kol_p^ [kol_index].login_user_identification := system_label.login_user_identification;
      jmv$kol_p^ [kol_index].output_controller := system_label.output_controller;
      jmv$kol_p^ [kol_index].output_submission_clock_time := #FREE_RUNNING_CLOCK (0);
      jmv$kol_p^ [kol_index].earliest_clock_time_to_print := earliest_clock_time_to_print;
      jmv$kol_p^ [kol_index].latest_clock_time_to_print := latest_clock_time_to_print;
      jmv$kol_p^ [kol_index].purge_delay := jmc$earliest_clock_time;
      jmv$kol_p^ [kol_index].destination_usage := system_label.output_destination_usage;
      jmv$kol_p^ [kol_index].next_destination_usage := system_label.output_destination_usage;
      jmv$kol_p^ [kol_index].output_deferred_by_operator := system_label.output_deferred_by_operator;
      jmv$kol_p^ [kol_index].output_deferred_by_user := system_label.output_deferred_by_user;
      jmv$kol_p^ [kol_index].system_job_name := system_label.system_job_name;
      jmv$kol_p^ [kol_index].user_job_name := system_label.user_job_name;
      jmv$kol_p^ [kol_index].application_state := jmc$kol_application_unused;

      time_deferred_file := earliest_clock_time_to_print > current_clock_time;
      IF time_deferred_file OR jmv$kol_p^ [kol_index].output_deferred_by_operator OR
            jmv$kol_p^ [kol_index].output_deferred_by_user THEN
        IF time_deferred_file AND (earliest_clock_time_to_print < jmv$time_to_ready_deferred_file) THEN
          jmv$time_to_ready_deferred_file := earliest_clock_time_to_print;
        IFEND;
        relink_kol_entry (kol_index, jmc$kol_deferred_entry);
      ELSE
        find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, application_index);
        relink_kol_entry (kol_index, jmc$kol_queued_entry);
        relink_kol_application (kol_index, application_index, jmc$kol_application_new);
        notify_output_application (application_index);
      IFEND;
      IF latest_clock_time_to_print < jmv$time_to_purge_expired_file THEN
        jmv$time_to_purge_expired_file := latest_clock_time_to_print;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$print_file;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$ready_deferred_file', EJECT ??
*copy qfh$ready_deferred_file

  PROCEDURE [XDCL, #GATE] qfp$ready_deferred_file;

    VAR
      current_clock_time: jmt$clock_time,
      kol_index: jmt$kol_index,
      next_kol_index: jmt$kol_index,
      output_application_index: jmt$output_application_index;

    current_clock_time := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    jmv$time_to_ready_deferred_file := jmc$latest_clock_time;
    kol_index := jmv$known_output_list.state_data [jmc$kol_deferred_entry].first_entry;
    WHILE kol_index <> jmc$kol_undefined_index DO
      next_kol_index := jmv$kol_p^ [kol_index].forward_link;
      IF NOT (jmv$kol_p^ [kol_index].output_deferred_by_operator OR
            jmv$kol_p^ [kol_index].output_deferred_by_user) THEN
        IF (jmv$kol_p^ [kol_index].earliest_clock_time_to_print <= current_clock_time) THEN
          relink_kol_entry (kol_index, jmc$kol_queued_entry);
          find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, output_application_index);
          relink_kol_application (kol_index, output_application_index, jmc$kol_application_new);
          notify_output_application (output_application_index);
        ELSE
          IF jmv$kol_p^ [kol_index].earliest_clock_time_to_print < jmv$time_to_ready_deferred_file THEN
            jmv$time_to_ready_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print;
          IFEND;
        IFEND;
      IFEND;
      kol_index := next_kol_index;
    WHILEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$ready_deferred_file;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$rebuild_output_queue', EJECT ??
*copy qfh$rebuild_output_queue

{ NOTES:
{   This is only used during deadstart.  The queue recovery process knows how many files that are
{ queued on a NOS/VE system and it will always make the Known Output List (KOL) large enough to
{ contain all of the files regardless of what the site requests.

  PROCEDURE [XDCL, #GATE] qfp$rebuild_output_queue
    (    system_label: jmt$output_system_label;
         earliest_clock_time_to_print: jmt$clock_time;
         latest_clock_time_to_print: jmt$clock_time;
         purge_delay_clock_time: jmt$clock_time;
         current_clock_time: jmt$clock_time;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index,
      time_deferred_file: boolean;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kol_lock);

{ Make sure that the name is not already in the KOL.

    kol_search (system_label.system_file_name, -$jmt$kol_entry_kind_set [], kol_index);
    IF kol_index <> jmc$kol_undefined_index THEN
      osp$clear_mainframe_sig_lock (qfv$kol_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$duplicate_name, system_label.system_file_name,
            status);
      RETURN;
    IFEND;

{ Make sure that there is room in the KOL.

    IF jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry = jmc$kol_undefined_index THEN
      expand_kol;
    IFEND;

    IF jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry = jmc$kol_undefined_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$maximum_output, '', status);
    ELSE
      kol_index := jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry;

      jmv$kol_p^ [kol_index].system_file_name := system_label.system_file_name;
      jmv$kol_p^ [kol_index].user_file_name := system_label.user_file_name;
      jmv$kol_p^ [kol_index].login_user_identification := system_label.login_user_identification;
      jmv$kol_p^ [kol_index].output_controller := system_label.output_controller;
      jmv$kol_p^ [kol_index].output_submission_clock_time := #FREE_RUNNING_CLOCK (0);
      jmv$kol_p^ [kol_index].earliest_clock_time_to_print := earliest_clock_time_to_print;
      jmv$kol_p^ [kol_index].latest_clock_time_to_print := latest_clock_time_to_print;
      jmv$kol_p^ [kol_index].purge_delay := purge_delay_clock_time;
      jmv$kol_p^ [kol_index].destination_usage := system_label.output_destination_usage;
      jmv$kol_p^ [kol_index].next_destination_usage := system_label.output_destination_usage;
      jmv$kol_p^ [kol_index].output_deferred_by_operator := system_label.output_deferred_by_operator;
      jmv$kol_p^ [kol_index].output_deferred_by_user := system_label.output_deferred_by_user;
      jmv$kol_p^ [kol_index].system_job_name := system_label.system_job_name;
      jmv$kol_p^ [kol_index].user_job_name := system_label.user_job_name;
      jmv$kol_p^ [kol_index].application_state := jmc$kol_application_unused;

{ Has the file been printed??

      IF system_label.output_disposition_time.specified THEN
        IF jmv$kol_p^ [kol_index].purge_delay < jmv$time_to_purge_printed_file THEN
          jmv$time_to_purge_printed_file := jmv$kol_p^ [kol_index].purge_delay;
        IFEND;
        relink_kol_entry (kol_index, jmc$kol_completed_entry);
      ELSE
        time_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print > current_clock_time;
        IF time_deferred_file OR jmv$kol_p^ [kol_index].output_deferred_by_operator OR
              jmv$kol_p^ [kol_index].output_deferred_by_user THEN
          IF time_deferred_file AND (jmv$kol_p^ [kol_index].earliest_clock_time_to_print <
                jmv$time_to_ready_deferred_file) THEN
            jmv$time_to_ready_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print;
          IFEND;
          relink_kol_entry (kol_index, jmc$kol_deferred_entry);
        ELSE
          find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, application_index);

          relink_kol_entry (kol_index, jmc$kol_queued_entry);
          relink_kol_application (kol_index, application_index, jmc$kol_application_new);
        IFEND;
        IF jmv$kol_p^ [kol_index].latest_clock_time_to_print < jmv$time_to_purge_expired_file THEN
          jmv$time_to_purge_expired_file := jmv$kol_p^ [kol_index].latest_clock_time_to_print;
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$rebuild_output_queue;
?? TITLE := '[XDCL, #GATE] qfp$release_output_files', EJECT ??
*copy qfh$release_output_files

{ NOTES:
{   Even if the release_file_list is NIL this procedure must still return all files to
{ NOS/VE queue file management.

  PROCEDURE [XDCL, #GATE] qfp$release_output_files
    (    release_file_list: ^jmt$release_output_file_list;
     VAR release_file_count: jmt$output_count_range);

    VAR
      application_index: jmt$output_application_index,
      application_state: jmt$kol_application_state,
      current_clock_time: jmt$clock_time,
      global_task_id: ost$global_task_id,
      kol_index: jmt$kol_index,
      next_kol_index: jmt$kol_index,
      previously_terminated: boolean,
      relink_application_index: jmt$output_application_index,
      release_list_limit: jmt$output_count_range,
      time_deferred_file: boolean;

    pmp$get_executing_task_gtid (global_task_id);

    release_file_count := 0;
    IF release_file_list = NIL THEN
      release_list_limit := 0;
    ELSE
      release_list_limit := UPPERBOUND (release_file_list^);
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kol_lock);

{ Check to see if this task has output files registered.

  /search_all_applications/
    FOR application_index := 1 TO UPPERBOUND (jmv$known_output_list.application_table) DO
      IF jmv$known_output_list.application_table [application_index].global_task_id = global_task_id THEN

      /search_all_application_states/
        FOR application_state := SUCC (jmc$kol_application_unused) TO UPPERVALUE (application_state) DO
          kol_index := jmv$known_output_list.application_table [application_index].
                state_data [application_state].first_entry;

        /release_entries_in_state/
          WHILE kol_index <> jmc$kol_undefined_index DO

{ Save the index of the next KOL entry.  When the entry is relinked, the links on the current entry
{ will no longer link to the next entry that needs to be managed.

            next_kol_index := jmv$kol_p^ [kol_index].application_forward_link;
            previously_terminated := jmv$kol_p^ [kol_index].entry_kind = jmc$kol_terminated_entry;

{ If the file was terminated, add it to the release list so the caller knows to delete the file
{ and remove the file from the KOL.

            IF previously_terminated THEN
              release_file_count := release_file_count + 1;
              IF release_file_count <= release_list_limit THEN
                release_file_list^ [release_file_count].system_file_name :=
                      jmv$kol_p^ [kol_index].system_file_name;
                release_file_list^ [release_file_count].output_destination_usage :=
                      jmv$kol_p^ [kol_index].destination_usage;
              IFEND;
              relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
              relink_kol_entry (kol_index, jmc$kol_unused_entry);
            ELSE

              time_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print > current_clock_time;
              IF time_deferred_file OR jmv$kol_p^ [kol_index].output_deferred_by_operator OR
                    jmv$kol_p^ [kol_index].output_deferred_by_user THEN
                IF time_deferred_file AND (jmv$kol_p^ [kol_index].earliest_clock_time_to_print <
                      jmv$time_to_ready_deferred_file) THEN
                  jmv$time_to_ready_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print;
                IFEND;
                find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage,
                      relink_application_index);
                relink_kol_application (kol_index, relink_application_index, jmc$kol_application_unused);
                jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
                relink_kol_entry (kol_index, jmc$kol_deferred_entry);
              ELSE

{ If the file's destination usage hasn't changed - relink it into the unassigned chain
{ If the destination_usage did change, then make it available to that application

                IF jmv$kol_p^ [kol_index].destination_usage = jmv$kol_p^ [kol_index].
                      next_destination_usage THEN
                  relink_application_index := jmc$unassigned_output_index;
                ELSE
                  find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage,
                        relink_application_index);
                IFEND;
                relink_kol_entry (kol_index, jmc$kol_queued_entry);
                relink_kol_application (kol_index, relink_application_index, jmc$kol_application_new);
                jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
                notify_output_application (relink_application_index);
              IFEND;
            IFEND;

            kol_index := next_kol_index;
          WHILEND /release_entries_in_state/;
        FOREND /search_all_application_states/;

{ Zero out the entry in the application table.  The state_data has be zeroed by the relink procedures.

        jmv$known_output_list.application_table [application_index].application_name := osc$null_name;
        jmv$known_output_list.application_table [application_index].destination_usage := osc$null_name;
        jmv$known_output_list.application_table [application_index].global_task_id.index := 0;
        jmv$known_output_list.application_table [application_index].global_task_id.seqno := 0;
        jmv$known_output_list.application_table [application_index].queue_file_password := osc$null_name;

      IFEND;
    FOREND /search_all_applications/;

    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$release_output_files;
?? TITLE := '[XDCL, #GATE] qfp$register_output_application', EJECT ??
*copy qfh$register_output_application

  PROCEDURE [XDCL, #GATE] qfp$register_output_application
    (    application_name: ost$name;
         destination_usage: jmt$destination_usage;
         password: ost$name;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      first_available_index: jmt$output_application_index,
      kol_index: jmt$kol_index,
      next_forward_link: jmt$kol_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    first_available_index := jmc$unassigned_output_index;

  /search_for_the_application/
    FOR application_index := 1 TO UPPERBOUND (jmv$known_output_list.application_table) DO
      IF jmv$known_output_list.application_table [application_index].application_name = osc$null_name THEN
        IF first_available_index = jmc$unassigned_output_index THEN
          first_available_index := application_index;
        IFEND;

      ELSE { does the destination_usage match ??
        IF jmv$known_output_list.application_table [application_index].destination_usage =
              destination_usage THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$destination_usage_in_use, destination_usage,
                status);
          EXIT /search_for_the_application/;
        IFEND;
      IFEND;
    FOREND /search_for_the_application/;

    IF status.normal THEN

{ The destination_usage is not already in the table.  Is there room in the table??

      IF first_available_index = jmc$unassigned_output_index THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$application_table_is_full, '', status);
      ELSE

{ Move all output files with this destination_usage from the unassigned thread to this application thread.

        kol_index := jmv$known_output_list.application_table [jmc$unassigned_output_index].
              state_data [jmc$kol_application_new].first_entry;
        WHILE kol_index <> jmc$kol_undefined_index DO
          next_forward_link := jmv$kol_p^ [kol_index].application_forward_link;
          IF jmv$kol_p^ [kol_index].destination_usage = destination_usage THEN
            relink_kol_application (kol_index, first_available_index, jmc$kol_application_new);
          IFEND;
          kol_index := next_forward_link;
        WHILEND;

{ Initialize the entry in the table.  All files must be relinked before the table is initialized otherwise
{ the relink procedure will get confused with the destination usages.

        jmv$known_output_list.application_table [first_available_index].application_name := application_name;
        jmv$known_output_list.application_table [first_available_index].destination_usage :=
              destination_usage;
        jmv$known_output_list.application_table [first_available_index].queue_file_password := password;
        pmp$get_executing_task_gtid (jmv$known_output_list.application_table [first_available_index].
              global_task_id);
      IFEND;
    IFEND; { status.normal
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$register_output_application;
?? TITLE := '[XDCL, #GATE] qfp$set_output_completed', EJECT ??
*copy qfh$set_output_completed

  PROCEDURE [XDCL, #GATE] qfp$set_output_completed
    (    output_destination_usage: jmt$destination_usage;
         system_file_name: jmt$system_supplied_name;
         completed_successfully: boolean;
         purge_delay_clock_time: jmt$clock_time;
         current_clock_time: jmt$clock_time;
     VAR delete_output_file: boolean;
     VAR system_job_name: jmt$system_supplied_name;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index,
      previously_terminated: boolean,
      time_deferred_file: boolean;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    delete_output_file := FALSE;
    validate_application_access (output_destination_usage, application_index, status);
    IF status.normal THEN
      find_output_file_by_application (system_file_name, application_index, kol_index);

      IF kol_index <> jmc$kol_undefined_index THEN
        system_job_name := jmv$kol_p^ [kol_index].system_job_name;
        previously_terminated := jmv$kol_p^ [kol_index].entry_kind = jmc$kol_terminated_entry;
        IF completed_successfully OR previously_terminated THEN
          IF previously_terminated OR (purge_delay_clock_time < current_clock_time) THEN
            delete_output_file := TRUE;
            relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
            relink_kol_entry (kol_index, jmc$kol_unused_entry);
          ELSE
            IF purge_delay_clock_time < jmv$time_to_purge_printed_file THEN
              jmv$time_to_purge_printed_file := purge_delay_clock_time;
            IFEND;
            jmv$kol_p^ [kol_index].purge_delay := purge_delay_clock_time;
            find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage, application_index);
            relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
            jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
            relink_kol_entry (kol_index, jmc$kol_completed_entry);
          IFEND;
        ELSE
          find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage, application_index);
          time_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print > current_clock_time;
          IF time_deferred_file OR jmv$kol_p^ [kol_index].output_deferred_by_operator OR
                jmv$kol_p^ [kol_index].output_deferred_by_user THEN
            IF time_deferred_file AND (jmv$kol_p^ [kol_index].earliest_clock_time_to_print <
                  jmv$time_to_ready_deferred_file) THEN
              jmv$time_to_ready_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print;
            IFEND;
            relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
            jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
            relink_kol_entry (kol_index, jmc$kol_deferred_entry);
          ELSE
            relink_kol_entry (kol_index, jmc$kol_queued_entry);
            relink_kol_application (kol_index, application_index, jmc$kol_application_new);
            jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
            notify_output_application (application_index);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$set_output_completed;
?? TITLE := '[XDCL, #GATE] qfp$set_output_initiated', EJECT ??
*copy qfh$set_output_initiated

  PROCEDURE [XDCL, #GATE] qfp$set_output_initiated
    (    output_destination_usage: jmt$destination_usage;
         system_file_name: jmt$system_supplied_name;
     VAR system_job_name: jmt$system_supplied_name;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    validate_application_access (output_destination_usage, application_index, status);
    IF status.normal THEN

      find_output_file_by_application (system_file_name, application_index, kol_index);
      IF kol_index <> jmc$kol_undefined_index THEN
        system_job_name := jmv$kol_p^ [kol_index].system_job_name;

        IF (jmv$kol_p^ [kol_index].application_state = jmc$kol_application_modified) OR
              (jmv$kol_p^ [kol_index].application_state = jmc$kol_application_terminated) OR
              (jmv$kol_p^ [kol_index].entry_kind = jmc$kol_terminated_entry) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$output_cannot_initiate, '', status);
        ELSE

          relink_kol_application (kol_index, application_index, jmc$kol_application_printing);
          relink_kol_entry (kol_index, jmc$kol_initiated_entry);
        IFEND;
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$set_output_initiated;
?? TITLE := '    QFP$TERMINATE_ACQUIRED_OUTPUT', EJECT ??
*copy qfh$terminate_acquired_output

  PROCEDURE [XDCL, #GATE] qfp$terminate_acquired_output
    (    output_destination_usage: jmt$destination_usage;
     VAR system_file_name: jmt$system_supplied_name;
     VAR system_job_name: jmt$system_supplied_name;
     VAR delete_output_file: boolean;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      current_clock_time: jmt$clock_time,
      kol_index: jmt$kol_index,
      time_deferred_file: boolean;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kol_lock);

    validate_application_access (output_destination_usage, application_index, status);
    IF status.normal THEN

      kol_index := jmv$known_output_list.application_table [application_index].
            state_data [jmc$kol_application_terminated].first_entry;
      IF kol_index <> jmc$kol_undefined_index THEN
        system_file_name := jmv$kol_p^ [kol_index].system_file_name;
        system_job_name := jmv$kol_p^ [kol_index].system_job_name;
        IF jmv$kol_p^ [kol_index].entry_kind = jmc$kol_terminated_entry THEN
          delete_output_file := TRUE;
          relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
          relink_kol_entry (kol_index, jmc$kol_unused_entry);
        ELSE
          delete_output_file := FALSE;
          find_destination_usage (jmv$kol_p^ [kol_index].next_destination_usage, application_index);
          current_clock_time := #FREE_RUNNING_CLOCK (0);
          time_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print > current_clock_time;
          IF time_deferred_file OR jmv$kol_p^ [kol_index].output_deferred_by_operator OR
                jmv$kol_p^ [kol_index].output_deferred_by_user THEN
            IF time_deferred_file AND (jmv$kol_p^ [kol_index].earliest_clock_time_to_print <
                  jmv$time_to_ready_deferred_file) THEN
              jmv$time_to_ready_deferred_file := jmv$kol_p^ [kol_index].earliest_clock_time_to_print;
            IFEND;
            relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
            jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
            relink_kol_entry (kol_index, jmc$kol_deferred_entry);
          ELSE
            relink_kol_application (kol_index, application_index, jmc$kol_application_new);
            jmv$kol_p^ [kol_index].destination_usage := jmv$kol_p^ [kol_index].next_destination_usage;
            notify_output_application (application_index);
          IFEND;
        IFEND;

      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$output_queue_is_empty, '', status);
      IFEND;

    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$terminate_acquired_output;
?? TITLE := '[XDCL, #GATE] qfp$terminate_output', EJECT ??
*copy qfh$terminate_output

  PROCEDURE [XDCL, #GATE] qfp$terminate_output
    (    system_file_name: jmt$system_supplied_name;
         output_state_set: jmt$output_state_set;
     VAR system_job_name: jmt$system_supplied_name;
     VAR output_destination_usage: jmt$destination_usage;
     VAR delete_output_file: boolean;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index,
      kol_entry_kind_set: jmt$kol_entry_kind_set,
      kol_entry_kind: jmt$kol_entry_kind,
      output_state: jmt$output_state;

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

    kol_entry_kind_set := $jmt$kol_entry_kind_set [];
    FOR output_state := LOWERVALUE (output_state) TO UPPERVALUE (output_state) DO
      IF output_state IN output_state_set THEN
        convert_state_to_entry_kind (output_state, kol_entry_kind, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        kol_entry_kind_set := kol_entry_kind_set + $jmt$kol_entry_kind_set [kol_entry_kind];
      IFEND;
    FOREND;

    osp$set_mainframe_sig_lock (qfv$kol_lock);

    kol_search (system_file_name, kol_entry_kind_set, kol_index);
    IF kol_index = jmc$kol_undefined_index THEN
      osp$clear_mainframe_sig_lock (qfv$kol_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
      RETURN;
    IFEND;

    IF jmv$kol_p^ [kol_index].entry_kind = jmc$kol_terminated_entry THEN
      osp$clear_mainframe_sig_lock (qfv$kol_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$output_already_terminated, system_file_name,
            status);
      RETURN;
    IFEND;

    system_job_name := jmv$kol_p^ [kol_index].system_job_name;
    output_destination_usage := jmv$kol_p^ [kol_index].destination_usage;
    relink_kol_entry (kol_index, jmc$kol_terminated_entry);
    find_destination_usage (jmv$kol_p^ [kol_index].destination_usage, application_index);
    IF jmv$kol_p^ [kol_index].application_state > jmc$kol_application_new THEN
      IF jmv$kol_p^ [kol_index].entry_kind <> jmc$kol_initiated_entry THEN
        relink_kol_application (kol_index, application_index, jmc$kol_application_terminated);
        notify_output_application (application_index);
      IFEND;
    ELSE
      delete_output_file := TRUE;
      relink_kol_application (kol_index, application_index, jmc$kol_application_unused);
      relink_kol_entry (kol_index, jmc$kol_unused_entry);
    IFEND;

    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$terminate_output;
?? TITLE := '[XDCL, #GATE] qfp$validate_output_file_access', EJECT ??
*copy qfh$validate_output_file_access

  PROCEDURE [XDCL, #GATE] qfp$validate_output_file_access
    (    system_file_name: jmt$system_supplied_name;
         output_destination_usage: jmt$destination_usage;
         queue_file_password: jmt$queue_file_password;
     VAR status: ost$status);

    VAR
      application_index: jmt$output_application_index,
      kol_index: jmt$kol_index;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kol_lock);
    find_destination_usage (output_destination_usage, application_index);
    IF application_index = jmc$unassigned_output_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$destination_usage_incorrect,
            output_destination_usage, status);
    ELSE

{ Do the passwords match??

      IF queue_file_password <> jmv$known_output_list.application_table [application_index].
            queue_file_password THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$application_not_permitted,
              output_destination_usage, status);
      ELSE

{ Search for the file in the applications initiated thread - If it isn't there, don't permit access
{ to the file.

        kol_index := jmv$known_output_list.application_table [application_index].
              state_data [jmc$kol_application_printing].first_entry;
        WHILE (kol_index <> jmc$kol_undefined_index) AND (jmv$kol_p^ [kol_index].system_file_name <>
              system_file_name) DO
          kol_index := jmv$kol_p^ [kol_index].application_forward_link;
        WHILEND;
        IF (kol_index = jmc$kol_undefined_index) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kol_lock);
  PROCEND qfp$validate_output_file_access;
MODEND qfm$queue_file_output_manager;
