?? NEWTITLE := 'NOS/VE Job Scheduling : administer definitions' ??
MODULE jmm$administer_definitions;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains the data declarations and routines that
{   are used to build the data structures that define the objects and
{   attributes of these objects for the scheduling profile.  These
{   data structures are used by the modules when displaying, building,
{   and merging of attribute lists and objects.
{
{ DESIGN:
{   The attribute structure for each object is a tree structure.  The
{   definitions here express this tree structure in a flat form.  The
{   routines in this module convert this flat form into the actual tree
{   structure.  The preset routine also builds the default profile.
{
{ NOTES:
{   See JMM$ADMINISTER_OBJECTS
{       JMM$ADMINISTER_ATTRIBUTES

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
*copyc jmt$profile_data
*copyc jmt$object_definition
?? PUSH (LISTEXT := ON) ??
*copyc jme$job_scheduler_conditions
*copyc jme$profile_internal_error
*copyc jmc$class_names
*copyc jmc$job_management_id
*copyc jmc$maximum_mainframes
*copyc jmc$profile_constants
*copyc jmt$application_index
*copyc jmt$job_category
*copyc jmt$job_class
*copyc jmt$job_class_attributes
*copyc jmt$job_scheduler_table
*copyc jmt$output_class_attributes
*copyc jmt$output_class_index
*copyc jmt$profile_header
*copyc jmt$service_class_attributes
*copyc jmt$service_class_index
?? POP ??
*copyc jmp$copy_attributes
*copyc jmp$delete_attributes
*copyc jmp$add_object
*copyc jmp$get_default_class_values
*copyc jmp$set_object_default
*copyc mmp$create_scratch_segment
*copyc osp$get_cpu_model_definition
*copyc osp$set_status_abnormal
*copyc osp$append_status_parameter
*copyc pmp$abort
*copyc pmp$convert_mainframe_to_binary
*copyc pmp$get_mainframe_id

*copyc jmv$current_class_name
*copyc jmv$current_profile_level
*copyc osv$lower_to_upper
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] JMV$THE_PROFILE', EJECT ??

{ PURPOSE:
{   Defines the working profile.
{
{ DESIGN:
{   The variable contains the profile identifier, counts of the number of
{   objects of each type, and a pointer to the head object for each type.
{   The procedures in JMM$ADMINISTER_ATTRIBUTES, and JMM$ADMINISTER_OBJECTS
{   manipulate the data referenced by this variable.

  VAR
    jmv$the_profile: [XDCL, #GATE] jmt$profile_data :=
          ['EMPTY', [REP object_kind_count of NIL],
          [REP object_kind_count of 0]];

?? TITLE := '[XDCL] JMV$NEW_PROFILE', EJECT ??

{ Global variable JMV$NEW_PROFILE
{ PURPOSE:
{   This variable is used to hold the definition of a profile read from
{   a profile file until it is made the working profile.
{
{ DESIGN:
{   The variable contains the profile identifier, counts of the number of
{   objects of each type, and a pointer to the head object for each type.

  VAR
    jmv$new_profile: [XDCL] jmt$profile_data :=
          ['EMPTY', [REP object_kind_count of NIL],
          [REP object_kind_count of 0]];

?? TITLE := '[XDCL, #GATE] JMV$OBJECT_DEFINITION', EJECT ??

{ PURPOSE:
{   This definition is used when reading a profile to verify the data on the
{   file; when displaying the attributes to determine the attribute class_name,
{   attribute groups and set the defaults for unspecified attributes of an
{   object; when building the system tables to set the defaults for unspecified
{   attributes of an object; when processing an scl command list to determine
{   the parameter class_name and to impose a structure on the parameter data.
{
{ DESIGN:
{   This variable is the starting point in a tree structure that defines the
{   structure of a scheduling profile - the structure of the attributes for
{   each of the object types, and the default values for each node in the
{   attribute tree structure for an object type.

?? FMT (FORMAT := OFF) ??

  VAR
    jmv$object_definition: [XDCL, #GATE] jmt$object_definition := [
      [['JOB_CATEGORY   ', 'JCA', *, jmc$none], ^fetch_standard_defaults,
          jmc$maximum_job_categories, NIL, NIL],
      [['JOB_PRIORITY   ', 'JP', *, jmc$none], ^fetch_standard_defaults,
          0, NIL, NIL],
      [['OUTPUT_CATEGORY', 'OC', *, jmc$none], ^fetch_standard_defaults,
          0, NIL, NIL],
      [['RESERVED       ', '--', *, jmc$none], ^fetch_standard_defaults,
          0, NIL, NIL],
      [['CONTROLS       ', 'C ', *, jmc$none], ^fetch_controls_defaults,
          jmc$maximum_mainframes, ^check_controls_attributes, NIL],
      [['JOB_CLASS      ', 'JCL', *, jmc$none], ^fetch_job_class_defaults,
          jmc$maximum_job_classes, ^check_job_class_attributes, NIL],
      [['SERVICE_CLASS  ', 'SC', *, jmc$none], ^fetch_standard_defaults,
          jmc$maximum_service_classes, NIL, NIL],
      [['OUTPUT_CLASS   ', 'OC', *, jmc$none], ^fetch_standard_defaults,
          jmc$maximum_output_classes, NIL, NIL],
      [['APPLICATION    ', 'A ', *, jmc$none], ^fetch_standard_defaults,
          jmc$maximum_application_index, NIL, NIL]];

?? FMT (FORMAT := ON) ??

?? TITLE := '[XDCL, #GATE] JMV$OBJECT_HEAP', EJECT ??

{ PURPOSE:
{   This variable references a heap that is used for allocating object and
{   attribute structures to be included in the JMV$THE_PROFILE and
{   JMV$NEW_PROFILE profile definitions.
{
{ NOTES:
{   The heap is created at utility initiation by requesting a segment as a
{   heap.

  VAR
    jmv$object_heap: [XDCL, #GATE] ^HEAP ( * );

?? TITLE := '[XDCL, #GATE] JMV$WORKING_STORAGE', EJECT ??

{ PURPOSE:
{   Provides temporary memory for building structures that have a limited
{   lifetime (a subcommand or less) but never the less must survive across
{   procedure calls.  For instance, when creating the system tables, the
{   tables are allocated from here, and the attributes for each object are
{   expanded to full depth assigning a value to each node in the list by
{   building the expanded list out of this storage area.
{
{ DESIGN:
{   Structures are allocated using NEXTs.  When the structures are no longer
{   needed then the sequence can be reset.

  VAR
    jmv$working_storage: [XDCL, #GATE] ^SEQ ( * );

?? TITLE := 'Declarations for This Module', EJECT ??

  CONST
    object_kind_count = 9;

  CONST
    lowest_idle_disp_q_time = jmc$lowest_idle_disp_q_time DIV 1000000,
    highest_idle_disp_q_time = jmc$highest_idle_disp_q_time DIV 1000000;

  CONST
    lowest_prio_age_interval = jmc$lowest_prio_age_interval DIV 1000000,
    highest_prio_age_interval = jmc$highest_prio_age_interval DIV 1000000;

  VAR
    mainframe_id: pmt$mainframe_id,
    abbreviation: ost$name := osc$null_name,
    empty_declaration: jmt$profile_declaration :=
          ['EMPTY', 'E', * , jmc$empty];

  CONST
    maximum_list_size = 4095;

  TYPE
    structure_list = array [1 .. * ] of attribute_structure,

    attribute_structure = record
      list_index: 1 .. maximum_list_size,
      definition: jmt$profile_declaration,
      default: jmt$object_attribute,
    recend;

  VAR
    object_structure: array [jmt$profile_object_kinds] of ^structure_list :=
          [^category_structure, ^priority_structure, ^empty_structure,
          ^empty_structure, ^controls_structure, ^job_class_structure,
          ^service_class_structure, ^output_class_structure,
          ^application_structure];

  VAR
    empty_structure: array [1 .. 1] of attribute_structure :=
          [[1, ['--', '--', * , jmc$empty], [jmc$empty]]];

  TYPE
    attribute_preset_list = array [1 .. * ] of attribute_preset,
    attribute_preset = record
      list_index: 0 .. maximum_list_size,
      attribute: jmt$object_attribute,
    recend;

  VAR
    object_attribute_defaults: array [jmt$profile_object_kinds] of
          jmt$object_attribute := [REP object_kind_count of [jmc$none]];

  TYPE
    job_and_service_classes = (interactive, batch, system, maintenance,
          unassigned);

?? TITLE := 'Job Category Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    category_descriptor_count = 39;

  VAR
    category_structure: array [1 .. category_descriptor_count] of
        attribute_structure := [

  [1, ['JOB_CATEGORY', 'JCA', * , jmc$type, jmc$c_maximum_attribute, * ],
          [jmc$type, * ]],

{ CPU_TIME_LIMIT                 = range of integer

    [jmc$c_cpu_time_limit, ['Cpu_Time_Limit', 'CTL', jmc$membership_group,
          jmc$range, 1, * ], [jmc$empty]],
      [1, ['Cpu_Time_Limit', '--', * , jmc$number, jmc$lowest_cpu_time_limit,
          jmc$highest_cpu_time_limit], [jmc$empty]],

{ JOB_MODE                       = list of name

    [jmc$c_job_mode, ['Job_Mode', 'JM', jmc$membership_group, jmc$list, 1, * ],
          [jmc$empty]],
      [1, ['Job_Mode', '--', * , jmc$name], [jmc$empty]],

{ JOB_PRIORITY

{   [jmc$c_job_priority, ['Job_Priority', 'JP', jmc$membership_group, jmc$list,
{         1, * ], [jmc$empty]],
{     [1, ['--', '--', * , jmc$object, jmc$profile_priority], [jmc$empty]],

{ JOB_QUALIFIER                  = list of name

    [jmc$c_job_qualifier, ['Job_Qualifier', 'JQ', jmc$membership_group,
          jmc$list, 1, * ], [jmc$empty]],
      [1, ['Job_Qualifier', '--', * , jmc$name], [jmc$empty]],

{ LOGIN_FAMILY                   = list of name

    [jmc$c_login_family, ['Login_Family', 'LF', jmc$membership_group, jmc$list,
          1, * ], [jmc$empty]],
      [1, ['Login_Family', '--', * , jmc$name], [jmc$empty]],

{ LOGIN_USER                     = list of name

    [jmc$c_login_user, ['Login_User', 'LU', jmc$membership_group, jmc$list,
          1, *], [jmc$empty]],
      [1, ['Login_User', '--', * , jmc$name], [jmc$empty]],

{ LOGIN_PROJECT                  = list of name

    [jmc$c_login_project, ['Login_Project', 'LP', jmc$membership_group,
          jmc$list, 1, * ], [jmc$empty]],
      [1, ['Login_Project', '--', * , jmc$name], [jmc$empty]],

{ LOGIN_ACCOUNT                  = list of name

    [jmc$c_login_account, ['Login_Account', 'LA', jmc$membership_group,
          jmc$list, 1, * ], [jmc$empty]],
      [1, ['Login_Account', '--', * , jmc$name], [jmc$empty]],

{ MAGNETIC_TAPE_LIMIT            = range of integer

    [jmc$c_magnetic_tape_limit, ['Magnetic_Tape_Limit', 'MTL',
          jmc$membership_group, jmc$range, 1, * ], [jmc$empty]],
      [1, ['Magnetic_Tape_Limit', '--', * , jmc$number,
            jmc$lowest_magnetic_tape_limit, jmc$highest_magnetic_tape_limit],
        [jmc$empty]],

{ ORIGINATING_APPLICATION_NAME   = list of name

    [jmc$c_origin_application_name, ['Originating_Application_Name', 'OAN',
          jmc$membership_group, jmc$list, 1, * ], [jmc$empty]],
      [1, ['Originating_Application_Name', '--', * , jmc$name], [jmc$empty]],

{ SRU_LIMIT                      = range of integer

    [jmc$c_sru_limit, ['Sru_Limit', 'SL', jmc$membership_group, jmc$range,
          1, * ], [jmc$empty]],
      [1, ['Sru_Limit', '--', * , jmc$number, jmc$lowest_sru_limit,
            jmc$highest_sru_limit], [jmc$empty]],

{ USER_JOB_NAME                  = list of name

    [jmc$c_user_job_name, ['User_Job_Name', 'UJN', jmc$membership_group,
          jmc$list, 1, * ], [jmc$empty]],
      [1, ['User_Job_Name', '--', * , jmc$name], [jmc$empty]],

{ MAXIMUM_WORKING_SET            = range of integer

    [jmc$c_maximum_working_set, ['Maximum_Working_Set', 'MAXWS',
          jmc$membership_group, jmc$range, 1, * ], [jmc$empty]],
      [1, ['Maximum_Working_Set', '--', * , jmc$number,
            jmc$lowest_working_set_size, jmc$highest_working_set_size],
        [jmc$empty]],

{ CATEGORY_DEFINITION            = list of record
{     SKIP_ITEM                  = integer
{     NEXT_ITEM                  = integer
{     CATEGORIES                 = list of jmc$profile_category
{     TYPE                       = name
{     MEMBERS                    = list of jmc$profile_category OR
{                                    name OR integer

    [jmc$c_data_display, ['Category_Data_Display', 'CDD', jmc$statistic_group,
          jmc$list, 1, * ], [jmc$empty]],
      [1, ['--', '--', * , jmc$type, 5, * ], [jmc$type, * ]],
        [1, ['Skip_Item', 'SI', * , jmc$number, 0, 0], [jmc$empty]],
        [2, ['Next_Item', 'NI', * , jmc$number, 0, 0], [jmc$empty]],
        [3, ['Categories', 'C', * , jmc$list, 1, * ], [jmc$empty]],
          [1, ['--', '--', * , jmc$object, jmc$profile_category], [jmc$empty]],
        [4, ['Type', 'T', * , jmc$name], [jmc$empty]],
        [5, ['Members', 'M', * , jmc$list, 1, * ], [jmc$empty]],
          [1, ['--', '--', * , jmc$object, jmc$profile_category], [jmc$empty]],

{ CATEGORY_SET_DISPLAY           = list of record
{    NAME                        = name
{    MEMBERS                     = list of jmc$profile_category

    [jmc$c_set_display, ['Category_Set_Display', 'CSD', jmc$statistic_group,
          jmc$list, 1, * ], [jmc$empty]],
      [1, ['--', '--', * , jmc$type, 2, * ], [jmc$empty]],
        [1, ['Name', 'N', * , jmc$name], [jmc$empty]],
        [2, ['Members', 'M', * , jmc$list, 1, * ], [jmc$empty]],
          [1, ['--', '--', * , jmc$object, jmc$profile_category],
            [jmc$empty]]];

?? FMT (FORMAT := ON) ??

  VAR
    category_default: array [1 .. 2] of attribute_preset :=
          [[jmc$c_job_mode, [jmc$list, * ]], [1, [jmc$name, * ]]];

?? TITLE := 'Job Priority Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    priority_descriptor_count = 6;

  VAR
    priority_structure: array [1 .. priority_descriptor_count] of
        attribute_structure := [

  [1, ['JOB_PRIORITY', 'JP', * , jmc$type, jmc$jp_maximum_attribute, * ],
          [jmc$type, * ]],

{ INITIATION_BIAS                = integer

    [jmc$jp_initiation_bias, ['Initiation_Bias', 'IB', jmc$priority_group,
          jmc$number, -jmc$highest_job_priority, jmc$highest_job_priority],
          [jmc$number, 0]],

{ SCHEDULING_BIAS                = integer

    [jmc$jp_scheduling_bias, ['Scheduling_Bias', 'SB', jmc$priority_group,
          jmc$number, -jmc$highest_job_priority, jmc$highest_job_priority],
          [jmc$number, 0]],

{ DISPATCHING_BIAS               = integer

    [jmc$jp_dispatching_bias, ['Dispatching_Bias', 'DB', jmc$priority_group,
          jmc$number, -10000000, 10000000], [jmc$number, 0]],

{ TIMESLICE_BIAS                 = integer

    [jmc$jp_timeslice_bias, ['Timeslice_Bias', 'TB', jmc$priority_group,
          jmc$number, -10000000, 10000000], [jmc$number, 0]],

{ OUTPUT_BIAS                    = integer

    [jmc$jp_output_bias, ['Output_Bias', 'OB', jmc$priority_group, jmc$number,
          -jmc$highest_job_priority, jmc$highest_job_priority],
          [jmc$number, 0]]];

?? FMT (FORMAT := ON) ??
?? TITLE := 'Scheduler Control Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    controls_descriptor_count = 35;

  VAR
    controls_structure: array [1 .. controls_descriptor_count] of
        attribute_structure := [

  [1, ['CONTROLS', 'C', * , jmc$type, jmc$ct_maximum_attribute, * ],
          [jmc$type, * ]],

{ ABBREVIATION                   = name

    [jmc$ct_abbreviation, ['Abbreviation', 'A', jmc$definition_group,
          jmc$name], [jmc$none]],

{ CPU_QUANTUM_TIME   = integer

    [jmc$ct_cpu_quantum_time, ['CPU_Quantum_Time', 'CQT',
          jmc$definition_group, jmc$number, 1000,
          100000], [jmc$number, 10000]],

{ ENABLE_JOB_LEVELING            = boolean

    [jmc$ct_enable_job_leveling, ['Enable_Job_Leveling', 'EJL',
          jmc$definition_group, jmc$boolean], [jmc$boolean, FALSE]],

{ JOB_LEVELING_INTERVAL          = integer

    [jmc$ct_job_leveling_interval, ['Job_Leveling_Interval', 'JLI',
          jmc$definition_group, jmc$number, jmc$lowest_service_interval,
          jmc$highest_service_interval], [jmc$number, 60]],

{ JOB_LEVELING_PRIORITY_BIAS     = integer

    [jmc$ct_job_leveling_prio_bias, ['Job_Leveling_Priority_Bias', 'JLPB',
          jmc$priority_group, jmc$number, jmc$lowest_priority_bias,
          jmc$highest_priority_bias], [jmc$number, 0]],

{ SERVICE_CALCULATION_INTERVAL   = integer

    [jmc$ct_service_calc_interval, ['Service_Calculation_Interval', 'SCI',
          jmc$definition_group, jmc$number, jmc$lowest_service_interval,
          jmc$highest_service_interval], [jmc$number, 10]],

{ STATISTICS_RESET_INTERVAL      = integer

{   [jmc$ct_stat_reset_interval, ['Statistics_Reset_Interval', 'SRI',
{         jmc$control_group, jmc$number, 1800, 36000], [jmc$number, 100]],

{ CPU_DISPATCHING_ALLOCATION     = list of
{   PRIORITY_INFORMATION
{    PRIORITY                        = dispatching priority 1..8
{    MINIMUM_PERCENT                 = integer 0..100
{    MAXIMUM_PERCENT                 = integer 0..100
{    ENFORCE_MAXIMUM                 = boolean

    [jmc$ct_dispatching_allocation, ['CPU_Dispatching_Allocation', 'CDA',
          jmc$control_group, jmc$editable_list, 1, * ],
          [jmc$editable_list, * ]],
      [1, ['Priority_Triplet', 'PT', *, jmc$type, 4, * ], [jmc$type, * ]],
        [1, ['Priority', 'P', * , jmc$range, 2, *], [jmc$range, *]],
          [1, ['Priority', 'P', * , jmc$dispatching_priority, 1, 8],
              [jmc$dispatching_priority, 1]],
          [2, ['Priority', 'P', * , jmc$dispatching_priority, 1, 8],
              [jmc$dispatching_priority, 8]],
        [2, ['Minimum_Percent', 'MINA', * , jmc$number, 0, 100],
            [jmc$number, 0]],
        [3, ['Maximum_Percent', 'MAXA', * , jmc$number, 0, 100],
            [jmc$number, 100]],
        [4, ['Enforce_Maximum', 'EM', * , jmc$boolean],
            [jmc$boolean, FALSE]],

{ CPU_DISPATCHING_INTERVAL       = integer

    [jmc$ct_cpu_dispatching_interval, ['CPU_Dispatching_Interval', 'CDI',
          jmc$control_group, jmc$number, 1, 600], [jmc$number, 1]],

{ DUAL_STATE_PRIORITY_CONTROL    = editable list
{   PRIORITY_CONTROL               = type
{     PRIORITY                       = dispatching priority 1..10
{     MAINFRAME_PRIORITY             = integer 0..7
{     SUBPRIORITY                    = integer 1..15

    [jmc$ct_dual_state_prio_control, ['Dual_State_Priority_Control', 'DSPC',
          jmc$control_group, jmc$editable_list, 1, * ],
          [jmc$empty]],
      [1, ['Priority_Control', 'PT', *, jmc$type, 3, * ], [jmc$empty]],
        [1, ['Dispatching_Priority', 'DP', * , jmc$range, 1, *],
            [jmc$range, *]],
          [1, ['Priority', 'P', * , jmc$dispatching_priority, 1, 10],
              [jmc$dispatching_priority, 1]],
        [2, ['Dual_State_Priority', 'DSP', * , jmc$number, 1, 7],
            [jmc$number, 1]],
        [3, ['Subpriority', 'S', * , jmc$number, 1, 15],
            [jmc$number, 8]],

{ IDLE_DISPATCHING_QUEUE_TIME    = integer

    [jmc$ct_idle_disp_queue_time, ['Idle_Dispatching_Queue_Time', 'IDQT',
          jmc$control_group, jmc$number, lowest_idle_disp_q_time,
          highest_idle_disp_q_time], [jmc$number, 360]],

{ SCHEDULING_MEMORY_LEVELS       = record
{    TARGET                          = integer
{    THRASHING                       = integer

    [jmc$ct_scheduling_memory_levels, ['Scheduling_Memory_Levels', 'SML',
          jmc$control_group, jmc$type, 2, * ], [jmc$type, * ]],
      [1, ['Target', 'TA', * , jmc$number, jmc$lowest_sched_memory_level,
          jmc$highest_sched_memory_level], [jmc$number, 60]],
      [2, ['Thrashing', 'TH', * , jmc$number, jmc$lowest_sched_memory_level,
          jmc$highest_sched_memory_level], [jmc$number, 20]],

{ MAXIMUM_INITIATED_JOBS         = integer

{   [jmc$ct_maximum_initiated_jobs, ['Maximum_Initiated_Jobs', 'MAXIJ',
{         jmc$control_group, jmc$number, 0, 1000], [jmc$number, 100]],

{ INITIATION_REQUIRED_CATEGORIES = list of jmc$profile_category

    [jmc$ct_ini_required_categories, ['Initiation_Required_Categories', 'IRC',
          jmc$control_group, jmc$list, 1, * ], [jmc$none]],
      [1, ['Initiation_Required_Categories', '--', * , jmc$object,
            jmc$profile_category], [jmc$empty]],

{ INITIATION_EXCLUDED_CATEGORIES = list of jmc$profile_category

    [jmc$ct_ini_excluded_categories, ['Initiation_Excluded_Categories', 'IEC',
          jmc$control_group, jmc$list, 1, * ], [jmc$none]],
      [1, ['Initiation_Excluded_Categories', '--', * , jmc$object,
            jmc$profile_category], [jmc$empty]],

{ VALIDATION_REQUIRED_CATEGORIES = list of jmc$profile_category

    [jmc$ct_val_required_categories, ['Validation_Required_Categories', 'VRC',
          jmc$membership_group, jmc$list, 1, * ], [jmc$none]],
      [1, ['Validation_Required_Categories', '--', * , jmc$object,
            jmc$profile_category], [jmc$empty]],

{ VALIDATION_EXCLUDED_CATEGORIES = list of jmc$profile_category

    [jmc$ct_val_excluded_categories, ['Validation_Excluded_Categories', 'VEC',
          jmc$membership_group, jmc$list, 1, * ], [jmc$none]],
      [1, ['Validation_Excluded_Categories', '--', * , jmc$object,
            jmc$profile_category], [jmc$empty]],

{ PROFILE_IDENTIFICATION         = name - for debugging purposes

    [jmc$ct_profile_identification, ['Profile_Identification', 'PI',
          jmc$statistic_group, jmc$name], [jmc$empty]]];

?? FMT (FORMAT := ON) ??
?? FMT (FORMAT := OFF) ??

{ Controls defaults
{   Dual_State_Priority_Control = ((p1..p2 1 8) (p3..p4 2 8)
{         (p5..p6 3 8) (p7..p8 4 8) (p9..p10 5 8))

  VAR
    ds_priority_control_default: array [1 .. 30] of attribute_preset := [
        [5, [jmc$type, * ]],
          [1, [jmc$range, *]],
            [2, [jmc$dispatching_priority, 10]],
            [1, [jmc$dispatching_priority, 9]],
          [2, [jmc$number, 5]],
          [3, [jmc$number, 8]],
        [1, [jmc$type, * ]],
          [1, [jmc$range, *]],
            [2, [jmc$dispatching_priority, 2]],
            [1, [jmc$dispatching_priority, 1]],
          [2, [jmc$number, 1]],
          [3, [jmc$number, 8]],
        [2, [jmc$type, * ]],
          [1, [jmc$range, *]],
            [2, [jmc$dispatching_priority, 4]],
            [1, [jmc$dispatching_priority, 3]],
          [2, [jmc$number, 2]],
          [3, [jmc$number, 8]],
        [3, [jmc$type, * ]],
          [1, [jmc$range, *]],
            [2, [jmc$dispatching_priority, 6]],
            [1, [jmc$dispatching_priority, 5]],
          [2, [jmc$number, 3]],
          [3, [jmc$number, 8]],
        [4, [jmc$type, * ]],
          [1, [jmc$range, *]],
            [2, [jmc$dispatching_priority, 8]],
            [1, [jmc$dispatching_priority, 7]],
          [2, [jmc$number, 4]],
          [3, [jmc$number, 8]]];
?? FMT (FORMAT := ON) ??
?? TITLE := 'Job Class Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    job_class_descriptor_count = 52;

  VAR
    job_class_structure: array [1 .. job_class_descriptor_count] of
        attribute_structure := [

  [1, ['JOB_CLASS', 'JCL', * , jmc$type, jmc$jc_maximum_attribute, * ],
          [jmc$type, * ]],

{ ABBREVIATION                   = name

    [jmc$jc_abbreviation, ['Abbreviation', 'A', jmc$definition_group,
          jmc$name], [jmc$none]],

{ PROLOG                         = name

    [jmc$jc_prolog, ['Prolog', 'P', jmc$definition_group, jmc$file],
          [jmc$none]],

{ EPILOG                         = name

    [jmc$jc_epilog, ['Epilog', 'E', jmc$definition_group, jmc$file],
          [jmc$none]],

{ ENABLE_CLASS_MEMBERSHIP        = boolean

{   [jmc$jc_enable_class_membership, ['Enable_Class_Membership', 'ECM',
{         jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{ ENABLE_CLASS_EXECUTION         = boolean

{   [jmc$jc_enable_class_execution, ['Enable_Class_Execution', 'ECE',
{         jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{ ENABLE_CLASS_INITIATION        = boolean

    [jmc$jc_enable_class_initiation, ['Enable_Class_Initiation', 'ECI',
          jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{ ENABLE_IMMEDIATE_AGING         = boolean

{   [jmc$jc_enable_immediate_aging, ['Enable_Immediate_Aging', 'EIA',
{         jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{ IMMEDIATE_INITIATION_CANDIDATES= boolean

    [jmc$jc_immediate_initiation_can, ['Immediate_Initiation_Candidate', 'IIC',
          jmc$definition_group, jmc$boolean], [jmc$boolean, FALSE]],

{ ENABLE_LATCH_MODE              = boolean

{   [jmc$jc_enable_latch_mode, ['Enable_Latch_Mode', 'ELM',
{         jmc$definition_group, jmc$boolean], [jmc$boolean, FALSE]],

{ INITIAL_WORKING_SET            = integer

    [jmc$jc_initial_working_set, ['Initial_Working_Set', 'IWS',
          jmc$definition_group, jmc$number, jmc$lowest_working_set_size,
          jmc$highest_working_set_size], [jmc$number, 65]],

{ INITIAL_SERVICE_CLASS          = jmc$profile_service_class

    [jmc$jc_initial_service_class, ['Initial_Service_Class', 'ISC',
          jmc$definition_group, jmc$object, jmc$profile_service_class],
          [jmc$object, * , * ]],

{ VALID_SERVICE_CLASSES          = list of jmc$profile_service_class

{   [jmc$jc_valid_service_classes, ['Valid_Service_Classes', 'VSC',
{         jmc$definition_group, jmc$empty], [jmc$none]],

{ DEFAULT_OUTPUT_CLASS           = jmc$profile_output_class

{   [jmc$jc_default_output_class, ['Default_Output_Class', 'DOC',
{         jmc$definition_group, jmc$empty], [jmc$system_default]],

{ VALID_OUTPUT_CLASSES           = list of jmc$profile_output_class

{   [jmc$jc_valid_output_classes, ['Valid_Output_Classes', 'VOC',
{         jmc$definition_group, jmc$empty], [jmc$none]],

{ DEFER_ON_SUBMIT                = boolean

    [jmc$jc_defer_on_submit, ['Defer_On_Submit', 'DOS',
          jmc$control_group, jmc$boolean], [jmc$boolean, FALSE]],

{ INITIATION_LEVEL               = record
{    PREFERRED                       = integer
{ *  MAXIMUM_INCREMENT               = integer

    [jmc$jc_initiation_level, ['Initiation_Level', 'IL', jmc$control_group,
          jmc$type, 1, * ], [jmc$type, * ]],
      [1, ['Preferred', 'P', * , jmc$number, jmc$lowest_max_initiated_jobs,
          jmc$highest_max_initiated_jobs], [jmc$number, 20]],
{     [2, ['Maximum_Increment', 'MAXI', * , jmc$number,
{         jmc$lowest_max_initiated_jobs, jmc$highest_max_initiated_jobs],
{         [jmc$number, 0]],

{ USE_INITIATION_GROUP           = jmc$profile_job_group

{   [jmc$jc_use_initiation_group, ['Use_Initiation_Group', 'UIG',
{         jmc$control_group, jmc$empty], [jmc$none]],

{ OVER_COMMITMENT_CRITERIA       = record
{    WAIT_TIME                       = integer
{    WAIT_COUNT                      = integer
{    MAXIMUM                         = integer

{   [jmc$jc_over_commitment_criteria, ['Over_Commitment_Criteria', 'OCC',
{         jmc$control_group, jmc$type, 3, * ], [jmc$empty]],
{     [1, ['Wait_Time', 'WT', *, jmc$number, jmc$lowest_lsi, jmc$highest_lsi],
{           [jmc$number, 600]],
{     [2, ['Wait_Count', 'WC', *, jmc$number, 1, 100], [jmc$number, 3]],
{     [3, ['Maximum', 'MAX', *, jmc$number, 0, 100], [jmc$number, 0]],

{ MINIMUM_WORKING_SET            = record
{    DEFAULT                         = integer
{    Minimum                         = integer
{    Maximum                         = integer

    [jmc$jc_minimum_working_set, ['Minimum_Working_Set', 'MINWS',
          jmc$control_group, jmc$type, 3, * ], [jmc$type, * ]],
      [1, ['Default', 'D', * , jmc$number, jmc$lowest_working_set_size,
            jmc$highest_working_set_size], [jmc$number, 20]],
      [2, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_working_set_size,
            jmc$highest_working_set_size], [jmc$number, 20]],
      [3, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_working_set_size,
            jmc$highest_working_set_size], [jmc$number, 1000]],

{ Maximum_Working_Set            = integer
{    Default                         = integer
{    Minimum                         = integer
{    Maximum                         = integer

    [jmc$jc_maximum_working_set, ['Maximum_Working_Set', 'MAXWS',
          jmc$control_group, jmc$type, 3, * ], [jmc$type, * ]],
      [1, ['Default', 'D', * , jmc$number, jmc$lowest_working_set_size,
            jmc$highest_working_set_size], [jmc$number, 1000]],
      [2, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_working_set_size,
            jmc$highest_working_set_size], [jmc$number, 20]],
      [3, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_working_set_size,
            jmc$highest_working_set_size], [jmc$number, 1000]],

{ PAGE_AGING_INTERVAL            = record
{    Default                         = integer
{    Minimum                         = integer
{    Maximum                         = integer

    [jmc$jc_page_aging_interval, ['Page_Aging_Interval', 'PAI',
          jmc$control_group, jmc$type, 3, * ], [jmc$type, * ]],
      [1, ['Default', 'D', * , jmc$number, jmc$lowest_aging_interval,
            jmc$highest_aging_interval], [jmc$number, 50000]],
      [2, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_aging_interval,
            jmc$highest_aging_interval], [jmc$number, 10000]],
      [3, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_aging_interval,
            jmc$highest_aging_interval], [jmc$number, 1000000000]],

{ CYCLIC_AGING_INTERVAL          = record
{    Default                         = integer
{    Minimum                         = integer
{    Maximum                         = integer

    [jmc$jc_cyclic_aging_interval, ['Cyclic_Aging_Interval', 'CAI',
          jmc$control_group, jmc$type, 3, * ], [jmc$type, * ]],
      [1, ['Default', 'D', * , jmc$number, jmc$lowest_aging_interval,
          jmc$highest_aging_interval], [jmc$number, 1000000000]],
      [2, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_aging_interval,
          jmc$highest_aging_interval], [jmc$number, 10000]],
      [3, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_aging_interval,
          jmc$highest_aging_interval], [jmc$number, 1000000000]],

{ CLASS_CAPABILITIES             = list of name

{   [jmc$jc_class_capabilities, ['Class_Capabilities', 'CC', jmc$control_group,
{         jmc$empty], [jmc$none]],

{ DETACHED_JOB_WAIT_TIME         = record
{    DEFAULT                         = integer
{    MINIMUM                         = integer
{    MAXIMUM                         = integer

    [jmc$jc_detached_job_wait_time, ['Detached_Job_Wait_Time', 'DJWT',
          jmc$limit_group, jmc$type, 3, * ], [jmc$type, * ]],
      [1, ['Default', 'D', * , jmc$number, jmc$lowest_det_job_wait_time,
          jmc$highest_det_job_wait_time], [jmc$number, 3600]],
      [2, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_det_job_wait_time,
          jmc$highest_det_job_wait_time], [jmc$number, 0]],
      [3, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_det_job_wait_time,
          jmc$highest_det_job_wait_time], [jmc$number, 18000]],

{ CPU_TIME_LIMIT                 = integer

    [jmc$jc_cpu_time_limit, ['CPU_Time_Limit', 'CTL', jmc$limit_group,
          jmc$number, jmc$lowest_cpu_time_limit, jmc$highest_cpu_time_limit],
          [jmc$unlimited]],

{ SRU_LIMIT                      = integer

    [jmc$jc_sru_limit, ['SRU_Limit', 'SL', jmc$limit_group, jmc$number,
          jmc$lowest_sru_limit, jmc$highest_sru_limit], [jmc$unlimited]],

{ MAGNETIC_TAPE_LIMIT            = integer

    [jmc$jc_magnetic_tape_limit, ['Magnetic_Tape_Limit', 'MTL', jmc$limit_group
,
          jmc$number, jmc$lowest_magnetic_tape_limit,
          jmc$highest_magnetic_tape_limit], [jmc$unlimited]],

{ AUTOMATIC_CLASS_SELECTION      = boolean

    [jmc$jc_auto_class_selection, ['Automatic_Class_Selection', 'ACS',
          jmc$membership_group, jmc$boolean], [jmc$boolean, FALSE]],

{ REQUIRED_CATEGORIES            = list of jmc$profile_category

    [jmc$jc_required_categories, ['Required_Categories', 'RC',
          jmc$membership_group, jmc$list, 1, * ], [jmc$none]],
      [1, ['Required_Categories', '--', * , jmc$object, jmc$profile_category],
            [jmc$empty]],

{ EXCLUDED_CATEGORIES            = list of jmc$profile_category

    [jmc$jc_excluded_categories, ['Excluded_Categories', 'EC',
          jmc$membership_group, jmc$list, 1, * ], [jmc$none]],
      [1, ['Excluded_Categories', '--', * , jmc$object, jmc$profile_category],
            [jmc$empty]],

{ MULTIPLE_JOB_BIAS              = integer
    [jmc$jc_multiple_job_bias, ['Multiple_Job_Bias', 'MJB',
          jmc$priority_group, jmc$number, jmc$lowest_job_priority,
          jmc$highest_job_priority], [jmc$number, 0]],

{ INITIATION_AGE_INTERVAL        = integer

    [jmc$jc_initiation_age_interval, ['Initiation_Age_Interval', 'IAI',
          jmc$priority_group, jmc$number, lowest_prio_age_interval,
          highest_prio_age_interval], [jmc$number, 1]],

{ SELECTION_PRIORITY             = record
{    INITIAL                         = integer
{    MAXIMUM                         = integer
{    INCREMENT                       = integer
{    THRESHOLD                       = integer

    [jmc$jc_selection_priority, ['Selection_Priority', 'SP',
          jmc$priority_group, jmc$type, 4, * ], [jmc$type, * ]],
      [1, ['Initial', 'I', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 5000]],
      [2, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 10000]],
      [3, ['Increment', 'I', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 10]],
      [4, ['Threshold', 'T', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 0]],

{ CLASS_PRIORITY_BIAS            = record
{    SCHEDULING                      = integer
{    DISPATCHING                     = integer
{    TIMESLICE                       = integer
{ *  OUTPUT                          = integer

{   [jmc$jc_class_priority_bias, ['Class_Priority_Bias', 'CPB',
{         jmc$priority_group, jmc$type, 3, * ], [jmc$none]],
{     [1, ['Scheduling', 'S', *, jmc$number, -8000000, 8000000],
{           [jmc$number, 0]],
{     [2, ['Dispatching', 'D', *, jmc$number, -9, 9], [jmc$number, 0]],
{     [3, ['Timeslice', 'T', *, jmc$number, -1000000, 1000000],
{           [jmc$number, 0]],
{     [3, ['Output', 'O', *, jmc$number, -8000000, 8000000], [jmc$number, 0]],

{ JOB_LEVELING_PRIORITY_BIAS     = integer

    [jmc$jc_job_leveling_prio_bias, ['Job_Leveling_Priority_Bias', 'JLPB',
          jmc$priority_group, jmc$number, jmc$lowest_priority_bias,
          jmc$highest_priority_bias], [jmc$number, 0]],

{ QUEUED_JOBS                    = integer (display only)

    [jmc$jc_queued_jobs, ['Queued_Jobs', 'QJ', jmc$statistic_group, jmc$number,
          0, 0], [jmc$empty]],

{ INITIATED_JOBS                 = integer (display only)

    [jmc$jc_initiated_jobs, ['Initiated_Jobs', 'IJ', jmc$statistic_group,
          jmc$number, 0, 0], [jmc$empty]],

{ INITIATION_WAIT_TIME           = record (display only)
{    MINIMUM                         = integer
{    MAXIMUM                         = integer
{    AVERAGE                         = integer
{    NUMBER_OF_JOBS                  = integer

{   [jmc$jc_initiation_wait_time, ['Initiation_Wait_Time', 'IWT',
{         jmc$statistic_group, jmc$type, 4, * ], [jmc$empty]],
{     [1, ['Minimum', 'MIN', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [2, ['Maximum', 'MAX', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [3, ['Average', 'A', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [4, ['Number_Of_Jobs', 'NOJ', *, jmc$number, 0, 0], [jmc$number, 0]],

{ PROCESSING_WAIT_TIME           = record (display only)
{    MINIMUM                         = integer
{    MAXIMUM                         = integer
{    AVERAGE                         = integer
{    NUMBER_OF_JOBS                  = integer

{   [jmc$jc_processing_wait_time, ['Processing_Wait_Time', 'PWT',
{         jmc$statistic_group, jmc$type, 4, * ], [jmc$empty]],
{     [1, ['Minimum', 'MIN', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [2, ['Maximum', 'MAX', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [3, ['Average', 'A', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [4, ['Number_Of_Jobs', 'NOJ', *, jmc$number, 0, 0], [jmc$number, 0]],

{ DEFINITION_NAME                = name (for debug display only)

    [jmc$jc_definition_name, ['Definition_Name', 'DN', jmc$statistic_group,
          jmc$name], [jmc$empty]],

{ PROFILE_INDEX                  = integer (for debug display only)

    [jmc$jc_profile_index, ['Profile_Index', 'PI', jmc$statistic_group,
          jmc$number, 0, 0], [jmc$empty]],

{ JOB_CLASS_INDEX                = integer (for debug display only)

    [jmc$jc_index, ['Job_Class_Index', 'JCI', jmc$statistic_group, jmc$number,
          0, 0], [jmc$empty]]];

?? FMT (FORMAT := ON) ??

  VAR
    job_class_defaults: array [job_and_service_classes] of
          ^attribute_preset_list := [^job_class_interactive, ^job_class_batch,
          ^job_class_system, ^job_class_maintenance, ^job_class_unassigned];

?? FMT (FORMAT := OFF) ??

  VAR
    job_class_interactive: array [1 .. 11] of attribute_preset := [
      [jmc$jc_excluded_categories, [jmc$list, * ]],
        [1, [jmc$object, * , * ]],
      [jmc$jc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$jc_immediate_initiation_can, [jmc$boolean, TRUE]],
      [jmc$jc_selection_priority, [jmc$type, * ]],
        [1, [jmc$number, 14000]],
        [2, [jmc$number, 17000]],
        [3, [jmc$number, 1000]],
        [4, [jmc$number, 0]],
      [jmc$jc_initiation_level, [jmc$type, * ]],
        [1, [jmc$unlimited]]];

  VAR
    job_class_batch: array [1 .. 7] of attribute_preset :=
     [[jmc$jc_excluded_categories, [jmc$list, * ]],
        [1, [jmc$object, * , * ]],
      [jmc$jc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$jc_initial_working_set, [jmc$number, 200]],
      [jmc$jc_initiation_age_interval, [jmc$number, 60]],
      [jmc$jc_initiation_level, [jmc$type, * ]],
        [1, [jmc$number, 10]]];

  VAR
    job_class_system: array [1 .. 11] of attribute_preset :=
     [[jmc$jc_excluded_categories, [jmc$list, * ]],
        [1, [jmc$object, * , * ]],
      [jmc$jc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$jc_initial_working_set, [jmc$number, 80]],
      [jmc$jc_selection_priority, [jmc$type, * ]],
        [1, [jmc$number, 19000]],
        [2, [jmc$number, 22000]],
        [3, [jmc$number, 100]],
        [4, [jmc$number, 0]],
      [jmc$jc_initiation_level, [jmc$type, * ]],
        [1, [jmc$unlimited]]];

  VAR
    job_class_maintenance: array [1 .. 10] of attribute_preset :=
     [[jmc$jc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$jc_immediate_initiation_can, [jmc$boolean, TRUE]],
      [jmc$jc_initiation_age_interval, [jmc$number, 60]],
      [jmc$jc_selection_priority, [jmc$type, * ]],
        [1, [jmc$number, 14000]],
        [2, [jmc$number, 17000]],
        [3, [jmc$number, 1000]],
        [4, [jmc$number, 0]],
      [jmc$jc_initiation_level, [jmc$type, * ]],
        [1, [jmc$number, 10]]];

  VAR
    job_class_unassigned: array [1 .. 7] of attribute_preset :=
     [[jmc$jc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$jc_enable_class_initiation, [jmc$boolean, FALSE]],
      [jmc$jc_initial_working_set, [jmc$number, 200]],
      [jmc$jc_initiation_age_interval, [jmc$number, 60]],
      [jmc$jc_initiation_level, [jmc$type, * ]],
        [1, [jmc$number, 10]],
        [2, [jmc$default]]];

?? FMT (FORMAT := ON) ??
?? TITLE := 'Service Class Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    service_class_descriptor_count = 33;

  VAR
    service_class_structure: array [1 .. service_class_descriptor_count] of
        attribute_structure := [

  [1, ['SERVICE_CLASS', 'SC', * , jmc$type, jmc$sc_maximum_attribute, * ],
          [jmc$type, * ]],

{   ABBREVIATION                 = name

    [jmc$sc_abbreviation, ['Abbreviation', 'A', jmc$definition_group,
          jmc$name], [jmc$none]],

{   ENABLE_CLASS_EXECUTION       = boolean

    [jmc$sc_enable_class_execution, ['Enable_Class_Execution', 'ECE',
          jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{   MAXIMUM_ACTIVE_JOBS          = integer

    [jmc$sc_maximum_active_jobs, ['Maximum_Active_Jobs', 'MAXAJ',
          jmc$control_group, jmc$number, jmc$lowest_maximum_active_jobs,
          jmc$highest_maximum_active_jobs], [jmc$number, 20]],

{   SERVICE_FACTORS              = record
{    CPU                             = integer
{    MEMORY                          = integer
{    RESIDENCE                       = integer
{    IO                              = integer

    [jmc$sc_service_factors, ['Service_Factors', 'SF', jmc$control_group,
          jmc$type, 4, * ], [jmc$type, * ]],
      [1, ['CPU', 'C', * , jmc$number, jmc$lowest_service_factor_value,
            jmc$highest_service_factor_valu], [jmc$number, 1]],
      [2, ['Memory', 'M', * , jmc$number, jmc$lowest_service_factor_value,
            jmc$highest_service_factor_valu], [jmc$number, 1]],
      [3, ['Residence', 'R', * , jmc$number, jmc$lowest_service_factor_value,
            jmc$highest_service_factor_valu], [jmc$number, 1]],
      [4, ['IO', 'IO', *, jmc$number, jmc$lowest_service_factor_value,
            jmc$highest_service_factor_valu], [jmc$number, 1]],

{   DISPATCHING_CONTROL          = list of record
{    DISPATCHING_PRIORITY            = integer
{    SERVICE_TIME                    = integer
{    MINOR_TIMESLICE                 = integer
{    MAJOR_TIMESLICE                 = integer

    [jmc$sc_dispatching_control, ['Dispatching_Control', 'DC',
          jmc$priority_group, jmc$list, 1, * ], [jmc$list, * ]],
      [1, ['Dispatching_Control', '--', jmc$control_group, jmc$type, 4, * ],
          [jmc$type, * ]],
        [1, ['Dispatching_Priority', 'DP', * , jmc$dispatching_priority,
            1, 10], [jmc$dispatching_priority, 5]],
        [2, ['Service_Time', 'ST', * , jmc$number,
            jmc$lowest_service_limit DIV 1000, jmc$highest_service_limit DIV
            1000], [jmc$unlimited]],
        [3, ['Minor_Timeslice', 'MINT', * , jmc$number,
            jmc$lowest_task_time_slice, jmc$highest_task_time_slice],
            [jmc$number, 1]],
        [4, ['Major_Timeslice', 'MAJT', * , jmc$number,
            jmc$lowest_task_time_slice, jmc$highest_task_time_slice],
            [jmc$number, 1]],

{   GUARANTEED_SERVICE_QUANTUM   = integer

    [jmc$sc_guaranteed_service_quan, ['Guaranteed_Service_Quantum', 'GSQ',
          jmc$control_group, jmc$number, jmc$lowest_service_accumulator,
          jmc$highest_service_accumulator], [jmc$number, 100]],

{   CLASS_SERVICE_THRESHOLD      = integer

    [jmc$sc_class_resource_threshold, ['Class_Service_Threshold', 'CST',
          jmc$control_group, jmc$number, jmc$lowest_service_accumulator,
          jmc$highest_service_accumulator], [jmc$unlimited]],

{   NEXT_SERVICE_CLASS           = jmc$profile_service_class

    [jmc$sc_next_service_class, ['Next_Service_Class', 'NSC',
          jmc$control_group, jmc$object, jmc$profile_service_class],
          [jmc$none]],

{   LONG_WAIT_THINK_TIME         = integer

    [jmc$sc_long_wait_think_time, ['Long_Wait_Think_Time', 'LWTT',
          jmc$control_group, jmc$number, jmc$low_long_wait_think_time,
          jmc$high_long_wait_think_time], [jmc$number, 0]],

{   AIO_LIMIT                    = integer

    [jmc$sc_aio_limit, ['AIO_Limit', 'AIOL', jmc$control_group, jmc$number,
          jmc$lowest_aio_limit, jmc$highest_aio_limit], [jmc$number, 60000]],

{   ATTEMPT_PREEMPTION           = boolean

    [jmc$sc_attempt_preemption, ['Attempt_Preemption', 'AP', jmc$control_group, jmc$boolean],
          [jmc$boolean, TRUE]],

{   SWAP_JOBS_IN_LONGWAIT

    [jmc$sc_swap_jobs_in_longwait, ['Swap_Jobs_In_Longwait', 'SJIL', jmc$control_group, jmc$boolean],
          [jmc$boolean, TRUE]],

{   SWAP_AGE_INTERVAL            = integer

    [jmc$sc_swap_age_interval, ['Swap_Age_Interval', 'SAI', jmc$priority_group,
          jmc$number, lowest_prio_age_interval, highest_prio_age_interval],
          [jmc$number, 1]],

{   SCHEDULING_PRIORITY          = record
{    MINIMUM                         = integer
{    MAXIMUM                         = integer
{    SWAP_AGE_INCREMENT              = integer
{    READY_TASK_INCREMENT            = integer

    [jmc$sc_scheduling_priority, ['Scheduling_Priority', 'SP',
          jmc$priority_group, jmc$type, 4, * ], [jmc$type, * ]],
      [1, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 1000]],
      [2, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 10000]],
      [3, ['Swap_Age_Increment', 'SAI', * , jmc$number,
            jmc$lowest_job_priority, jmc$highest_job_priority],
            [jmc$number, 1000]],
      [4, ['Ready_Task_Increment', 'RTI', * , jmc$number,
            jmc$lowest_job_priority, jmc$highest_job_priority],
            [jmc$number, 0]],

{   ACTIVE_JOBS                  = integer (display only)

    [jmc$sc_active_jobs, ['Active_Jobs', 'AJ', jmc$statistic_group, jmc$number,
          0, 0], [jmc$empty]],

{   QUEUED_JOBS                  = integer (display only)

    [jmc$sc_queued_jobs, ['Queued_Jobs', 'QJ', jmc$statistic_group, jmc$number,
          0, 0], [jmc$empty]],

{   SWAPPED_JOBS                 = integer (display only)

    [jmc$sc_swapped_jobs, ['Swapped_Jobs', 'SJ', jmc$statistic_group,
          jmc$number, 0, 0], [jmc$empty]],

{   SERVICE_ACHIEVED_PERCENT     = integer (display only)

{   [jmc$sc_service_achieved_percent, ['Service_Achieved_Percent', 'SAP',
{         jmc$statistic_group, jmc$number, 0, 0], [jmc$empty]]];

{ DEFINITION_NAME                = name (for debug display only)

    [jmc$sc_definition_name, ['Definition_Name', 'DN', jmc$statistic_group,
          jmc$name], [jmc$empty]],

{ SERVICE_CLASS_INDEX            = integer (for debug display only)

    [jmc$sc_index, ['Service_Class_Index', 'SCI', jmc$statistic_group,
          jmc$number, 0, 0], [jmc$empty]]];

?? FMT (FORMAT := ON) ??

  VAR
    service_class_defaults: array [job_and_service_classes] of
          ^attribute_preset_list := [^service_class_interactive,
          ^service_class_batch, ^service_class_system,
          ^service_class_maintenance, ^service_class_unassigned];

?? FMT (FORMAT := OFF) ??

  VAR
    service_class_interactive: array [1 .. 8] of attribute_preset :=
     [[jmc$sc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$sc_maximum_active_jobs, [jmc$number, 100]],
      [jmc$sc_guaranteed_service_quan, [jmc$number, 9000]],
      [jmc$sc_scheduling_priority, [jmc$type, * ]],
        [1, [jmc$number, 8000]],
        [2, [jmc$number, 17000]],
        [3, [jmc$number, 1000]],
        [4, [jmc$number, 1000]]];

  VAR
    service_class_batch: array [1 .. 4] of attribute_preset :=
     [[jmc$sc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$sc_attempt_preemption, [jmc$boolean, FALSE]],
      [jmc$sc_maximum_active_jobs, [jmc$number, 50]],
      [jmc$sc_guaranteed_service_quan, [jmc$number, 20000]]];

  VAR
    service_class_system: array [1 .. 13] of attribute_preset :=
     [[jmc$sc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$sc_guaranteed_service_quan, [jmc$number, 2000]],
      [jmc$sc_scheduling_priority, [jmc$type, * ]],
        [1, [jmc$number, 19000]],
        [2, [jmc$number, 22000]],
        [3, [jmc$number, 1000]],
        [4, [jmc$number, 0]],
      [jmc$sc_dispatching_control, [jmc$list, * ]],
        [1, [jmc$type, * ]],
          [1, [jmc$dispatching_priority, 6]],
          [2, [jmc$unlimited]],
          [3, [jmc$number, 1]],
          [4, [jmc$number, 1]]];

  VAR
    service_class_maintenance: array [1 .. 15] of attribute_preset :=
     [[jmc$sc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$sc_attempt_preemption, [jmc$boolean, FALSE]],
      [jmc$sc_maximum_active_jobs, [jmc$number, 100]],
      [jmc$sc_guaranteed_service_quan, [jmc$number, 9400]],
      [jmc$sc_scheduling_priority, [jmc$type, * ]],
        [1, [jmc$number, 8000]],
        [2, [jmc$number, 17000]],
        [3, [jmc$number, 1000]],
        [4, [jmc$number, 1000]],
      [jmc$sc_dispatching_control, [jmc$list, * ]],
        [1, [jmc$type, * ]],
          [1, [jmc$dispatching_priority, 6]],
          [2, [jmc$unlimited]],
          [3, [jmc$number, 1]],
          [4, [jmc$number, 1]]];

  VAR
    service_class_unassigned: array [1 .. 4] of attribute_preset :=
     [[jmc$sc_abbreviation, [jmc$name, ^abbreviation]],
      [jmc$sc_attempt_preemption, [jmc$boolean, FALSE]],
      [jmc$sc_maximum_active_jobs, [jmc$number, 0]],
      [jmc$sc_guaranteed_service_quan, [jmc$number, 20000]]];

?? FMT (FORMAT := ON) ??
?? TITLE := 'Output Class Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    output_class_descriptor_count = 10;

  VAR
    output_class_structure: array [1 .. output_class_descriptor_count] of
        attribute_structure := [

  [1, ['OUTPUT_CLASS', 'OC', * , jmc$type, jmc$oc_maximum_attribute, * ],
          [jmc$type, * ]],

{   ABBREVIATION                 = name

    [jmc$oc_abbreviation, ['Abbreviation', 'A', jmc$definition_group, jmc$name]
,
          [jmc$none]],

{   ENABLE_CLASS_SCHEDULING      = boolean

    [jmc$oc_enable_class_scheduling, ['Enable_Class_Scheduling', 'ECS',
          jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{   CLASS_CAPABILITIES           = list of name

{   [jmc$oc_class_capabilities, ['Class_Capabilities', 'CC',
{         jmc$control_group, jmc$empty], [jmc$none]],

{   OUTPUT_AGE_INTERVAL          = integer

    [jmc$oc_output_age_interval, ['Output_Age_Interval', 'OAI',
          jmc$priority_group, jmc$number, lowest_prio_age_interval,
          highest_prio_age_interval], [jmc$number, 1]],

{   DELIVERY_PRIORITY            = record
{    MINIMUM                         = integer
{    MAXIMUM                         = integer
{    OUTPUT_AGE_INCREMENT            = integer

    [jmc$oc_delivery_priority, ['Delivery_Priority', 'DP', jmc$priority_group,
          jmc$type, 3, * ], [jmc$type, * ]],
      [1, ['Minimum', 'MIN', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 100]],
      [2, ['Maximum', 'MAX', * , jmc$number, jmc$lowest_job_priority,
            jmc$highest_job_priority], [jmc$number, 200]],
      [3, ['Output_Age_Increment', 'OAI', * , jmc$number,
            jmc$lowest_job_priority, jmc$highest_job_priority],
            [jmc$number, 1]],

{ DELIVERY_WAIT_TIME             = record (display only)
{    MINIMUM                         = integer
{    MAXIMUM                         = integer
{    AVERAGE                         = integer
{    NUMBER_OF_FILES                 = integer

{   [jmc$oc_delivery_wait_time, ['Delivery_Wait_Time', 'DWT',
{         jmc$statistic_group, jmc$type, 4, * ], [jmc$empty]],
{     [1, ['Minimum', 'MIN', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [2, ['Maximum', 'MAX', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [3, ['Average', 'A', *, jmc$number, 0, 0], [jmc$number, 0]],
{     [4, ['Number_Of_Files', 'NOF', *, jmc$number, 0, 0], [jmc$number, 0]],

{ DEFINITION_NAME                = name (debug display only)

    [jmc$oc_definition_name, ['Definition_Name', 'DN', jmc$statistic_group,
          jmc$name], [jmc$empty]],

{ OUTPUT_CLASS_INDEX             = integer (debug display only)

    [jmc$oc_index, ['Output_Class_Index', 'OCI', jmc$statistic_group,
          jmc$number, 0, 0], [jmc$empty]]];

?? FMT (FORMAT := ON) ??
?? TITLE := 'Application Definitions', EJECT ??

?? FMT (FORMAT := OFF) ??

  CONST
    application_descriptor_count = 8;

  VAR
    application_structure: array [1 .. application_descriptor_count] of
        attribute_structure := [

  [1, ['APPLICATION', 'A', * , jmc$type, jmc$ap_maximum_attribute, * ],
          [jmc$type, * ]],

{   ENABLE_APPLICATION_SCHEDULING= boolean

    [jmc$ap_enable_application_sched, ['Enable_Application_Scheduling', 'EAS',
          jmc$definition_group, jmc$boolean], [jmc$boolean, TRUE]],

{   ENABLE_ACCOUNTING_STATISTICS = boolean

{   [jmc$ap_enable_accounting_stats, ['Enable_Accounting_Stats', 'EAS',
{         jmc$definition_group, jmc$boolean], [jmc$boolean, FALSE]],

{   SERVICE_CLASS                = jmc$profile_service_class

    [jmc$ap_service_class, ['Service_Class', 'SC', jmc$control_group,
          jmc$object, jmc$profile_service_class], [jmc$unspecified]],

{   MINIMUM_WORKING_SET          = integer

    [jmc$ap_minimum_working_set, ['Minimum_Working_Set', 'MINWS',
          jmc$control_group, jmc$number, jmc$lowest_working_set_size,
          jmc$highest_working_set_size], [jmc$unspecified]],

{   MAXIMUM_WORKING_SET          = integer

    [jmc$ap_maximum_working_set, ['Maximum_Working_Set', 'MAXWS',
          jmc$control_group, jmc$number, jmc$lowest_working_set_size,
          jmc$highest_working_set_size], [jmc$unspecified]],

{   PAGE_AGING_INTERVAL          = integer

    [jmc$ap_page_aging_interval, ['Page_Aging_Interval', 'PAI',
          jmc$control_group, jmc$number, jmc$lowest_aging_interval,
          jmc$highest_aging_interval], [jmc$unspecified]],

{   CYCLIC_AGING_INTERVAL        = integer

    [jmc$ap_cyclic_aging_interval, ['Cyclic_Aging_Interval', 'CAI',
          jmc$control_group, jmc$number, jmc$lowest_aging_interval,
          jmc$highest_aging_interval], [jmc$unspecified]],

{ DEFINITION_NAME                = name (debug display only)

    [jmc$ap_definition_name, ['Definition_Name', 'DN', jmc$statistic_group,
          jmc$name], [jmc$empty]]];

?? FMT (FORMAT := ON) ??
?? TITLE := 'check_categories', EJECT ??

{ PURPOSE:
{   Compare the excluded category and required_category lists to ensure that
{   no element is in both lists.

  PROCEDURE check_categories
    (    the_object: jmt$profile_object;
         excluded_category_index: jmt$object_attribute_index;
         required_category_index: jmt$object_attribute_index;
     VAR status: ost$status);

    VAR
      job_category: jmt$profile_object_reference,
      all_categories: boolean,
      any_categories: boolean,
      duplicate_categories: boolean,
      attribute: jmt$object_attribute,
      i: jmt$object_attribute_index;

    status.normal := TRUE;

    IF the_object.attributes.kind <> jmc$type THEN
      RETURN;
    IFEND;

    job_category := jmv$the_profile.objects [jmc$profile_category];
    WHILE job_category <> NIL DO
      job_category^.profile_index := 0;
      job_category := job_category^.next_object;
    WHILEND;

    any_categories := FALSE;
    all_categories := FALSE;

    attribute := the_object.attributes.attribute_list^
          [excluded_category_index];
    IF attribute.kind = jmc$list THEN
      FOR i := 1 TO UPPERBOUND (attribute.attribute_list^) DO
        IF attribute.attribute_list^ [i].kind = jmc$object THEN
          attribute.attribute_list^ [i].object_p^.profile_index := 1;
          any_categories := TRUE;
        IFEND;
      FOREND;
    ELSEIF attribute.kind = jmc$all THEN
      any_categories := TRUE;
      all_categories := TRUE;
    IFEND;

    duplicate_categories := FALSE;
    attribute := the_object.attributes.attribute_list^
          [required_category_index];
    IF attribute.kind = jmc$list THEN
      IF NOT all_categories THEN

      /scan_categories/
        FOR i := 1 TO UPPERBOUND (attribute.attribute_list^) DO
          IF attribute.attribute_list^ [i].kind = jmc$object THEN
            IF attribute.attribute_list^ [i].object_p^.profile_index = 1 THEN
              duplicate_categories := TRUE;
              EXIT /scan_categories/;
            IFEND;
          IFEND;
        FOREND /scan_categories/;
      ELSE
        duplicate_categories := TRUE;
      IFEND;
    ELSEIF (attribute.kind = jmc$all) AND any_categories THEN
      duplicate_categories := TRUE;
    IFEND;

    IF duplicate_categories THEN
      set_object_error (jme$duplicate_categories, the_object, status);
    IFEND;
  PROCEND check_categories;
?? TITLE := 'check_controls_attributes', EJECT ??

{ PURPOSE:
{   This routine verifies that the controls attribute list is valid.
{
{ DESIGN:
{   This routine checks:
{   o that the object name is a valid mainframe name and
{   o that the excluded_categories and required_categories do not intersect.
{   o that the dispatching allocation is correct.

  PROCEDURE check_controls_attributes
    (    the_object: jmt$profile_object;
     VAR status: ost$status);

?? NEWTITLE := 'check_dispatching_allocation', EJECT ??

{ PURPOSE:
{   This routine verifies that the dispatchin allocation list is valid.
{
{ DESIGN:
{   This routine checks:
{   o that no dispatching priority is given twice and
{   o that the sum of the minimum percentage does not exceed 100 percent.

    PROCEDURE check_dispatching_allocation
      (    dispatching_allocation: jmt$object_attribute;
       VAR status: ost$status);

      TYPE
        priority_set = set of 1 .. 8;

      VAR
        index: 1 .. 8,
        dispatching_entity: ^jmt$object_attribute_list,
        percentage_total: integer,
        priorities: priority_set,
        priority_range: 1 .. 8;

      status.normal := TRUE;
      IF dispatching_allocation.kind <> jmc$editable_list THEN
        RETURN;
      IFEND;

      priorities := $priority_set [];
      percentage_total := 0;
      FOR index := 1 TO UPPERBOUND (dispatching_allocation.attribute_list^) DO
        IF dispatching_allocation.attribute_list^ [index].kind = jmc$type THEN
          dispatching_entity := dispatching_allocation.attribute_list^ [index].
                attribute_list;
          IF dispatching_entity^ [2].kind = jmc$number THEN
            priority_range := 1;
            IF dispatching_entity^ [1].attribute_list^ [2].kind <>
                  jmc$empty THEN
              priority_range := dispatching_entity^ [1].attribute_list^ [2].
                    number - dispatching_entity^ [1].attribute_list^ [1].
                    number + 1;
            IFEND;
            percentage_total := percentage_total + priority_range *
                  dispatching_entity^ [2].number;
            IF percentage_total > 100 THEN
              set_object_error (jme$percent_sums_over_100, the_object, status);
              RETURN;
            IFEND;
          IFEND;
        IFEND;
      FOREND;
    PROCEND check_dispatching_allocation;
?? OLDTITLE, EJECT ??

    VAR
      mainframe_name: pmt$mainframe_id,
      binary_name: pmt$binary_mainframe_id;

    status.normal := TRUE;
    mainframe_name := the_object.name;
    pmp$convert_mainframe_to_binary (mainframe_name, binary_name, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF the_object.attributes.kind <> jmc$type THEN
      RETURN;
    IFEND;

    check_categories (the_object, jmc$ct_ini_required_categories,
          jmc$ct_ini_excluded_categories, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    check_categories (the_object, jmc$ct_val_required_categories,
          jmc$ct_val_excluded_categories, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    check_dispatching_allocation (the_object.attributes.
          attribute_list^ [jmc$ct_dispatching_allocation], status);
  PROCEND check_controls_attributes;
?? TITLE := 'check_job_class_attributes', EJECT ??

{ PURPOSE:
{   This routine verifies that the job class attribute list is valid.
{
{ DESIGN:
{   This routine checks:
{   o that the excluded_categories and required_categories do not intersect.
{   o that the auto_class_selection is not true for permanent job classes.

  PROCEDURE check_job_class_attributes
    (    the_object: jmt$profile_object;
     VAR status: ost$status);

    status.normal := TRUE;
    IF the_object.attributes.kind <> jmc$type THEN
      RETURN;
    IFEND;

    check_categories (the_object, jmc$jc_required_categories,
          jmc$jc_excluded_categories, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF the_object.permanent AND (the_object.attributes.
          attribute_list^ [jmc$jc_auto_class_selection].kind = jmc$boolean) AND
          the_object.attributes.attribute_list^ [jmc$jc_auto_class_selection].
          bool THEN
      osp$set_status_abnormal (jmc$job_management_id,
            jme$no_ranking_of_default_class, 'Job Class', status);
      osp$append_status_parameter (osc$status_parameter_delimiter,
            the_object.name, status);
    IFEND;
  PROCEND check_job_class_attributes;
?? TITLE := 'fetch_controls_defaults', EJECT ??

{ PURPOSE
{   Returns the default attributes the specified controls.
{
{ NOTE
{   The defaults must be modified based on mainframe type.  The value for
{   cpu_quantum type varies based on mainframe type.

  PROCEDURE fetch_controls_defaults
    (    profile: jmt$profile_data;
         the_object: jmt$profile_object;
     VAR defaults: jmt$object_attribute);

    VAR
      binary_name: pmt$binary_mainframe_id,
      definition_found: boolean,
      ignored: ost$status,
      mainframe_name: pmt$mainframe_id,
      processor_model_definition: ost$processor_model_definition,
      search_data: ost$processor_search_data;

    mainframe_name := the_object.name;
    pmp$convert_mainframe_to_binary (mainframe_name, binary_name, ignored);

    defaults := object_attribute_defaults [the_object.kind];

    search_data.search_mode := osc$psm_by_pseudo_model_number;
    search_data.pseudo_model_number := binary_name.model_number;
    osp$get_cpu_model_definition (search_data, definition_found,
          processor_model_definition);
    IF definition_found THEN
      defaults.attribute_list^ [jmc$ct_cpu_quantum_time].number :=
            processor_model_definition.quantum;
    ELSE
      defaults.attribute_list^ [jmc$ct_cpu_quantum_time].number := 30000;
    IFEND;

  PROCEND fetch_controls_defaults;
?? TITLE := 'fetch_job_class_defaults', EJECT ??

{ PURPOSE
{   Returns the default attributes for job class objects.
{
{ NOTE
{   The default for service class is set here.

  PROCEDURE fetch_job_class_defaults
    (    profile: jmt$profile_data;
         the_object: jmt$profile_object;
     VAR defaults: jmt$object_attribute);

    VAR
      target_class: jmt$profile_object_reference,
      service_class: jmt$profile_object_reference;

    defaults := object_attribute_defaults [the_object.kind];

    target_class := NIL;
    service_class := profile.objects [jmc$profile_service_class];

  /find_service_class/
    WHILE service_class <> NIL DO
      IF service_class^.name = jmc$unassigned_class_name THEN
        target_class := service_class;
      ELSEIF service_class^.name = the_object.name THEN
        target_class := service_class;
        EXIT /find_service_class/;
      IFEND;
      service_class := service_class^.next_object;
    WHILEND /find_service_class/;
    defaults.attribute_list^ [jmc$jc_initial_service_class].object_p :=
          target_class;

  PROCEND fetch_job_class_defaults;
?? TITLE := 'fetch_standard_defaults', EJECT ??

{ PURPOSE
{   Returns the default attributes for objects of the type of the specified
{   object.
{
{ NOTE
{   This routine is used to only if the defaults can be used as is.

  PROCEDURE fetch_standard_defaults
    (    profile: jmt$profile_data;
         the_object: jmt$profile_object;
     VAR defaults: jmt$object_attribute);

    defaults := object_attribute_defaults [the_object.kind];

  PROCEND fetch_standard_defaults;

?? TITLE := '[XDCL] jmp$build_default_profile', EJECT ??

{ PURPOSE:
{   Initializes the tables defining what the attributes of each object type
{   are and then builds the standard profile.
{
{ NOTES:
{   The standard profile consists of
{      Job categories  INTERACTIVE, BATCH
{      Job classes     INTERACTIVE, BATCH, MAINTENANCE, SYSTEM, UNASSIGNED
{      Service classes INTERACTIVE, BATCH, MAINTENANCE, SYSTEM, UNASSIGNED

  PROCEDURE [XDCL] jmp$build_default_profile
    (VAR status: ost$status);

    VAR
      no_attributes: [STATIC] jmt$object_attribute := [jmc$empty];

?? NEWTITLE := 'build_object_attributes', EJECT ??

{ PURPOSE:
{   Builds the default attributes for the specified object.
{
{ DESIGN:
{   The default attributes are built from a flat static list which gives
{   values for the desired attributes.  The attribute declarations are used
{   to determine the shape of the attribute lists.

    PROCEDURE build_object_attributes
      (    attribute_values: attribute_preset_list;
       VAR object_attribute_definitions: jmt$profile_declaration;
       VAR object_attributes: jmt$object_attribute);

      VAR
        index: jmt$object_attribute_index,
        last_index: jmt$object_attribute_index;

?? NEWTITLE := 'build_attribute', EJECT ??

{ PURPOSE
{   Builds the data structure for an attribute based on the attribute value
{   list.
{
{ DESIGN
{   Since the attribute data is defined recursively, this routine calls
{   itself to build the lower levels of the attribute definition.

      PROCEDURE build_attribute
        (    attribute_definition: jmt$profile_declaration;
         VAR attribute: jmt$object_attribute);

        VAR
          local_attribute: jmt$object_attribute,
          list_size: jmt$object_attribute_index,
          i: jmt$object_attribute_index,
          j: jmt$object_attribute_index;

        IF attribute_definition.kind <= jmc$range THEN
          list_size := attribute_definition.count;
          IF attribute_values [index].list_index > list_size THEN
            list_size := attribute_values [index].list_index;
          IFEND;
          ALLOCATE attribute.attribute_list: [1 .. list_size] IN
                jmv$object_heap^;
          IF attribute.attribute_list = NIL THEN
            jmp$internal_error (10);
          IFEND;
          FOR i := 1 TO list_size DO
            attribute.attribute_list^ [i].kind := jmc$empty;
          FOREND;
          FOR i := 1 TO list_size DO
            j := attribute_values [index].list_index;
            attribute.attribute_list^ [j] := attribute_values [index].
                  attribute;
            index := index + 1;
            IF attribute_definition.kind = jmc$type THEN
              build_attribute (attribute_definition.declarations^ [j]^,
                    attribute.attribute_list^ [j]);
            ELSE
              build_attribute (attribute_definition.declarations^ [1]^,
                    attribute.attribute_list^ [j]);
            IFEND;
            IF index > last_index THEN
              RETURN;
            IFEND;
          FOREND;
        ELSE
          local_attribute := attribute;
          jmp$copy_attributes (local_attribute, attribute);
        IFEND;
      PROCEND build_attribute;
?? OLDTITLE, EJECT ??

      index := 1;
      last_index := UPPERBOUND (attribute_values);
      object_attributes.kind := object_attribute_definitions.kind;
      build_attribute (object_attribute_definitions, object_attributes);
    PROCEND build_object_attributes;
?? TITLE := 'build_object_descriptions', EJECT ??

{ PURPOSE:
{   This routine builds the declaration structure and default attributes
{   for each object type from the flat static declarations lists.
{
{ DESIGN:
{   Builds the declaration and default attribute trees from a static
{   description in flat form.
{
{   A flat list has the form
{     [index  declaration  attribute_value]
{
{   A flat list of the form
{     [1 a*1 aa] [1 b*2 ba] [1 c*0 ca] [2 d*2 da] [1 e*0 ea] [1 f*0 fa] ..
{     [3 g*0 ga]
{
{   builds the following two lists.
{              c                         ca
{      a - b - |   e           aa - ba - |    ea
{              d - |                     da - |
{              |   f                     |    fa
{              g                         ga
{
{ NOTE:
{   Index starts at 2 because the values at index = 1 are used in the call
{   to build_lists.

    PROCEDURE build_object_descriptions
      (VAR object_declarations: structure_list;
       VAR object_definition: jmt$profile_declaration;
       VAR object_attribute_default: jmt$object_attribute);

      VAR
        index: jmt$object_attribute_index,
        last_index: jmt$object_attribute_index;

?? NEWTITLE := 'build_lists', EJECT ??

{ PURPOSE
{   Builds the lists for the attribute definition and for the default
{   values of the attribute.
{
{ DESIGN
{   Since the definition and default value lists for attributes are
{   defined recursively the routine calls itself to define the definitions
{   and default values of the attributes of the attributes.

      PROCEDURE build_lists
        (VAR definition: jmt$profile_declaration;
         VAR default: jmt$object_attribute);

        VAR
          list_size: jmt$object_attribute_index,
          i: jmt$object_attribute_index,
          j: jmt$object_attribute_index;

        IF definition.kind <= jmc$range THEN
          list_size := definition.count;
          ALLOCATE definition.declarations: [1 .. list_size] IN
                jmv$object_heap^;
          ALLOCATE default.attribute_list: [1 .. list_size] IN
                jmv$object_heap^;
          IF (default.attribute_list = NIL) OR
                (definition.declarations = NIL) THEN
            jmp$internal_error (11);
          IFEND;
          FOR i := 1 TO list_size DO
            definition.declarations^ [i] := ^empty_declaration;
            default.attribute_list^ [i].kind := jmc$empty;
          FOREND;
          FOR i := 1 TO list_size DO
            j := object_declarations [index].list_index;
            definition.declarations^ [j] := ^object_declarations [index].
                  definition;
            default.attribute_list^ [j] := object_declarations [index].default;
            index := index + 1;
            build_lists (definition.declarations^ [j]^,
                  default.attribute_list^ [j]);
            IF index > last_index THEN
              RETURN;
            IFEND;
          FOREND;
        IFEND;
      PROCEND build_lists;
?? OLDTITLE, EJECT ??

      index := 2;
      last_index := UPPERBOUND (object_declarations);
      object_definition := object_declarations [1].definition;
      object_attribute_default := object_declarations [1].default;
      build_lists (object_definition, object_attribute_default);
    PROCEND build_object_descriptions;
?? TITLE := 'build_job_and_service_classes', EJECT ??

{ PURPOSE
{   Build the standard job and service classes for the default profile.
{
{ NOTE
{   The initial service class for each job class is the service class
{   with the same name.

    PROCEDURE build_job_and_service_classes
      (VAR status: ost$status);

      VAR
        class_name: [STATIC, READ] array [job_and_service_classes] of
              string (12) := [jmc$interactive_class_name, jmc$batch_class_name,
              jmc$system_class_name, jmc$maintenance_class_name,
              jmc$unassigned_class_name],
        class_index: [STATIC, READ] array [job_and_service_classes] of
              jmt$object_attribute_index := [jmc$lowest_site_job_class,
              jmc$lowest_site_job_class + 1, jmc$system_job_class,
              jmc$maintenance_job_class, jmc$unassigned_job_class];

      VAR
        class: job_and_service_classes,
        job_class: jmt$profile_object_reference,
        service_class: jmt$profile_object_reference;

      status.normal := TRUE;

      FOR class := interactive TO unassigned DO
        abbreviation := class_name [class] (1);

        jmp$add_object (jmc$profile_service_class, class_name [class],
              no_attributes, service_class, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        jmp$add_object (jmc$profile_job_class, class_name [class],
              no_attributes, job_class, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        IF class > batch THEN
          service_class^.permanent := TRUE;
          job_class^.permanent := TRUE;
        IFEND;

        service_class^.index := class_index [class];
        job_class^.index := class_index [class];

        build_object_attributes (service_class_defaults [class]^,
              jmv$object_definition [jmc$profile_service_class].declaration,
              service_class^.attributes);
        build_object_attributes (job_class_defaults [class]^,
              jmv$object_definition [jmc$profile_job_class].declaration,
              job_class^.attributes);

        service_class^.definition_id := class_name [class];
        service_class^.behaviour_id := jmc$standard_behaviour;
        job_class^.definition_id := class_name [class];
        job_class^.behaviour_id := jmc$standard_behaviour;
      FOREND;
    PROCEND build_job_and_service_classes;
?? TITLE := 'build_job_categories', EJECT ??

{  PURPOSE
{    This procedure builds the default job categories of INTERACTIVE and
{    BATCH for the standard profile.

    PROCEDURE build_job_categories
      (VAR status: ost$status);

      CONST
        interactive_category_index = 1,
        batch_category_index = 2;

      TYPE
        category_indicies = interactive_category_index .. batch_category_index;

      CONST
        interactive_category_name = 'INTERACTIVE',
        batch_category_name = 'BATCH';

      VAR
        category_name: [STATIC, READ] array [category_indicies] of
              ost$name := [interactive_category_name, batch_category_name];

      VAR
        category_index: category_indicies,
        job_category: jmt$profile_object_reference;

      status.normal := TRUE;

      FOR category_index := LOWERVALUE (category_indicies)
            TO UPPERVALUE (category_indicies) DO
        jmp$add_object (jmc$profile_category, category_name [category_index],
              no_attributes, job_category, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        job_category^.index := category_index;

        category_default [2].attribute.name := ^category_name [category_index];

        build_object_attributes (category_default,
              jmv$object_definition [jmc$profile_category].declaration,
              job_category^.attributes);

{ Store references to the job categories in the job class attributes.
{ Batch and System have excluded_categories = interactive.
{ Interactive has excluded_categories = batch.

        IF category_index = interactive_category_index THEN
          job_class_batch [2].attribute.object_p := job_category;
          job_class_system [2].attribute.object_p := job_category;
        ELSE
          job_class_interactive [2].attribute.object_p := job_category;
        IFEND;

        job_category^.definition_id := category_name [category_index];
        job_category^.behaviour_id := jmc$standard_behaviour;
      FOREND;
    PROCEND build_job_categories;
?? TITLE := 'build_sorted_parameter_list', EJECT ??

{ PURPOSE:
{   This procedure builds a sorted parameter list from the declaration
{   for the object's attributes.

    PROCEDURE build_sorted_parameter_list
      (    declaration_list: jmt$profile_declaration_list;
       VAR parameter_list: ^jmt$object_parameter_list);

?? NEWTITLE := 'sort_parameters', EJECT ??

{ PURPOSE
{   This procedure sorts a parameter list by name.
{
{ DESIGN:
{   The sort used is a shell sort.

      PROCEDURE sort_parameters
        (VAR parameter_list: jmt$object_parameter_list);

        VAR
          gap: integer,
          starting_index: integer,
          current_index: integer,
          current_element: jmt$object_parameter_element;

{ Use shell sort technique.

        gap := 1;
        REPEAT
          gap := gap * 3 + 1;
        UNTIL gap > UPPERBOUND (parameter_list);

        WHILE gap > 1 DO
          gap := gap DIV 3;
          FOR starting_index := gap + 1 TO UPPERBOUND (parameter_list) DO
            current_index := starting_index;
            current_element := parameter_list [current_index];
            WHILE (current_index > gap) AND (current_element.name <
                  parameter_list [current_index - gap].name) DO
              parameter_list [current_index] :=
                    parameter_list [current_index - gap];
              current_index := current_index - gap;
            WHILEND;
            parameter_list [current_index] := current_element;
          FOREND;
        WHILEND;

      PROCEND sort_parameters;
?? OLDTITLE, EJECT ??

      VAR
        declaration_index: jmt$object_attribute_index,
        list_length: integer,
        unsorted_parameters: ^jmt$object_parameter_list,
        parameter_element: ^jmt$object_parameter_element;

      RESET jmv$working_storage;
      list_length := 0;
      FOR declaration_index := LOWERBOUND (declaration_list)
            TO UPPERBOUND (declaration_list) DO
        IF declaration_list [declaration_index] <> ^empty_declaration THEN
          NEXT parameter_element IN jmv$working_storage;
          #TRANSLATE (osv$lower_to_upper, declaration_list
                [declaration_index]^.name, parameter_element^.name);
          parameter_element^.attribute_index := declaration_index;
          parameter_element^.abbreviation := FALSE;
          NEXT parameter_element IN jmv$working_storage;
          parameter_element^.name := declaration_list [declaration_index]^.
                abbreviation;
          parameter_element^.attribute_index := declaration_index;
          parameter_element^.abbreviation := TRUE;
          list_length := list_length + 2;
        IFEND;
      FOREND;

      RESET jmv$working_storage;
      NEXT unsorted_parameters: [1 .. list_length] IN jmv$working_storage;
      ALLOCATE parameter_list: [1 .. list_length] IN jmv$object_heap^;
      parameter_list^ := unsorted_parameters^;

      sort_parameters (parameter_list^);

    PROCEND build_sorted_parameter_list;

?? TITLE := 'build_standard_controls', EJECT ??

{ PURPOSE
{   This procedure builds the controls for the standard profile.  The controls
{   are built for the mainframe on which the utility is run.

    PROCEDURE build_standard_controls
      (VAR status: ost$status);

      VAR
        controls: jmt$profile_object_reference;

      status.normal := TRUE;

      jmp$add_object (jmc$profile_controls, mainframe_id, no_attributes,
            controls, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      controls^.definition_id := mainframe_id;
      controls^.behaviour_id := jmc$standard_behaviour;
      controls^.index := 1;
    PROCEND build_standard_controls;
?? TITLE := 'update_dynamic_defaults', EJECT ??

{ PURPOSE
{   Update the job class and service class default attributes
{   with those values that depend on the deadstart.

    PROCEDURE update_dynamic_defaults
      (VAR status: ost$status);

      VAR
        job_class_defaults: jmt$job_class_attributes,
        service_class_defaults: jmt$service_class_attributes,
        application_defaults: jmt$application_attributes;

      status.normal := TRUE;

      jmp$get_default_class_values (job_class_defaults, service_class_defaults,
            application_defaults, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      object_attribute_defaults [jmc$profile_job_class].
            attribute_list^ [jmc$jc_page_aging_interval].attribute_list^ [1].
            number := job_class_defaults.page_aging_interval.default;

    PROCEND update_dynamic_defaults;
?? OLDTITLE, EJECT ??

    VAR
      control_default: clt$data_value,
      initial_call: [STATIC] boolean := TRUE,
      object_kind: jmt$profile_object_kinds,
      segment_pointer: amt$segment_pointer;

    status.normal := TRUE;

    IF initial_call THEN

      pmp$get_mainframe_id (mainframe_id, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

{ Create heap for allocating objects and their attributes.

      mmp$create_scratch_segment (amc$heap_pointer, mmc$as_random,
            segment_pointer, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      jmv$object_heap := segment_pointer.heap_pointer;

{ Create sequence for temporary storage of data.

      mmp$create_scratch_segment (amc$sequence_pointer, mmc$as_random,
            segment_pointer, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      jmv$working_storage := segment_pointer.sequence_pointer;
      initial_call := FALSE;
    IFEND;

    RESET jmv$object_heap^;
    RESET jmv$working_storage;

    FOR object_kind := LOWERVALUE (object_kind) TO UPPERVALUE (object_kind) DO
      jmv$current_class_name [object_kind] := NIL;
    FOREND;

{ Build internal tables.

    FOR object_kind := LOWERVALUE (object_kind) TO UPPERVALUE (object_kind) DO
      build_object_descriptions (object_structure [object_kind]^,
            jmv$object_definition [object_kind].declaration,
            object_attribute_defaults [object_kind]);
      IF jmv$object_definition [object_kind].declaration.kind = jmc$type THEN
        build_sorted_parameter_list (jmv$object_definition [object_kind].
              declaration.declarations^, jmv$object_definition [object_kind].
              sorted_parameters);
      IFEND;
      jmv$new_profile.objects [object_kind] := NIL;
      jmv$new_profile.count [object_kind] := 0;
    FOREND;
    jmv$the_profile := jmv$new_profile;

    build_object_attributes (ds_priority_control_default,
          jmv$object_definition [jmc$profile_controls].declaration.
          declarations^ [jmc$ct_dual_state_prio_control]^,
          object_attribute_defaults [jmc$profile_controls].
          attribute_list^ [jmc$ct_dual_state_prio_control]);

    update_dynamic_defaults (status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Create controls for this mainframe.

    build_standard_controls (status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Create standard job categories.

    build_job_categories (status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Create the standard output classes.

{ Create the standard job and service classes.

    build_job_and_service_classes (status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    jmv$the_profile.definition_id := jmv$the_profile.
          objects [jmc$profile_controls]^.definition_id;

    jmp$set_object_default (jmc$profile_category, NIL);
    jmp$set_object_default (jmc$profile_service_class, NIL);
    jmp$set_object_default (jmc$profile_job_class, NIL);

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

{ PURPOSE:
{   Issues the message 'Internal profile error #n.'

  PROCEDURE [XDCL, #GATE] jmp$internal_error
    (    location: integer);

    VAR
      number: string (10),
      string_size: integer,
      status: ost$status;

    STRINGREP (number, string_size, location);
    osp$set_status_abnormal (jmc$job_management_id, jme$profile_internal_error,
          number, status);
    pmp$abort (status);
  PROCEND jmp$internal_error;
?? TITLE := '[XDCL] jmp$set_profile', EJECT ??

{ PURPOSE:
{   Makes the specified profile the working profile.
{
{ DESIGN:
{   It moves the provided profile to jmv$the_profile.
{   It finds the UNASSIGNED service class in the profile and stores a reference
{   to it in the default for the 'INITIAL_SERVICE_CLASS' attribute for
{   job classes.
{
{ FUTURE:
{   When output classes are implemented - Find the NORMAL output class in the
{   profile and store a reference to it in the default for the attribute
{   'INITIAL_OUTPUT_CLASS' for job classes.

  PROCEDURE [XDCL] jmp$set_profile
    (VAR profile: jmt$profile_data);

    VAR
      control_default: clt$data_value,
      deleted_object: jmt$profile_object_reference,
      next_object: jmt$profile_object_reference,
      object_kind: jmt$profile_object_kinds,
      service_class: jmt$profile_object_reference;

    FOR object_kind := LOWERVALUE (object_kind) TO UPPERVALUE (object_kind) DO
      deleted_object := jmv$the_profile.objects [object_kind];
      WHILE deleted_object <> NIL DO
        jmp$delete_attributes (deleted_object^.attributes);
        deleted_object := deleted_object^.next_object;
      WHILEND;
    FOREND;

    FOR object_kind := LOWERVALUE (object_kind) TO UPPERVALUE (object_kind) DO
      deleted_object := jmv$the_profile.objects [object_kind];
      WHILE deleted_object <> NIL DO
        next_object := deleted_object^.next_object;
        FREE deleted_object IN jmv$object_heap^;
        deleted_object := next_object;
      WHILEND;
      jmv$the_profile.objects [object_kind] := profile.objects [object_kind];
      profile.objects [object_kind] := NIL;
      jmp$set_object_default (jmc$profile_controls, NIL);
    FOREND;

    control_default.kind := clc$name;
    control_default.name_value := mainframe_id;
    jmp$set_object_default (jmc$profile_controls, ^control_default);
    jmv$the_profile.definition_id := profile.definition_id;
    jmv$the_profile.count := profile.count;

    jmv$current_profile_level := jmc$profile_job_class;

  PROCEND jmp$set_profile;
?? TITLE := 'set_object_error', EJECT ??

{ PURPOSE:
{   This routine builds an error message including both the object name
{   and object kind.

  PROCEDURE set_object_error
    (    the_error: ost$status_condition_code;
         the_object: jmt$profile_object;
     VAR status: ost$status);

    osp$set_status_abnormal (jmc$job_management_id, the_error, the_object.name,
          status);
    osp$append_status_parameter (osc$status_parameter_delimiter,
          jmv$object_definition [the_object.kind].declaration.name, status);
  PROCEND set_object_error;
MODEND jmm$administer_definitions;
