?? NEWTITLE := 'NOS/VE Job Scheduling : the_stubs' ??
MODULE jmm$the_stubs;
?? RIGHT := 110 ??
{ PURPOSE:
{   Simulate the behaviour of the ring 3 scheduling interfaces.
{
{ NOTES:
{   This deck is for testing purposes only and must have no 'osf$' library
{   in the deck header groups when in the source library.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmt$element_state
*copyc fst$file_reference
*copyc jmc$job_management_id
*copyc jmc$sched_profile_deadstart_id
*copyc jme$job_scheduler_conditions
*copyc jme$queued_file_conditions
*copyc jmt$application_attributes
*copyc jmt$application_index
*copyc jmt$application_name
*copyc jmt$application_set
*copyc jmt$application_table
*copyc jmt$class_kind
*copyc jmt$defined_classes
*copyc jmt$dispatching_control
*copyc jmt$job_category_data
*copyc jmt$job_class
*copyc jmt$job_class_attributes
*copyc jmt$job_class_set
*copyc jmt$job_class_statistics
*copyc jmt$job_class_table
*copyc jmt$job_scheduler_table
*copyc jmt$profile_header
*copyc jmt$profile_index_to_job_class
*copyc jmt$service_class_attributes
*copyc jmt$service_class_index
*copyc jmt$service_class_set
*copyc jmt$service_class_statistics
*copyc jmt$service_class_table
*copyc jmt$system_profile_cycle_number
*copyc jmt$system_supplied_name
*copyc osd$integer_limits
*copyc ost$binary_unique_name
*copyc ost$caller_identifier
*copyc ost$status
*copyc pme$program_services_exceptions
*copyc pmt$binary_mainframe_id
*copyc pmt$mainframe_id
*copyc pmt$processor_state
?? POP ??
*copyc amp$return
*copyc amp$get_segment_pointer
*copyc amp$set_segment_eoi
*copyc clp$convert_string_to_file
*copyc clp$get_variable
*copyc fsp$close_file
*copyc fsp$open_file
*copyc osp$append_status_file
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc pfp$change
*copyc pfp$purge
*copyc pmp$abort
*copyc pmp$convert_mainframe_to_binary
*copyc pmp$generate_unique_name
*copyc pmp$get_job_names
*copyc pmp$get_mainframe_id
*copyc rmp$request_mass_storage
?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

  VAR
    jmv$profile_index_to_job_class: [XDCL] jmt$profile_index_to_job_class;

{ *copyc jmc$system_scheduling_profile

  CONST
    jmc$scheduling_profile_family = osc$null_name,
    jmc$scheduling_profile_user = osc$null_name,
    jmc$scheduling_profile_catalog = 'SCHEDULING                     ',
    jmc$scheduling_profile_filename = 'OSF$SYSTEM_PROFILE             ',
    jmc$scheduling_profile_cycle = 2,
    jmc$scheduling_profile_pathname = '$USER.SCHEDULING.OSF$SYSTEM_PROFILE',
    jmc$scheduling_profile_path_siz = 35,
    jmc$scheduling_profile_password = osc$null_name;

  VAR
    utility_active: boolean := FALSE,
    path: array [1 .. 4] of pft$name := [jmc$scheduling_profile_family, jmc$scheduling_profile_user,
          jmc$scheduling_profile_catalog, jmc$scheduling_profile_filename],
    password: [STATIC] pft$password := ' ';

  VAR
    the_access_id: ost$binary_unique_name := [1234, osc$cyber_180_model_835, 1987, 4, 29, 16, 33, 10, 1111,
          0];

  TYPE
    maximums = record
      max_jc: integer,
      max_jci: integer,
      max_sc: integer,
      max_sci: integer,
      max_ap: integer,
      max_cat: integer,
    recend;

  VAR
    jobs_moved: integer := 5,
    the_max: maximums := [10, 10, 10, 10, 10, 65];

  VAR
    the_applications: ^jmt$application_table,
    the_job_classes: ^jmt$job_class_table,
    the_service_classes: ^jmt$service_class_table;

  VAR
    validation_list: array [1 .. 1] of jmt$mainframe_entry :=
          [['$SYSTEM_0855_0109', [030(16), 0109(10)], [], []]],
    the_controls: jmt$job_scheduler_table := [10000, FALSE, 10, jmc$sched_profile_deadstart_id, 100,
          [REP 8 of [0, 100, FALSE]], 10, [[1, 8], [1, 8], [2, 8], [2, 8], [3, 8], [3, 8], [4, 8], [4, 8],
          [5, 8], [5, 8]], 1000, [], [], [100, 200], ^validation_list, 0];

  VAR
    jc_default: jmt$job_class_attributes := [
{ DEFINED                              } TRUE,
{ INDEX                                } 0,
{ PROFILE_INDEX                        } 0,
{ PROFILE_IDENTIFICATION               } 'DEFAULT_JOB_CLASS',
{ NAME                                 } 'default_job_class',
{ ABBREVIATION                         } ' ',
{ PROLOG_P                             } NIL,
{ EPILOG_P                             } NIL,
{ ENABLE_CLASS_INITIATION              } TRUE,
{ IMMEDIATE_INITIATION_CANDIDATE       } FALSE,
{ DEFAULT_OUTPUT_CLASS                 } 'NORMAL',
{ INITIAL_SERVICE_CLASS_INDEX          } 0,
{ INITIAL_WORKING_SET                  } 200,
{                                      }
{ CYCLIC_AGING_INTERVAL                } [1000000000, 10000, 1000000000],
{ DEFER_ON_SUBMIT                      } FALSE,
{ INITIATION_LEVEL                     } [0, 0],
{ MAXIMUM_WORKING_SET                  } [1000, 20, 2000],
{ MINIMUM_WORKING_SET                  } [20, 20, 1000],
{ PAGE_AGING_INTERVAL                  } [10000, 10000, 1000000000],
{                                      }
{ CPU_TIME_LIMIT                       } 1000000000,
{ DETACHED_JOB_WAIT_TIME               } [18000, 18000, 18000],
{ MAGNETIC_TAPE_LIMIT                  } 0,
{ SRU_LIMIT                            } 1000000000,
{                                      }
{ AUTOMATIC_CLASS_SELECTION            } FALSE,
{ EXCLUDED_CATEGORIES                  } [],
{ NEXT_RANK_CLASS                      } 0,
{ REQUIRED_CATEGORIES                  } [],
{                                      }
{ INITIATION_AGE_INTERVAL              } 1,
{ JOB_LEVELING_PRIORITY_BIAS           } 0,
{ MULTIPLE_JOB_BIAS                    } 0,
{ SELECTION_PRIORITY                   } [300, 600, 1, 300]];

  VAR
    default_job_classes: array [1 .. 4] of jmt$job_class_attributes := [

{1                                   } [
{ DEFINED                              } TRUE,
{ INDEX                                } 1,
{ PROFILE_INDEX                        } 1,
{ PROFILE_IDENTIFICATION               } 'JC_SYSTEM',
{ NAME                                 } 'SYSTEM',
{ ABBREVIATION                         } 'S',
{ PROLOG_P                             } NIL,
{ EPILOG_P                             } NIL,
{ ENABLE_CLASS_INITIATION              } TRUE,
{ IMMEDIATE_INITIATION_CANDIDATE       } FALSE,
{ DEFAULT_OUTPUT_CLASS                 } 'NORMAL',
{ INITIAL_SERVICE_CLASS_INDEX          } 2,
{ INITIAL_WORKING_SET                  } 80,
{                                      }
{ CYCLIC_AGING_INTERVAL                } [1000000000, 10000, 1000000000],
{ DEFER_ON_SUBMIT                      } FALSE,
{ INITIATION_LEVEL                     } [20, 20],
{ MAXIMUM_WORKING_SET                  } [1000, 20, 2000],
{ MINIMUM_WORKING_SET                  } [20, 20, 1000],
{ PAGE_AGING_INTERVAL                  } [10000, 10000, 1000000000],
{                                      }
{ CPU_TIME_LIMIT                       } 1000000000,
{ DETACHED_JOB_WAIT_TIME               } [18000, 18000, 18000],
{ MAGNETIC_TAPE_LIMIT                  } 0,
{ SRU_LIMIT                            } 1000000000,
{                                      }
{ AUTOMATIC_CLASS_SELECTION            } FALSE,
{ EXCLUDED_CATEGORIES                  } [],
{ NEXT_RANK_CLASS                      } 0,
{ REQUIRED_CATEGORIES                  } [],
{                                      }
{ INITIATION_AGE_INTERVAL              } 1,
{ JOB_LEVELING_PRIORITY_BIAS           } 0,
{ MULTIPLE_JOB_BIAS                    } 0,
{ SELECTION_PRIORITY                   } [700, 1000, 1, 700]],

{2                                   } [
{ DEFINED                              } TRUE,
{ INDEX                                } 2,
{ PROFILE_INDEX                        } 2,
{ PROFILE_IDENTIFICATION               } 'JC_MAINTENANCE',
{ NAME                                 } 'MAINTENANCE',
{ ABBREVIATION                         } 'M',
{ PROLOG_P                             } NIL,
{ EPILOG_P                             } NIL,
{ ENABLE_CLASS_INITIATION              } TRUE,
{ IMMEDIATE_INITIATION_CANDIDATE       } TRUE,
{ DEFAULT_OUTPUT_CLASS                 } 'NORMAL',
{ INITIAL_SERVICE_CLASS_INDEX          } 3,
{ INITIAL_WORKING_SET                  } 65,
{                                      }
{ CYCLIC_AGING_INTERVAL                } [1000000000, 10000, 1000000000],
{ DEFER_ON_SUBMIT                      } FALSE,
{ INITIATION_LEVEL                     } [50, 0],
{ MAXIMUM_WORKING_SET                  } [1000, 20, 2000],
{ MINIMUM_WORKING_SET                  } [20, 20, 1000],
{ PAGE_AGING_INTERVAL                  } [10000, 10000, 1000000000],
{                                      }
{ CPU_TIME_LIMIT                       } 1000000000,
{ DETACHED_JOB_WAIT_TIME               } [18000, 18000, 18000],
{ MAGNETIC_TAPE_LIMIT                  } 0,
{ SRU_LIMIT                            } 1000000000,
{                                      }
{ AUTOMATIC_CLASS_SELECTION            } FALSE,
{ EXCLUDED_CATEGORIES                  } [],
{ NEXT_RANK_CLASS                      } 0,
{ REQUIRED_CATEGORIES                  } [],
{                                      }
{ INITIATION_AGE_INTERVAL              } 1,
{ JOB_LEVELING_PRIORITY_BIAS           } 0,
{ MULTIPLE_JOB_BIAS                    } 0,
{ SELECTION_PRIORITY                   } [200, 250, 1, 200]],

{3                                   } [
{ DEFINED                              } TRUE,
{ INDEX                                } 3,
{ PROFILE_INDEX                        } 3,
{ PROFILE_IDENTIFICATION               } 'JC_UNASSIGNED',
{ NAME                                 } 'UNASSIGNED',
{ ABBREVIATION                         } 'U',
{ PROLOG_P                             } NIL,
{ EPILOG_P                             } NIL,
{ ENABLE_CLASS_INITIATION              } FALSE,
{ IMMEDIATE_INITIATION_CANDIDATE       } FALSE,
{ DEFAULT_OUTPUT_CLASS                 } 'NORMAL',
{ INITIAL_SERVICE_CLASS_INDEX          } 1,
{ INITIAL_WORKING_SET                  } 800,
{                                      }
{ CYCLIC_AGING_INTERVAL                } [1000000000, 10000, 1000000000],
{ DEFER_ON_SUBMIT                      } FALSE,
{ INITIATION_LEVEL                     } [50, 0],
{ MAXIMUM_WORKING_SET                  } [1000, 20, 2000],
{ MINIMUM_WORKING_SET                  } [20, 20, 1000],
{ PAGE_AGING_INTERVAL                  } [10000, 10000, 1000000000],
{                                      }
{ CPU_TIME_LIMIT                       } 1000000000,
{ DETACHED_JOB_WAIT_TIME               } [18000, 18000, 18000],
{ MAGNETIC_TAPE_LIMIT                  } 0,
{ SRU_LIMIT                            } 1000000000,
{                                      }
{ AUTOMATIC_CLASS_SELECTION            } FALSE,
{ EXCLUDED_CATEGORIES                  } [],
{ NEXT_RANK_CLASS                      } 0,
{ REQUIRED_CATEGORIES                  } [],
{                                      }
{ INITIATION_AGE_INTERVAL              } 1,
{ JOB_LEVELING_PRIORITY_BIAS           } 0,
{ MULTIPLE_JOB_BIAS                    } 0,
{ SELECTION_PRIORITY                   } [200, 250, 1, 200]],

{4                                   } [
{ DEFINED                              } FALSE,
{ INDEX                                } 0,
{ PROFILE_INDEX                        } 0,
{ PROFILE_IDENTIFICATION               } 'BAD_JC',
{ NAME                                 } 'bad_jc',
{ ABBREVIATION                         } '-',
{ PROLOG_P                             } NIL,
{ EPILOG_P                             } NIL,
{ ENABLE_CLASS_INITIATION              } TRUE,
{ IMMEDIATE_INITIATION_CANDIDATE       } FALSE,
{ DEFAULT_OUTPUT_CLASS                 } 'NORMAL',
{ INITIAL_SERVICE_CLASS_INDEX          } 0,
{ INITIAL_WORKING_SET                  } 200,
{                                      }
{ CYCLIC_AGING_INTERVAL                } [1000000000, 10000, 1000000000],
{ DEFER_ON_SUBMIT                      } FALSE,
{ INITIATION_LEVEL                     } [0, 0],
{ MAXIMUM_WORKING_SET                  } [1000, 20, 2000],
{ MINIMUM_WORKING_SET                  } [20, 20, 1000],
{ PAGE_AGING_INTERVAL                  } [10000, 10000, 1000000000],
{                                      }
{ CPU_TIME_LIMIT                       } 1000000000,
{ DETACHED_JOB_WAIT_TIME               } [18000, 18000, 18000],
{ MAGNETIC_TAPE_LIMIT                  } 0,
{ SRU_LIMIT                            } 1000000000,
{                                      }
{ AUTOMATIC_CLASS_SELECTION            } FALSE,
{ EXCLUDED_CATEGORIES                  } [],
{ NEXT_RANK_CLASS                      } 0,
{ REQUIRED_CATEGORIES                  } [],
{                                      }
{ INITIATION_AGE_INTERVAL              } 1,
{ JOB_LEVELING_PRIORITY_BIAS           } 0,
{ MULTIPLE_JOB_BIAS                    } 0,
{ SELECTION_PRIORITY                   } [300, 600, 1, 300]]];

  VAR
    sc_default: jmt$service_class_attributes := [
{ DEFINED                              } TRUE,
{ INDEX                                } 0,
{ PROFILE_IDENTIFICATION               } 'DEFAULT_SERVICE_CLASS',
{ NAME                                 } 'default_service_class',
{ ABBREVIATION                         } ' ',
{                                      }
{ AIO_LIMIT                            } 60000,
{ ATTEMPT_PREEMPTION                   } TRUE,
{ SWAP_JOBS_IN_LONGWAIT                } TRUE,
{ CLASS_SERVICE_THRESHOLD              } 10000,
{ GUARANTEED_SERVICE_QUANTUM           } 6000,
{ LONG_WAIT_THINK_TIME                 } 0,
{ MAXIMUM_ACTIVE_JOBS                  } 50,
{ NEXT_SERVICE_CLASS_INDEX             } 1,
{ SERVICE_FACTORS                      } [1, 0, 0, 0],
{                                      }
{ DISPATCHING_CONTROL                  } [[TRUE, 3, 1000, [10000, 10000000]], REP 4 of [FALSE, 0, 0, [0, 0]]],
{ SCHEDULING_PRIORITY                  } [100, 600, 100, 0],
{ SWAP_AGE_INTERVAL                    } 1];

  VAR
    default_service_classes: array [1 .. 4] of jmt$service_class_attributes := [

{ 1                                  } [
{ DEFINED                              } TRUE,
{ INDEX                                } 1,
{ PROFILE_IDENTIFICATION               } 'SC_SYSTEM',
{ NAME                                 } 'SYSTEM',
{ ABBREVIATION                         } ' ',
{                                      }
{ AIO_LIMIT                            } 60000,
{ ATTEMPT_PREEMPTION                   } TRUE,
{ SWAP_JOBS_IN_LONGWAIT                } TRUE,
{ CLASS_SERVICE_THRESHOLD              } 10000,
{ GUARANTEED_SERVICE_QUANTUM           } 500,
{ LONG_WAIT_THINK_TIME                 } 0,
{ MAXIMUM_ACTIVE_JOBS                  } 20,
{ NEXT_SERVICE_CLASS_INDEX             } 2,
{ SERVICE_FACTORS                      } [1, 0, 0, 0],
{                                      }
{ DISPATCHING_CONTROL                  } [[TRUE, 3, 1000, [10000, 10000000]], REP 4 of [FALSE, 0, 0, [0, 0]]],
{ SCHEDULING_PRIORITY                  } [600, 1000, 100, 0],
{ SWAP_AGE_INTERVAL                    } 1],

{ 2                                  } [
{ DEFINED                              } TRUE,
{ INDEX                                } 2,
{ PROFILE_IDENTIFICATION               } 'SC_MAINTENANCE',
{ NAME                                 } 'MAINTENANCE',
{ ABBREVIATION                         } 'M',
{                                      }
{ AIO_LIMIT                            } 60000,
{ ATTEMPT_PREEMPTION                   } TRUE,
{ SWAP_JOBS_IN_LONGWAIT                } TRUE,
{ CLASS_SERVICE_THRESHOLD              } 10000,
{ GUARANTEED_SERVICE_QUANTUM           } 1000,
{ LONG_WAIT_THINK_TIME                 } 0,
{ MAXIMUM_ACTIVE_JOBS                  } 100,
{ NEXT_SERVICE_CLASS_INDEX             } 3,
{ SERVICE_FACTORS                      } [1, 0, 0, 0],
{                                      }
{ DISPATCHING_CONTROL                  } [[TRUE, 3, 1000, [10000, 10000000]], REP 4 of [FALSE, 0, 0, [0, 0]]],
{ SCHEDULING_PRIORITY                  } [200, 700, 100, 100],
{ SWAP_AGE_INTERVAL                    } 1],

{ 3                                  } [
{ DEFINED                              } TRUE,
{ INDEX                                } 3,
{ PROFILE_IDENTIFICATION               } 'SC_UNASSIGNED',
{ NAME                                 } 'UNASSIGNED',
{ ABBREVIATION                         } 'U',
{                                      }
{ AIO_LIMIT                            } 60000,
{ ATTEMPT_PREEMPTION                   } FALSE,
{ SWAP_JOBS_IN_LONGWAIT                } TRUE,
{ CLASS_SERVICE_THRESHOLD              } 10000,
{ GUARANTEED_SERVICE_QUANTUM           } 100,
{ LONG_WAIT_THINK_TIME                 } 0,
{ MAXIMUM_ACTIVE_JOBS                  } 50,
{ NEXT_SERVICE_CLASS_INDEX             } 1,
{ SERVICE_FACTORS                      } [1, 0, 0, 0],
{                                      }
{ DISPATCHING_CONTROL                  } [[TRUE, 1, 1000, [10000, 10000000]], REP 4 of [FALSE, 0, 0, [0, 0]]],
{ SCHEDULING_PRIORITY                  } [50, 250, 1, 0],
{ SWAP_AGE_INTERVAL                    } 1],

{ 4                                  } [
{ DEFINED                              } TRUE,
{ INDEX                                } 3,
{ PROFILE_IDENTIFICATION               } 'BAD_SC',
{ NAME                                 } 'bad_sc',
{ ABBREVIATION                         } ' ',
{                                      }
{ AIO_LIMIT                            } 60000,
{ ATTEMPT_PREEMPTION                   } FALSE,
{ SWAP_JOBS_IN_LONGWAIT                } TRUE,
{ CLASS_SERVICE_THRESHOLD              } 10000,
{ GUARANTEED_SERVICE_QUANTUM           } 6000,
{ LONG_WAIT_THINK_TIME                 } 0,
{ MAXIMUM_ACTIVE_JOBS                  } 50,
{ NEXT_SERVICE_CLASS_INDEX             } 1,
{ SERVICE_FACTORS                      } [1, 0, 0, 0],
{                                      }
{ DISPATCHING_CONTROL                  } [[TRUE, 3, 1000, [10000, 10000000]], REP 4 of [FALSE, 0, 0, [0, 0]]],
{ SCHEDULING_PRIORITY                  } [100, 600, 100, 0],
{ SWAP_AGE_INTERVAL                    } 1]];

  VAR
    ap_default: jmt$application_attributes := [TRUE, 'DEFAULT_APPLICATION', 'default_application', TRUE, 0, 0,
          0, 0, 0];

  VAR
    default_applications: array [1 .. 1] of jmt$application_attributes := [
          { 1} [FALSE, 'NONE', 'name', TRUE, 0, 0, 0, 0, 0]];

  VAR
    jmv$job_category_data: jmt$job_category_data := [NIL, [REP 14 of []], NIL];

  VAR
    required_attributes: [STATIC] array [1 .. 3] of fst$file_cycle_attribute :=
          [[fsc$file_contents_and_processor, 'SCHEDULING_PROFILE', 'ADMINISTER_SCHEDULING'],
          [fsc$file_organization, amc$byte_addressable], [fsc$record_type, amc$undefined]];

  VAR
    base_file: string (20) := 'ACTIVE_PROFILE';

  VAR
    controls_p: ^jmt$job_scheduler_table,
    job_classes_p: ^jmt$job_class_table,
    service_classes_p: ^jmt$service_class_table,
    applications_p: ^jmt$application_table,
    category_data_p: ^jmt$job_category_data;

?? TITLE := 'initiated_jobs_in_job_class', EJECT ??

  FUNCTION initiated_jobs_in_job_class
    (    job_class_index: jmt$job_class): boolean;

    initiated_jobs_in_job_class := the_job_classes^ [job_class_index].enable_class_initiation AND
          (the_job_classes^ [job_class_index].initiation_level.preferred > 0);
    initiated_jobs_in_job_class := FALSE;

  FUNCEND initiated_jobs_in_job_class;

?? TITLE := 'jobs_in_service_class', EJECT ??

  FUNCTION jobs_in_service_class
    (    service_class_index: jmt$service_class_index): boolean;

{         This function will return a 'TRUE' value if there are jobs initiated
{         in the given service class.

    jobs_in_service_class := the_service_classes^ [service_class_index].maximum_active_jobs > 0;
    jobs_in_service_class := FALSE;

  FUNCEND jobs_in_service_class;
?? TITLE := 'jmp$verify_utility_access_id', EJECT ??

  PROCEDURE jmp$verify_utility_access_id
    (    access_id: ost$binary_unique_name;
     VAR status: ost$status);

    status.normal := TRUE;
    IF NOT utility_active THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$no_utility_is_active, '', status);
      RETURN; {----->
    IFEND;

    IF access_id <> the_access_id THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$access_id_mismatch, '', status);
      RETURN; {----->
    IFEND;
  PROCEND jmp$verify_utility_access_id;
?? TITLE := '[XDCL, #GATE] jmp$abort_deadstart', EJECT ??

*copyc jmh$abort_deadstart

  PROCEDURE [XDCL, #GATE] jmp$abort_deadstart
    (    display_message: string ( * );
         display_status: ost$status;
     VAR status: ost$status);

{  jme$must_be_system_job

    pmp$abort (display_status);

  PROCEND jmp$abort_deadstart;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] jmp$change_profile_cycle', EJECT ??
*copy jmh$change_profile_cycle

  PROCEDURE [XDCL, #GATE] jmp$change_profile_cycle
    (    access_id: ost$binary_unique_name;
     VAR status: ost$status);

    VAR
      change_list: array [1 .. 1] of pft$change_descriptor,
      file_cycle: pft$cycle_selector,
      local_access_id: ost$binary_unique_name,
      local_status: ost$status;

    status.normal := TRUE;
    local_access_id := access_id;
    jmp$verify_utility_access_id (local_access_id, local_status);
    IF NOT local_status.normal THEN
      status := local_status;
      RETURN; {----->
    IFEND;

    file_cycle.cycle_option := pfc$specific_cycle;
    file_cycle.cycle_number := 1;

    change_list [1].change_type := pfc$cycle_number_change;
    change_list [1].cycle_number := 2;

    pfp$change (path, file_cycle, password, change_list, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

  PROCEND jmp$change_profile_cycle;
?? OLDTITLE ??
?? TITLE := '[XDCL, #GATE] jmp$clear_utility_active', EJECT ??

*copyc jmh$clear_utility_active

  PROCEDURE [XDCL, #GATE] jmp$clear_utility_active
    (    access_id: ost$binary_unique_name;
     VAR status: ost$status);

{       jme$must_be_scheduling_admin
{       jme$no_utility_is_active

    jmp$verify_utility_access_id (access_id, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    utility_active := FALSE;
    write_system_tables (status);
  PROCEND jmp$clear_utility_active;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] jmp$close_system_profile', EJECT ??
*copy jmh$close_system_profile

  PROCEDURE [XDCL, #GATE] jmp$close_system_profile
    (    access_id: ost$binary_unique_name;
         detach_file: boolean;
         file_identifier: amt$file_identifier;
     VAR status: ost$status);

    VAR
      local_access_id: ost$binary_unique_name,
      local_status: ost$status;

    local_access_id := access_id;
    jmp$verify_utility_access_id (local_access_id, local_status);
    IF NOT local_status.normal THEN
      status := local_status;
      RETURN; {----->
    IFEND;

    fsp$close_file (file_identifier, status);

    IF status.normal AND detach_file THEN
      amp$return (jmc$scheduling_profile_pathname CAT '.1', status);
    IFEND;

  PROCEND jmp$close_system_profile;
?? TITLE := 'delete_classes', EJECT ??

  PROCEDURE delete_classes
    (    job_classes: jmt$job_class_set;
         service_classes: jmt$service_class_set;
         applications: jmt$application_set;
     VAR status: ost$status);

    VAR
      ai: jmt$application_index,
      am: jmt$application_index,
      jci: jmt$job_class,
      sci: jmt$service_class_index;

{            jme$class_or_appl_not_defined
{            jme$delete_class_still_active
{            jme$must_be scheduling_admin
{            jme$no_delete_of_default_class
{            jme$no_profile_is_loading
{            jme$no_utility_is_active

    FOR ai := 1 TO UPPERBOUND (the_applications^) DO
      IF ai IN applications THEN
        IF NOT the_applications^ [ai].defined THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Application',
                status);
          osp$append_status_integer (osc$status_parameter_delimiter, ai, 10, FALSE, status);
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;

{  Delete job classes

    FOR jci := 1 TO UPPERBOUND (the_job_classes^) DO
      IF jci IN job_classes THEN { validity checked in check_installability
        the_job_classes^ [jci].defined := FALSE;
      IFEND;
    FOREND;

{  Delete service classes

    FOR sci := 1 TO UPPERBOUND (the_service_classes^) DO
      IF sci IN service_classes THEN { validity checked in check_installability
        the_service_classes^ [sci].defined := FALSE;
      IFEND;
    FOREND;

{   Remove references to deleted service classes from job classes.

    FOR jci := 1 TO UPPERBOUND (the_job_classes^) DO
      IF the_job_classes^ [jci].defined THEN
        IF the_service_classes^ [the_job_classes^ [jci].initial_service_class_index].defined THEN
          the_job_classes^ [jci].initial_service_class_index := 3;
        IFEND;
      IFEND;
    FOREND;

{   Remove references to deleted service classes from other service classes.

    FOR sci := 1 TO UPPERBOUND (the_service_classes^) DO
      IF the_service_classes^ [sci].defined THEN
        IF the_service_classes^ [sci].next_service_class_index > 0 THEN
          IF the_service_classes^ [the_service_classes^ [sci].next_service_class_index].defined THEN
            the_service_classes^ [sci].next_service_class_index := sci;
          IFEND;
        IFEND;
      IFEND;
    FOREND;

{   Remove references to deleted service classes from applications

    am := 1;
    FOR ai := 1 TO UPPERBOUND (the_applications^) DO
      IF ai IN applications THEN
        the_applications^ [ai].defined := FALSE;
      ELSEIF the_applications^ [ai].defined THEN
        IF the_applications^ [ai].service_class_index > 0 THEN
          IF NOT the_service_classes^ [the_applications^ [ai].service_class_index].defined THEN
            the_applications^ [ai].service_class_index := 0;
          IFEND;
        IFEND;
        the_applications^ [am] := the_applications^ [ai];
        am := am + 1;
      IFEND;
    FOREND;

    FOR ai := am TO UPPERBOUND (the_applications^) DO
      the_applications^ [ai].defined := FALSE;
    FOREND;
  PROCEND delete_classes;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] jmp$delete_profile_cycle', EJECT ??
*copy jmh$delete_profile_cycle

  PROCEDURE [XDCL, #GATE] jmp$delete_profile_cycle
    (    access_id: ost$binary_unique_name;
         cycle_number: jmt$system_profile_cycle_number;
     VAR status: ost$status);

    VAR
      local_access_id: ost$binary_unique_name,
      local_status: ost$status;

    status.normal := TRUE;
    local_access_id := access_id;
    jmp$verify_utility_access_id (local_access_id, local_status);
    IF NOT local_status.normal THEN
      status := local_status;
      RETURN; {----->
    IFEND;

    delete_profile_cycle (cycle_number, status);

  PROCEND jmp$delete_profile_cycle;
?? OLDTITLE ??
?? TITLE := '[XDCL, #GATE] jmp$get_application_record', EJECT ??

*copyc jmh$get_application_record

  PROCEDURE [XDCL, #GATE] jmp$get_application_record
    (    application_name: jmt$application_name;
     VAR application_record: jmt$application_attributes;
     VAR status: ost$status);

{         Return the attribute record for the given application name.

    VAR
      ai: jmt$application_index;

{            jme$class_or_appl_not_defined
{            jme$must_be_scheduling_admin

    osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Application', status);
    osp$append_status_integer (osc$status_parameter_delimiter, ai, 10, FALSE, status);
    FOR ai := 1 TO UPPERBOUND (the_applications^) DO
      IF NOT the_applications^ [ai].defined THEN
        RETURN; {----->
      IFEND;
      IF the_applications^ [ai].name = application_name THEN
        application_record := the_applications^ [ai];
        status.normal := TRUE;
        RETURN; {----->
      IFEND;
    FOREND;

  PROCEND jmp$get_application_record;
?? TITLE := '[XDCL, #GATE] jmp$get_category_data', EJECT ??

*copyc jmh$get_category_data

  PROCEDURE [XDCL, #GATE] jmp$get_category_data
    (VAR category_data: jmt$job_category_data;
     VAR storage_p: ^SEQ ( * );
     VAR status: ost$status);

{             jme$must_be_scheduling_admin

    RESET storage_p;
    category_data := jmv$job_category_data;
    IF category_data.item_list <> NIL THEN
      NEXT category_data.item_list: [[REP #SIZE (category_data.item_list^) OF cell]] IN storage_p;
      category_data.item_list^ := jmv$job_category_data.item_list^;
    IFEND;
    IF category_data.category_names <> NIL THEN
      NEXT category_data.category_names: [0 .. UPPERBOUND (category_data.category_names^)] IN storage_p;
      category_data.category_names^ := jmv$job_category_data.category_names^;
    IFEND;
    status.normal := TRUE;

  PROCEND jmp$get_category_data;
?? TITLE := '[XDCL, #GATE] jmp$get_default_class_values', EJECT ??

*copyc jmh$get_default_class_values

  PROCEDURE [XDCL, #GATE] jmp$get_default_class_values
    (VAR job_class_defaults: jmt$job_class_attributes;
     VAR service_class_defaults: jmt$service_class_attributes;
     VAR application_defaults: jmt$application_attributes;
     VAR status: ost$status);

{         Return the default values for a job class, service class,
{         and application record.

    job_class_defaults := jc_default;
    service_class_defaults := sc_default;
    application_defaults := ap_default;
    status.normal := TRUE;

  PROCEND jmp$get_default_class_values;
?? TITLE := '[XDCL, #GATE] jmp$get_defined_classes', EJECT ??

*copyc jmh$get_defined_classes

  PROCEDURE [XDCL, #GATE] jmp$get_defined_classes
    (    class_kind: jmt$class_kind;
     VAR defined_classes: jmt$defined_classes;
     VAR number_of_classes: ost$non_negative_integers;
     VAR status: ost$status);

    VAR
      i: integer,
      j: integer;

{             jme$error_in_job_class_ranking
{             jme$must_be_scheduling_admin

    status.normal := TRUE;
    j := 0;
    CASE class_kind OF
    = jmc$job_class =
      i := the_job_classes^ [jmc$unassigned_job_class].next_rank_class;
      WHILE i <> 0 DO
        IF the_job_classes^ [i].defined THEN
          IF the_job_classes^ [i].automatic_class_selection THEN
            j := j + 1;
            defined_classes [j].name := the_job_classes^ [i].name;
            defined_classes [j].index := i;
          IFEND;
        IFEND;
        i := the_job_classes^ [i].next_rank_class;
      WHILEND;

      FOR i := 1 TO UPPERBOUND (the_job_classes^) DO
        IF the_job_classes^ [i].defined THEN
          IF NOT the_job_classes^ [i].automatic_class_selection THEN
            j := j + 1;
            defined_classes [j].name := the_job_classes^ [i].name;
            defined_classes [j].index := i;
          IFEND;
        IFEND;
      FOREND;

    = jmc$service_class =
      FOR i := 1 TO UPPERBOUND (the_service_classes^) DO
        IF the_service_classes^ [i].defined THEN
          j := j + 1;
          defined_classes [j].name := the_service_classes^ [i].name;
          defined_classes [j].index := i;
        IFEND;
      FOREND;

    = jmc$application =
      FOR i := 1 TO UPPERBOUND (the_applications^) DO
        IF the_applications^ [i].defined THEN
          j := j + 1;
          defined_classes [j].name := the_applications^ [i].name;
          defined_classes [j].index := i;
        IFEND;
      FOREND;
    CASEND;

    number_of_classes := j;
  PROCEND jmp$get_defined_classes;
?? TITLE := '[XDCL, #GATE] jmp$get_input_q_from_unassigned', EJECT ??

*copyc jmh$get_input_q_from_unassigned

  PROCEDURE [XDCL] jmp$get_input_q_from_unassigned
    (VAR system_supplied_names: array [1 .. * ] of jmt$system_supplied_name;
     VAR number_of_jobs_found: integer;
     VAR status: ost$status);

    VAR
      i: integer,
      j: integer,
      sjn: jmt$system_supplied_name,
      ujn: jmt$user_supplied_name,
      un: ost$unique_name;

    status.normal := TRUE;
    number_of_jobs_found := jobs_moved;
    IF UPPERBOUND (system_supplied_names) < number_of_jobs_found THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$result_array_too_small, '', status);
      RETURN; {----->
    IFEND;

    pmp$get_job_names (ujn, sjn, status);
    FOR i := 1 TO number_of_jobs_found DO
      pmp$generate_unique_name (un, status);
      system_supplied_names [i] := sjn;
      system_supplied_names [i] (16, 4) := un.sequence_number (3, 4);
    FOREND;

  PROCEND jmp$get_input_q_from_unassigned;
?? TITLE := '[XDCL, #GATE] jmp$get_job_class_record', EJECT ??

*copyc jmh$get_job_class_record

  PROCEDURE [XDCL, #GATE] jmp$get_job_class_record
    (    job_class_index: jmt$job_class;
     VAR job_class_record: jmt$job_class_attributes;
     VAR storage_p: ^SEQ ( * );
     VAR status: ost$status);

{             jme$class_or_appl_not_defined
{             jme$must_be_scheduling_admin

    RESET storage_p;

    IF NOT the_job_classes^ [job_class_index].defined THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Job Class', status);
      osp$append_status_integer (osc$status_parameter_delimiter, job_class_index, 10, FALSE, status);
      RETURN; {----->
    IFEND;

    job_class_record := the_job_classes^ [job_class_index];
    IF job_class_record.prolog_p <> NIL THEN
      NEXT job_class_record.prolog_p: [STRLENGTH (job_class_record.prolog_p^)] IN storage_p;
      job_class_record.prolog_p^ := the_job_classes^ [job_class_index].prolog_p^;
    IFEND;
    IF job_class_record.epilog_p <> NIL THEN
      NEXT job_class_record.epilog_p: [STRLENGTH (job_class_record.epilog_p^)] IN storage_p;
      job_class_record.epilog_p^ := the_job_classes^ [job_class_index].epilog_p^;
    IFEND;
    status.normal := TRUE;

  PROCEND jmp$get_job_class_record;
?? TITLE := '[XDCL, #GATE] jmp$get_job_class_statistics', EJECT ??

*copyc jmh$get_job_class_statistics

  PROCEDURE [XDCL, #GATE] jmp$get_job_class_statistics
    (    job_class_index: jmt$job_class;
     VAR job_class_statistics: jmt$job_class_statistics;
     VAR status: ost$status);

{             jme$class_or_appl_not_defined
{             jme$must_be_scheduling_admin

    IF NOT the_job_classes^ [job_class_index].defined THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Job Class', status);
      osp$append_status_integer (osc$status_parameter_delimiter, job_class_index, 10, FALSE, status);
      RETURN; {----->
    ELSE
      job_class_statistics.queued_jobs := job_class_index * 2;
      job_class_statistics.initiated_jobs := job_class_index + 10;
    IFEND;
    status.normal := TRUE;

  PROCEND jmp$get_job_class_statistics;
?? TITLE := '[XDCL, #GATE] jmp$get_length_of_sched_tables', EJECT ??

*copyc jmh$get_length_of_sched_tables

  PROCEDURE [XDCL, #GATE] jmp$get_length_of_sched_tables
    (VAR maximum_job_classes: jmt$job_class;
     VAR maximum_job_class_index: jmt$job_class;
     VAR maximum_service_classes: jmt$service_class_index;
     VAR maximum_service_class_index: jmt$service_class_index;
     VAR maximum_applications: jmt$application_index;
     VAR maximum_categories: integer;
     VAR status: ost$status);

{             jme$must_be_scheduling_admin

    maximum_job_classes := the_max.max_jc;
    maximum_service_classes := the_max.max_sc;
    maximum_applications := the_max.max_ap;
    maximum_job_class_index := the_max.max_jci;
    maximum_service_class_index := the_max.max_sci;
    maximum_categories := 64;
    status.normal := TRUE;

  PROCEND jmp$get_length_of_sched_tables;
?? TITLE := '[XDCL, #GATE] jmp$get_scheduler_table', EJECT ??

*copyc jmh$get_scheduler_table

  PROCEDURE [XDCL, #GATE] jmp$get_scheduler_table
    (VAR scheduler_table: jmt$job_scheduler_table;
     VAR data_p: ^SEQ ( * );
     VAR status: ost$status);

{             jme$must_be_scheduling_admin

    VAR
      mainframe_id: pmt$mainframe_id;

    status.normal := TRUE;
    scheduler_table := the_controls;
    RESET data_p;
    NEXT scheduler_table.validation_categories_p: [1 .. UPPERBOUND (the_controls.validation_categories_p^)] IN
          data_p;
    scheduler_table.validation_categories_p^ := the_controls.validation_categories_p^;
    IF scheduler_table.profile_identification = jmc$sched_profile_deadstart_id THEN
      pmp$get_mainframe_id (mainframe_id, status);
      IF status.normal THEN
        scheduler_table.validation_categories_p^ [1].mainframe_id := mainframe_id;
        pmp$convert_mainframe_to_binary (mainframe_id, scheduler_table.validation_categories_p^ [1].
              binary_mainframe_id, status);
      IFEND;
    IFEND;

  PROCEND jmp$get_scheduler_table;
?? TITLE := '[XDCL, #GATE] jmp$get_service_class_record', EJECT ??

*copyc jmh$get_service_class_record

  PROCEDURE [XDCL, #GATE] jmp$get_service_class_record
    (    service_class_index: jmt$service_class_index;
     VAR service_class_record: jmt$service_class_attributes;
     VAR status: ost$status);

{             jme$class_or_appl_not_defined
{             jme$must_be_scheduling_admin

    IF NOT the_service_classes^ [service_class_index].defined THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Service Class', status);
      osp$append_status_integer (osc$status_parameter_delimiter, service_class_index, 10, FALSE, status);
      RETURN; {----->
    IFEND;

    service_class_record := the_service_classes^ [service_class_index];
    status.normal := TRUE;

  PROCEND jmp$get_service_class_record;
?? TITLE := '[XDCL, #GATE] jmp$get_service_class_stats', EJECT ??

*copyc jmh$get_service_class_stats

  PROCEDURE [XDCL, #GATE] jmp$get_service_class_stats
    (    service_class_index: jmt$service_class_index;
     VAR service_class_statistics: jmt$service_class_statistics;
     VAR status: ost$status);

{             jme$class_or_appl_not_defined
{             jme$must_be_scheduling_admin

    IF NOT the_service_classes^ [service_class_index].defined THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Service Class', status);
      osp$append_status_integer (osc$status_parameter_delimiter, service_class_index, 10, FALSE, status);
      RETURN; {----->
    IFEND;
    status.normal := TRUE;
    service_class_statistics.active_jobs := service_class_index + 5;
    service_class_statistics.queued_jobs := service_class_index * 2;
    service_class_statistics.swapped_jobs := service_class_index + 1;

  PROCEND jmp$get_service_class_stats;
?? TITLE := 'delete_profile_cycle', EJECT ??

{ PURPOSE:
{   Deletes the specified cycle of the system profile file.

  PROCEDURE delete_profile_cycle
    (    cycle_number: fst$cycle_number;
     VAR status: ost$status);

    VAR
      the_cycle: pft$cycle_selector;

    the_cycle.cycle_option := pfc$specific_cycle;
    the_cycle.cycle_number := cycle_number;

    pfp$purge (path, the_cycle, password, status);
    IF NOT status.normal AND (status.condition = pfe$unknown_cycle) THEN
      status.normal := TRUE;
    IFEND;

  PROCEND delete_profile_cycle;
?? TITLE := 'move_jobs', EJECT ??

{ PURPOSE:
{   This request moves jobs from the specified job classes into the
{   UNASSIGNED job class.

  PROCEDURE move_jobs
    (    move_job_classes: jmt$job_class_set;
     VAR status: ost$status);

    VAR
      count: integer,
      jci: jmt$job_class;

{             jme$not_all_jobs_were_moved

    jobs_moved := 0;
    FOR jci := 1 TO UPPERBOUND (the_job_classes^) DO
      IF jci IN move_job_classes THEN
        jmp$move_input_q_to_unassigned (jci, count, status);
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;
  PROCEND move_jobs;
?? TITLE := '[XDCL, #GATE] jmp$install_profile', EJECT ??

*copyc jmh$install_profile

  PROCEDURE [XDCL, #GATE] jmp$install_profile
    (    access_id: ost$binary_unique_name;
         job_class_entries_p: ^jmt$job_class_table;
         service_class_entries_p: ^jmt$service_class_table;
         application_entries_p: ^jmt$application_table;
         controls_entry: jmt$job_scheduler_table;
         category_data: jmt$job_category_data;
         move_job_classes: jmt$job_class_set;
         deleted_job_classes: jmt$job_class_set;
         deleted_service_classes: jmt$service_class_set;
         deleted_applications: jmt$application_set;
         delete_profile_cycle2: boolean;
     VAR status: ost$status);

    VAR
      local_status: ost$status;

{             jme$access_id_mismatch
{             jme$applications_not_sorted
{             jme$class_abbrev_not_unique
{             jme$class_index_already_in_use
{             jme$class_or_appl_not_defined
{             jme$class_or_appl_not_unique
{             jme$delete_class_still_active
{             jme$excess_class_in_sched_table
{             jme$must_be_scheduling_admin
{             jme$not_all_jobs_were_moved
{             jme$no_delete_of_default_class
{             jme$no_utility_is_active
{             jme$profile_cycle2_lost
{             jme$profile_not_installed
{             jme$profile_too_large

    jmp$verify_utility_access_id (access_id, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    verify_profile (job_class_entries_p, service_class_entries_p, application_entries_p, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    check_installability (deleted_job_classes, deleted_service_classes, job_class_entries_p,
          service_class_entries_p, application_entries_p, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    jmp$set_sched_profile_loading (TRUE, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    move_jobs (move_job_classes, status);
    IF NOT status.normal THEN
      jmp$set_sched_profile_loading (FALSE, local_status);
      RETURN; {----->
    IFEND;

    delete_classes (deleted_job_classes, deleted_service_classes, deleted_applications, status);

    IF delete_profile_cycle2 THEN
      delete_profile_cycle (2, status);
    IFEND;

    install_profile (job_class_entries_p, service_class_entries_p, application_entries_p, controls_entry,
          category_data, status);

    jmp$set_sched_profile_loading (FALSE, local_status);

  PROCEND jmp$install_profile;

?? TITLE := 'install_profile', EJECT ??

  PROCEDURE install_profile
    (    job_classes_p: ^jmt$job_class_table;
         service_classes_p: ^jmt$service_class_table;
         applications_p: ^jmt$application_table;
         controls: jmt$job_scheduler_table;
         categories: jmt$job_category_data;
     VAR status: ost$status);

    VAR
      ai: jmt$application_index,
      an: jmt$application_name,
      first_ranked_class: integer,
      i: integer,
      jci: jmt$job_class,
      sci: jmt$service_class_index;

{             jme$applications_not_sorted
{             jme$class_abbrev_not_unique
{             jme$class_index_already_in_use
{             jme$class_or_appl_not_defined
{             jme$class_or_appl_not_unique
{             jme$excess_class_in_sched_table
{             jme$profile_not_installed
{             jme$profile_too_large

    FOR i := 1 TO UPPERBOUND (service_classes_p^) DO
      sci := service_classes_p^ [i].index;
      the_service_classes^ [sci] := service_classes_p^ [i];
    FOREND;

    the_job_classes^ [jmc$unassigned_job_class].next_rank_class := 0;
    first_ranked_class := 0;
    FOR i := UPPERBOUND (job_classes_p^) DOWNTO 1 DO
      jci := job_classes_p^ [i].index;
      IF the_job_classes^ [jci].prolog_p <> NIL THEN
        FREE the_job_classes^ [jci].prolog_p;
      IFEND;
      IF the_job_classes^ [jci].epilog_p <> NIL THEN
        FREE the_job_classes^ [jci].epilog_p;
      IFEND;
      the_job_classes^ [jci] := job_classes_p^ [i];
      jmv$profile_index_to_job_class [job_classes_p^ [i].profile_index] := jci;
      IF the_job_classes^ [jci].prolog_p <> NIL THEN
        ALLOCATE the_job_classes^ [jci].prolog_p: [STRLENGTH (the_job_classes^ [jci].prolog_p^)];
        the_job_classes^ [jci].prolog_p^ := job_classes_p^ [i].prolog_p^;
      IFEND;
      IF the_job_classes^ [jci].epilog_p <> NIL THEN
        ALLOCATE the_job_classes^ [jci].epilog_p: [STRLENGTH (the_job_classes^ [jci].epilog_p^)];
        the_job_classes^ [jci].epilog_p^ := job_classes_p^ [i].epilog_p^;
      IFEND;
      IF the_job_classes^ [jci].automatic_class_selection THEN
        the_job_classes^ [jci].next_rank_class := first_ranked_class;
        first_ranked_class := jci;
      ELSE
        the_job_classes^ [jci].next_rank_class := 0;
      IFEND;
    FOREND;
    the_job_classes^ [jmc$unassigned_job_class].next_rank_class := first_ranked_class;

{         - reallocate the valid_categories array of the controls table

{         - reallocate the applications table and store the applications
{           in ascending order

    FOR ai := 1 TO UPPERBOUND (the_applications^) DO
      the_applications^ [ai].defined := FALSE;
    FOREND;

    IF applications_p <> NIL THEN
      FOR ai := 1 TO UPPERBOUND (applications_p^) DO
        the_applications^ [ai] := applications_p^ [ai];
      FOREND;
    IFEND;

    IF jmv$job_category_data.item_list <> NIL THEN
      FREE jmv$job_category_data.item_list;
      jmv$job_category_data.item_list := NIL;
    IFEND;

    IF jmv$job_category_data.category_names <> NIL THEN
      FREE jmv$job_category_data.category_names;
      jmv$job_category_data.category_names := NIL;
    IFEND;

    jmv$job_category_data := categories;
    IF categories.item_list <> NIL THEN
      ALLOCATE jmv$job_category_data.item_list: [[REP #SIZE (categories.item_list^) OF cell]];
      jmv$job_category_data.item_list^ := categories.item_list^;
    IFEND;

    IF categories.category_names <> NIL THEN
      ALLOCATE jmv$job_category_data.category_names: [0 .. UPPERBOUND (categories.category_names^)];
      jmv$job_category_data.category_names^ := categories.category_names^;
    IFEND;

    FREE the_controls.validation_categories_p;

    the_controls := controls;

    ALLOCATE the_controls.validation_categories_p: [1 .. UPPERBOUND (controls.validation_categories_p^)];
    the_controls.validation_categories_p^ := controls.validation_categories_p^;
  PROCEND install_profile;

?? TITLE := 'verify_profile', EJECT ??

  PROCEDURE verify_profile
    (    job_classes_p: ^jmt$job_class_table;
         service_classes_p: ^jmt$service_class_table;
         applications_p: ^jmt$application_table;
     VAR status: ost$status);

    VAR
      ai: jmt$application_index,
      i: integer,
      jci: jmt$job_class,
      sci: jmt$service_class_index;

{   IF the_max.max_jc < UPPERBOUND (job_classes_p^) THEN
{     osp$set_status_abnormal (jmc$job_management_id, jme$profile_too_large,
{           'Maximum job classes', status);
{     osp$append_status_integer (osc$status_parameter_delimiter,
{     the_max.max_jc,
{           10, FALSE, status);
{     RETURN;
{   ELSEIF the_max.max_sc < UPPERBOUND (service_classes_p^) THEN
{     osp$set_status_abnormal (jmc$job_management_id, jme$profile_too_large,
{           'Maximum Service classes', status);
{     osp$append_status_integer (osc$status_parameter_delimiter,
{     the_max.max_sc,
{           10, FALSE, status);
{     RETURN;
{   IFEND;

    FOR i := 1 TO UPPERBOUND (service_classes_p^) DO
      sci := service_classes_p^ [i].index;
      IF sci > the_max.max_sci THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$profile_too_large, 'Maximum service class index',
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, sci, 10, FALSE, status);
        osp$append_status_integer (osc$status_parameter_delimiter, the_max.max_sci, 10, FALSE, status);
        RETURN; {----->
      IFEND;
    FOREND;

    FOR i := UPPERBOUND (job_classes_p^) DOWNTO 1 DO
      jci := job_classes_p^ [i].index;
      IF jci > the_max.max_jci THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$profile_too_large, 'Maximum job class index',
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, jci, 10, FALSE, status);
        osp$append_status_integer (osc$status_parameter_delimiter, the_max.max_jci, 10, FALSE, status);
        RETURN; {----->
      IFEND;
    FOREND;

    IF applications_p <> NIL THEN
      IF the_max.max_ap < UPPERBOUND (applications_p^) THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$profile_too_large, 'Applications', status);
        osp$append_status_integer (osc$status_parameter_delimiter, UPPERBOUND (applications_p^), 10, FALSE,
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, the_max.max_ap, 10, FALSE, status);
        RETURN; {----->
      IFEND;
    IFEND;

    status.normal := TRUE;

  PROCEND verify_profile;
?? TITLE := 'check_installability', EJECT ??

{ PURPOSE:
{   This routine checks for active jobs in the deleted job and service classes.

  PROCEDURE check_installability
    (    deleted_job_classes: jmt$job_class_set;
         deleted_service_classes: jmt$service_class_set;
         job_classes_p: ^jmt$job_class_table;
         service_classes_p: ^jmt$service_class_table;
         applications_p: ^jmt$application_table;
     VAR status: ost$status);

    VAR
      ai: jmt$application_index,
      an: jmt$application_name,
      first_ranked_class: integer,
      i: integer,
      jci: jmt$job_class,
      sci: jmt$service_class_index;

{             jme$applications_not_sorted
{             jme$class_abbrev_not_unique
{             jme$class_index_already_in_use
{             jme$class_or_appl_not_defined
{             jme$class_or_appl_not_unique
{             jme$excess_class_in_sched_table
{             jme$profile_not_installed
{             jme$profile_too_large

    status.normal := TRUE;

    FOR sci := 1 TO UPPERBOUND (the_service_classes^) DO
      IF sci IN deleted_service_classes THEN
        IF NOT the_service_classes^ [sci].defined THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Service Class',
                status);
          osp$append_status_integer (osc$status_parameter_delimiter, sci, 10, FALSE, status);
          RETURN; {----->
        ELSEIF sci < 4 THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$no_delete_of_default_class, 'Service Class',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, the_service_classes^ [sci].name,
                status);
          RETURN; {----->
        ELSEIF jobs_in_service_class (sci) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$delete_class_still_active, 'Service Class',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, the_service_classes^ [sci].name,
                status);
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;

    FOR i := 1 TO UPPERBOUND (service_classes_p^) DO
      sci := service_classes_p^ [i].index;
      IF NOT (sci IN deleted_service_classes) AND the_service_classes^ [sci].defined THEN
        IF the_service_classes^ [sci].name <> service_classes_p^ [i].name THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_index_already_in_use, 'Service Class',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, the_service_classes^ [sci].name,
                status);
          osp$append_status_integer (osc$status_parameter_delimiter, sci, 10, FALSE, status);
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;

    FOR jci := 1 TO UPPERBOUND (the_job_classes^) DO
      IF jci IN deleted_job_classes THEN
        IF NOT the_job_classes^ [jci].defined THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Job Class', status);
          osp$append_status_integer (osc$status_parameter_delimiter, jci, 10, FALSE, status);
          RETURN; {----->
        ELSEIF jci < 4 THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$no_delete_of_default_class, 'Job Class',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, the_job_classes^ [jci].name, status);
          RETURN; {----->
        ELSEIF initiated_jobs_in_job_class (jci) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$delete_class_still_active, 'Job Class', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, the_job_classes^ [jci].name, status);
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;

    FOR i := UPPERBOUND (job_classes_p^) DOWNTO 1 DO
      jci := job_classes_p^ [i].index;
      IF NOT (jci IN deleted_job_classes) AND the_job_classes^ [jci].defined THEN
        IF (the_job_classes^ [jci].name <> job_classes_p^ [i].name) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_index_already_in_use, 'Job Class',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, the_job_classes^ [jci].name, status);
          osp$append_status_integer (osc$status_parameter_delimiter, sci, 10, FALSE, status);
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;

    IF applications_p <> NIL THEN
      an := osc$null_name;
      FOR ai := 1 TO UPPERBOUND (applications_p^) DO
        IF applications_p^ [ai].name < an THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$applications_not_sorted,
                applications_p^ [ai].name, status);
          RETURN; {----->
        IFEND;
        an := applications_p^ [ai].name;
      FOREND;
    IFEND;

  PROCEND check_installability;
?? TITLE := 'jmp$move_input_q_to_unassigned', EJECT ??

  PROCEDURE jmp$move_input_q_to_unassigned
    (    job_class_index: jmt$job_class;
     VAR number_of_jobs: integer;
     VAR status: ost$status);

{             jme$class_or_appl_not_defined
{             jme$must_be_scheduling_admin
{             jme$not_all_jobs_were_moved

    IF NOT the_job_classes^ [job_class_index].defined THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Job Class', status);
      osp$append_status_integer (osc$status_parameter_delimiter, job_class_index, 10, FALSE, status);
      RETURN; {----->
    IFEND;

    status.normal := TRUE;
    number_of_jobs := job_class_index * 2;
    jobs_moved := jobs_moved + number_of_jobs;

  PROCEND jmp$move_input_q_to_unassigned;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] jmp$open_system_profile', EJECT ??
*copy jmh$open_system_profile

  PROCEDURE [XDCL, #GATE] jmp$open_system_profile
    (    access_id: ost$binary_unique_name;
         cycle_number: jmt$system_profile_cycle_number;
         open_for_write: boolean;
         validation_attributes_p: ^fst$file_cycle_attributes;
     VAR file_identifier: amt$file_identifier;
     VAR status: ost$status);

    CONST
      path_size = jmc$scheduling_profile_path_siz + 2;

    VAR
      attachment_options_p: ^fst$attachment_options,
      attribute_override_p: ^fst$file_cycle_attributes,
      caller_id: ost$caller_identifier,
      file_path: string (path_size),
      local_access_id: ost$binary_unique_name,
      local_status: ost$status;

    status.normal := TRUE;
    local_access_id := access_id;
    jmp$verify_utility_access_id (local_access_id, local_status);
    IF NOT local_status.normal THEN
      status := local_status;
      RETURN; {----->
    IFEND;

    #CALLER_ID (caller_id);

    file_path := jmc$scheduling_profile_pathname CAT '.1';
    IF cycle_number = 2 THEN
      file_path (path_size) := '2';
    IFEND;

{ Attach the file for read access and open the file with the rings of the
{ caller

    PUSH attribute_override_p: [1 .. 1];
    attribute_override_p^ [1].selector := fsc$ring_attributes;
    attribute_override_p^ [1].ring_attributes.r1 := osc$tsrv_ring;
    attribute_override_p^ [1].ring_attributes.r2 := caller_id.ring;
    attribute_override_p^ [1].ring_attributes.r3 := caller_id.ring;
    attribute_override_p := NIL;

    PUSH attachment_options_p: [1 .. 3];
    attachment_options_p^ [1].selector := fsc$access_and_share_modes;
    attachment_options_p^ [1].access_modes.selector := fsc$specific_access_modes;
    attachment_options_p^ [1].access_modes.value := $fst$file_access_options [fsc$read];
    attachment_options_p^ [1].share_modes.selector := fsc$specific_share_modes;
    attachment_options_p^ [1].share_modes.value := $fst$file_access_options [fsc$read];
    attachment_options_p^ [2].selector := fsc$open_position;
    attachment_options_p^ [2].open_position := amc$open_at_boi;
    attachment_options_p^ [3].selector := fsc$create_file;
    attachment_options_p^ [3].create_file := FALSE;

    IF open_for_write THEN
      attachment_options_p^ [1].access_modes.value := $fst$file_access_options
            [fsc$read, fsc$append, fsc$modify, fsc$shorten];
      attachment_options_p^ [3].create_file := TRUE;
      rmp$request_mass_storage (file_path, rmc$unspecified_allocation_size, rmc$unspecified_file_size,
            rmc$unspecified_file_class, rmc$unspecified_vsn, {volume_overflow_allowed =} TRUE, status);
    IFEND;
    IF status.normal THEN
      fsp$open_file (file_path, amc$segment, attachment_options_p, NIL, validation_attributes_p,
            validation_attributes_p, attribute_override_p, file_identifier, status);
    IFEND;

  PROCEND jmp$open_system_profile;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] jmp$reactivate_job_leveling' ??
*copyc jmh$reactivate_job_leveling

  PROCEDURE [XDCL, #GATE] jmp$reactivate_job_leveling
    (    access_id: ost$binary_unique_name;
     VAR status: ost$status);

    jmp$verify_utility_access_id (access_id, status);

  PROCEND jmp$reactivate_job_leveling;
?? TITLE := '[XDCL, #GATE] jmp$resubmit_queued_input_job', EJECT ??

*copyc jmh$resubmit_queued_input_job

  PROCEDURE [XDCL, #GATE] jmp$resubmit_queued_input_job
    (    system_supplied_name: jmt$system_supplied_name;
     VAR status: ost$status);

{             jme$job_class_must_be_disabled
{             jme$job_is_in_termination
{             jme$name_not_found

    status.normal := TRUE;
    IF system_supplied_name (18, 2) < '05' THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$invalid_job_class, '', status);
    IFEND;
    jobs_moved := 0;

  PROCEND jmp$resubmit_queued_input_job;
?? TITLE := 'jmp$set_sched_profile_loading', EJECT ??

  PROCEDURE jmp$set_sched_profile_loading
    (    profile_is_loading: boolean;
     VAR status: ost$status);

{             jme$must_be_scheduling_admin

    status.normal := TRUE;

  PROCEND jmp$set_sched_profile_loading;
?? TITLE := '[XDCL, #GATE] jmp$set_utility_active', EJECT ??

*copyc jmh$set_utility_active

  PROCEDURE [XDCL, #GATE] jmp$set_utility_active
    (VAR access_id: ost$binary_unique_name;
     VAR status: ost$status);

{             jme$another_utility_is_active
{             jme$must_be_scheduling_admin

    status.normal := TRUE;
    IF utility_active THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$another_utility_is_active, '', status);
      RETURN; {----->
    IFEND;
    utility_active := TRUE;

    read_system_tables (status);
    IF status.normal THEN
      access_id := the_access_id;
    IFEND;
  PROCEND jmp$set_utility_active;
?? TITLE := '[XDCL, #GATE] jmp$update_profile', EJECT ??

*copyc jmh$update_profile

  PROCEDURE [XDCL, #GATE] jmp$update_profile
    (    access_id: ost$binary_unique_name;
         changed_job_classes_p: ^jmt$job_class_table;
         changed_service_classes_p: ^jmt$service_class_table;
         changed_applications_p: ^jmt$application_table;
         controls_p: ^jmt$job_scheduler_table;
     VAR status: ost$status);

    VAR
      ai: jmt$application_index,
      i: integer,
      jci: jmt$job_class,
      nrc: integer,
      sci: jmt$service_class_index;

{             jme$access_id_mismatch
{             jme$class_index_conflict
{             jme$class_or_appl_not_defined
{             jme$must_be_scheduling_admin
{             jme$no_utility_is_active

    jmp$verify_utility_access_id (access_id, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF changed_service_classes_p <> NIL THEN
      FOR i := 1 TO UPPERBOUND (changed_service_classes_p^) DO
        sci := changed_service_classes_p^ [i].index;
        IF NOT the_service_classes^ [sci].defined THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Service Class',
                status);
          osp$append_status_integer (osc$status_parameter_delimiter, sci, 10, FALSE, status);
          RETURN; {----->
        IFEND;
        IF the_service_classes^ [sci].profile_identification <>
              changed_service_classes_p^ [i].profile_identification THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_index_conflict, 'Job Class', status);
          RETURN; {----->
        IFEND;
        the_service_classes^ [sci] := changed_service_classes_p^ [i];
      FOREND;
    IFEND;

    IF changed_job_classes_p <> NIL THEN
      FOR i := 1 TO UPPERBOUND (changed_job_classes_p^) DO
        jci := changed_job_classes_p^ [i].index;
        IF NOT the_job_classes^ [jci].defined THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_or_appl_not_defined, 'Job Class', status);
          osp$append_status_integer (osc$status_parameter_delimiter, jci, 10, FALSE, status);
          RETURN; {----->
        IFEND;
        IF the_job_classes^ [jci].profile_identification <> changed_job_classes_p^ [i].
              profile_identification THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$class_index_conflict, 'Job Class', status);
          RETURN; {----->
        IFEND;
        IF the_job_classes^ [jci].prolog_p <> NIL THEN
          FREE the_job_classes^ [jci].prolog_p;
        IFEND;
        IF the_job_classes^ [jci].epilog_p <> NIL THEN
          FREE the_job_classes^ [jci].epilog_p;
        IFEND;
        nrc := the_job_classes^ [jci].next_rank_class;
        the_job_classes^ [jci] := changed_job_classes_p^ [i];
        the_job_classes^ [jci].next_rank_class := nrc;
        IF the_job_classes^ [jci].prolog_p <> NIL THEN
          ALLOCATE the_job_classes^ [jci].prolog_p: [STRLENGTH (the_job_classes^ [jci].prolog_p^)];
          the_job_classes^ [jci].prolog_p^ := changed_job_classes_p^ [i].prolog_p^;
        IFEND;
        IF the_job_classes^ [jci].epilog_p <> NIL THEN
          ALLOCATE the_job_classes^ [jci].epilog_p: [STRLENGTH (the_job_classes^ [jci].epilog_p^)];
          the_job_classes^ [jci].epilog_p^ := changed_job_classes_p^ [i].epilog_p^;
        IFEND;
      FOREND;
    IFEND;

    IF changed_applications_p <> NIL THEN

    /next_application/
      FOR i := 1 TO UPPERBOUND (changed_applications_p^) DO
        FOR ai := 1 TO UPPERBOUND (the_applications^) DO
          IF the_applications^ [ai].name = changed_applications_p^ [i].name THEN
            the_applications^ [ai] := changed_applications_p^ [i];
            CYCLE /next_application/; {----->
          IFEND;
        FOREND;
        osp$set_status_abnormal (jmc$job_management_id, jme$class_index_conflict, 'Applications', status);
        RETURN; {----->
      FOREND /next_application/;
    IFEND;

    IF controls_p <> NIL THEN
      the_controls.enable_job_leveling := controls_p^.enable_job_leveling;
      the_controls.job_leveling_interval := controls_p^.job_leveling_interval;
      the_controls.service_calculation_interval := controls_p^.service_calculation_interval;
      the_controls.idle_dispatching_queue_time := controls_p^.idle_dispatching_queue_time;
      the_controls.scheduling_memory_levels := controls_p^.scheduling_memory_levels;
      the_controls.initiation_required_categories := controls_p^.initiation_required_categories;
      the_controls.initiation_excluded_categories := controls_p^.initiation_excluded_categories;
      the_controls.job_leveling_priority_bias := controls_p^.job_leveling_priority_bias;
    IFEND;
  PROCEND jmp$update_profile;
?? TITLE := 'read_system_tables', EJECT ??

  PROCEDURE read_system_tables
    (VAR status: ost$status);

    VAR
      read_attachment: [STATIC] array [1 .. 2] of fst$attachment_option :=
            [[fsc$access_and_share_modes, [fsc$specific_access_modes, [fsc$read]],
            [fsc$specific_share_modes, []]], [fsc$open_position, amc$open_at_boi]];

    VAR
      fid: amt$file_identifier,
      local_status: ost$status,
      seg_ptr: amt$segment_pointer,
      the_seq: ^SEQ ( * );

    VAR
      cd: jmt$job_category_data,
      epilog_p: ^fst$file_reference,
      i: integer,
      j: integer,
      k: integer,
      prolog_p: ^fst$file_reference,
      the_header: jmt$profile_header,
      tm: ^maximums,
      validation_categories: ^jmt$mainframe_categories;

    VAR
      access_mode: clt$data_access_mode,
      class: clt$variable_class,
      evaluation_method: clt$expression_eval_method,
      type_specification: ^clt$type_specification,
      value: ^clt$data_value,
      work_area: ^clt$work_area;

  /read_file/
    BEGIN

      fsp$open_file (base_file, amc$segment, ^read_attachment, NIL, NIL, ^required_attributes, NIL, fid,
            status);
      IF NOT status.normal THEN
        EXIT /read_file/; {----->
      IFEND;

      amp$get_segment_pointer (fid, amc$sequence_pointer, seg_ptr, status);
      IF NOT status.normal THEN
        EXIT /read_file/; {----->
      IFEND;
      RESET seg_ptr.sequence_pointer;
      the_seq := seg_ptr.sequence_pointer;

      NEXT tm IN the_seq;
      the_max := tm^;

      NEXT controls_p IN the_seq;
      the_controls := controls_p^;

      NEXT validation_categories: [1 .. UPPERBOUND (the_controls.validation_categories_p^)] IN the_seq;
      ALLOCATE the_controls.validation_categories_p: [1 .. UPPERBOUND (validation_categories^)];
      the_controls.validation_categories_p^ := validation_categories^;

      NEXT job_classes_p: [1 .. the_max.max_jci] IN the_seq;
      NEXT service_classes_p: [1 .. the_max.max_sci] IN the_seq;
      NEXT applications_p: [1 .. the_max.max_ap] IN the_seq;

      ALLOCATE the_job_classes: [1 .. the_max.max_jci];
      ALLOCATE the_service_classes: [1 .. the_max.max_sci];
      ALLOCATE the_applications: [1 .. the_max.max_ap];

      the_job_classes^ := job_classes_p^;
      the_service_classes^ := service_classes_p^;
      the_applications^ := applications_p^;

      FOR i := 1 TO UPPERBOUND (the_job_classes^) DO
        IF the_job_classes^ [i].defined THEN
          prolog_p := the_job_classes^ [i].prolog_p;
          IF prolog_p <> NIL THEN
            NEXT prolog_p: [STRLENGTH (prolog_p^)] IN the_seq;
            ALLOCATE the_job_classes^ [i].prolog_p: [STRLENGTH (prolog_p^)];
            the_job_classes^ [i].prolog_p^ := prolog_p^;
          IFEND;
          epilog_p := the_job_classes^ [i].epilog_p;
          IF epilog_p <> NIL THEN
            NEXT epilog_p: [STRLENGTH (epilog_p^)] IN the_seq;
            ALLOCATE the_job_classes^ [i].epilog_p: [STRLENGTH (epilog_p^)];
            the_job_classes^ [i].epilog_p^ := epilog_p^;
          IFEND;
        IFEND;
      FOREND;

      NEXT category_data_p IN the_seq;
      jmv$job_category_data := category_data_p^;
      cd := category_data_p^;

      IF cd.item_list <> NIL THEN
        NEXT cd.item_list: [[REP #SIZE (cd.item_list^) OF cell]] IN the_seq;
        ALLOCATE jmv$job_category_data.item_list: [[REP #SIZE (cd.item_list^) OF cell]];
        jmv$job_category_data.item_list^ := cd.item_list^;
      IFEND;

      IF cd.category_names <> NIL THEN
        NEXT cd.category_names: [0 .. UPPERBOUND (cd.category_names^)] IN the_seq;
        ALLOCATE jmv$job_category_data.category_names: [0 .. UPPERBOUND (cd.category_names^)];
        jmv$job_category_data.category_names^ := cd.category_names^;
      IFEND;

      fsp$close_file (fid, local_status);
      RETURN; {----->

    END /read_file/;

    fsp$close_file (fid, local_status);

    PUSH work_area: [[REP 100 OF clt$data_value]];
    clp$get_variable ('SCHEDULER_LIMITS', work_area, class, access_mode, evaluation_method,
          type_specification, value, local_status);
    IF local_status.normal THEN
      i := 1;
      WHILE (value <> NIL) AND (value^.kind = clc$list) DO
        IF value^.element_value^.kind = clc$integer THEN
          j := value^.element_value^.integer_value.value;
          CASE i OF
          = 1 =
            the_max.max_jc := j;
            the_max.max_jci := j;
          = 2 =
            the_max.max_jci := j;
          = 3 =
            the_max.max_sc := j;
            the_max.max_sci := j;
          = 4 =
            the_max.max_sci := j;
          = 5 =
            the_max.max_ap := j;
          ELSE
          CASEND;
        IFEND;
        i := i + 1;
        value := value^.link;
      WHILEND;
    IFEND;

    read_profile (the_header, status);
    IF status.normal THEN
      IF the_max.max_jci < the_header.maximum_job_class_index THEN
        the_max.max_jci := the_header.maximum_job_class_index;
      IFEND;
      IF the_max.max_sci < the_header.maximum_service_class_index THEN
        the_max.max_sci := the_header.maximum_service_class_index;
      IFEND;
      IF the_max.max_ap < the_header.application_count THEN
        the_max.max_ap := the_header.application_count;
      IFEND;
    IFEND;

    ALLOCATE the_controls.validation_categories_p: [1 .. UPPERBOUND (validation_list)];
    the_controls.validation_categories_p^ := validation_list;

    ALLOCATE the_job_classes: [1 .. the_max.max_jci];
    ALLOCATE the_service_classes: [1 .. the_max.max_sci];
    ALLOCATE the_applications: [1 .. the_max.max_ap];

    FOR i := 1 TO the_max.max_jci DO
      IF i < 4 THEN
        the_job_classes^ [i] := default_job_classes [i];
      ELSE
        the_job_classes^ [i] := default_job_classes [4];
      IFEND;
    FOREND;

    FOR i := 1 TO the_max.max_sci DO
      IF i < 4 THEN
        the_service_classes^ [i] := default_service_classes [i];
      ELSE
        the_service_classes^ [i] := default_service_classes [4];
      IFEND;
    FOREND;

    FOR i := 1 TO the_max.max_ap DO
      the_applications^ [i] := default_applications [1];
    FOREND;

    status.normal := TRUE;
  PROCEND read_system_tables;
?? TITLE := 'write_system_tables [xdcl]', EJECT ??

  PROCEDURE write_system_tables
    (VAR status: ost$status);

    VAR
      write_attachment: [STATIC] array [1 .. 3] of fst$attachment_option :=
            [[fsc$access_and_share_modes, [fsc$specific_access_modes,
            [fsc$read, fsc$append, fsc$modify, fsc$shorten]], [fsc$specific_share_modes, []]],
            [fsc$create_file, TRUE], [fsc$open_position, amc$open_at_boi]];

    VAR
      fid: amt$file_identifier,
      local_status: ost$status,
      seg_ptr: amt$segment_pointer,
      the_seq: ^SEQ ( * );

    VAR
      cd: jmt$job_category_data,
      epilog_p: ^fst$file_reference,
      i: integer,
      prolog_p: ^fst$file_reference,
      tm: ^maximums,
      validation_categories: ^jmt$mainframe_categories;

    fsp$open_file (base_file, amc$segment, ^write_attachment, NIL, ^required_attributes, ^required_attributes,
          NIL, fid, status);
    IF NOT status.normal THEN
      fsp$close_file (fid, local_status);
      RETURN {----->
    IFEND;

    amp$get_segment_pointer (fid, amc$sequence_pointer, seg_ptr, status);
    IF NOT status.normal THEN
      fsp$close_file (fid, local_status);
      RETURN {----->
    IFEND;
    RESET seg_ptr.sequence_pointer;
    the_seq := seg_ptr.sequence_pointer;

    NEXT tm IN the_seq;
    tm^ := the_max;

    NEXT controls_p IN the_seq;
    controls_p^ := the_controls;

    NEXT validation_categories: [1 .. UPPERBOUND (the_controls.validation_categories_p^)] IN the_seq;
    validation_categories^ := the_controls.validation_categories_p^;

    NEXT job_classes_p: [1 .. the_max.max_jci] IN the_seq;
    NEXT service_classes_p: [1 .. the_max.max_sci] IN the_seq;
    NEXT applications_p: [1 .. the_max.max_ap] IN the_seq;

    job_classes_p^ := the_job_classes^;
    service_classes_p^ := the_service_classes^;
    applications_p^ := the_applications^;

    FOR i := 1 TO UPPERBOUND (the_job_classes^) DO
      IF the_job_classes^ [i].defined THEN
        IF the_job_classes^ [i].prolog_p <> NIL THEN
          NEXT prolog_p: [STRLENGTH (the_job_classes^ [i].prolog_p^)] IN the_seq;
          prolog_p^ := the_job_classes^ [i].prolog_p^;
        IFEND;
        IF the_job_classes^ [i].epilog_p <> NIL THEN
          NEXT epilog_p: [STRLENGTH (the_job_classes^ [i].epilog_p^)] IN the_seq;
          epilog_p^ := the_job_classes^ [i].epilog_p^;
        IFEND;
      IFEND;
    FOREND;

    NEXT category_data_p IN the_seq;
    cd := jmv$job_category_data;

    IF cd.item_list <> NIL THEN
      NEXT cd.item_list: [[REP #SIZE (cd.item_list^) OF cell]] IN the_seq;
      cd.item_list^ := jmv$job_category_data.item_list^;
      FREE jmv$job_category_data.item_list;
    IFEND;

    IF cd.category_names <> NIL THEN
      NEXT cd.category_names: [0 .. UPPERBOUND (cd.category_names^)] IN the_seq;
      cd.category_names^ := jmv$job_category_data.category_names^;
      FREE jmv$job_category_data.category_names;
    IFEND;
    category_data_p^ := cd;

    fsp$close_file (fid, status);

  PROCEND write_system_tables;

?? TITLE := 'read_profile', EJECT ??

{ PURPOSE:
{   This interface reads the profile from the specified file.

  PROCEDURE read_profile
    (VAR profile_header: jmt$profile_header;
     VAR status: ost$status);

    VAR
      profile_file: ^SEQ ( * );

    VAR
      read_attachment: [STATIC] array [1 .. 2] of fst$attachment_option :=
            [[fsc$access_and_share_modes, [fsc$specific_access_modes, [fsc$read]],
            [fsc$specific_share_modes, []]], [fsc$open_position, amc$open_at_boi]];

    VAR
      required_attributes: [STATIC] array [1 .. 3] of fst$file_cycle_attribute :=
            [[fsc$file_contents_and_processor, 'SCHEDULING_PROFILE', 'ADMINISTER_SCHEDULING'],
            [fsc$file_organization, amc$byte_addressable], [fsc$record_type, amc$undefined]];

    VAR
      file: clt$file,
      header: ^jmt$profile_header,
      local_status: ost$status,
      profile_file_identifier: amt$file_identifier,
      segment_pointer: amt$segment_pointer;

    clp$convert_string_to_file (jmc$scheduling_profile_pathname, file, status);

    fsp$open_file (file.local_file_name, amc$segment, ^read_attachment, NIL, NIL, ^required_attributes, NIL,
          profile_file_identifier, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

  /read_file/
    BEGIN

      amp$get_segment_pointer (profile_file_identifier, amc$sequence_pointer, segment_pointer, status);
      IF NOT status.normal THEN
        EXIT /read_file/; {----->
      IFEND;

      RESET segment_pointer.sequence_pointer;
      profile_file := segment_pointer.sequence_pointer;

      NEXT header IN profile_file;
      IF header = NIL THEN
        status.normal := FALSE;
        EXIT /read_file/; {----->
      IFEND;

      IF header^.version <> jmc$profile_version THEN
        status.normal := FALSE;
        EXIT /read_file/; {----->
      IFEND;

      profile_header := header^;

    END /read_file/;

    fsp$close_file (profile_file_identifier, local_status);
  PROCEND read_profile;

MODEND jmm$the_stubs;

