?? RIGHT := 110 ??
?? NEWTITLE := 'clm$keypoint_commands' ??
MODULE clm$keypoint_commands;

{PURPOSE:
{    The purpose of this module is to process the SCL keypoint
{    commands.

?? PUSH (LISTEXT := ON) ??
*copyc clt$value
*copyc clt$path_display_chunks
*copyc osc$multiprocessor_constants
*copyc osd$wait
*copyc oss$job_paged_literal
*copyc ost$keypoint_class
*copyc ost$keypoint_control
*copyc pfe$internal_error_conditions
*copyc pmd$local_queues
*copyc syt$perf_keypoints_enabled
?? POP ??
*copyc amp$get_segment_pointer
*copyc amp$put_next
*copyc amv$nil_file_identifier
*copyc clp$build_standard_title
*copyc clp$close_display
*copyc clp$convert_integer_to_string
*copyc clp$convert_str_to_path_handle
*copyc clp$get_set_count
*copyc clp$get_value
*copyc clp$horizontal_tab_display
*copyc clp$new_display_line
*copyc clp$open_display
*copyc clp$put_display
*copyc clp$put_job_output
*copyc clp$put_partial_display
*copyc clp$reset_for_next_display_page
*copyc clp$scan_parameter_list
*copyc clp$trimmed_string_size
*copyc clp$turn_keypoint_off
*copyc clv$nil_display_control
*copyc dfp$locate_served_family
*copyc fsp$close_file
*copyc fsp$open_file
*copyc fsp$path_element
*copyc osp$collection_file_info
*copyc osp$disestablish_cond_handler
*copyc osp$display_keypoint_status
*copyc osp$establish_block_exit_hndlr
*copyc osp$fetch_collection_file_info
*copyc osp$generate_message
*copyc osp$issue_string_as_keypoint
*copyc osp$release_keypoint_env
*copyc osp$reserve_keypoint_env
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc osp$start_keypoint_collection
*copyc osp$stop_keypoint_collection
*copyc pmp$connect_queue
*copyc pmp$continue_to_cause
*copyc pmp$define_queue
*copyc pmp$disconnect_queue
*copyc pmp$format_compact_date
*copyc pmp$format_compact_time
*copyc pmp$receive_from_queue
*copyc pmp$remove_queue


?? TITLE := 'clp$issue_keypoint', EJECT ??

  PROCEDURE [XDCL] clp$issue_keypoint
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PDT keypoint_pdt (
{ class: INTEGER 0..15 = 15
{ code: INTEGER 0..0ffffffff(16) = 0
{ status)

?? PUSH (LISTEXT := ON) ??

    VAR
      keypoint_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^keypoint_pdt_names, ^keypoint_pdt_params];

    VAR
      keypoint_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
            clt$parameter_name_descriptor := [['CLASS', 1], ['CODE', 2], ['STATUS', 3]];

    VAR
      keypoint_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 3] of clt$parameter_descriptor := [

{ CLASS }
      [[clc$optional_with_default, ^keypoint_pdt_dv1], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$integer_value, 0, 15]],

{ CODE }
      [[clc$optional_with_default, ^keypoint_pdt_dv2], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$integer_value, 0, 0ffffffff(16)]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

    VAR
      keypoint_pdt_dv1: [STATIC, READ, cls$pdt_names_and_defaults] string (2) := '15';

    VAR
      keypoint_pdt_dv2: [STATIC, READ, cls$pdt_names_and_defaults] string (1) := '0';

?? POP ??

    VAR
      k_class: integer,
      value: clt$value;


    clp$scan_parameter_list (parameter_list, keypoint_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('CLASS', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    k_class := value.int.value;

    clp$get_value ('CODE', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$keypoint (k_class, value.int.value);

  PROCEND clp$issue_keypoint;

{   PDT status_pdt (data_string,ds: string 0..32 = 'keypoint_collection_utility'
{       status)

?? PUSH (LISTEXT := ON) ??

  VAR
    status_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
          [^status_pdt_names, ^status_pdt_params];

  VAR
    status_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
          clt$parameter_name_descriptor := [['DATA_STRING', 1], ['DS', 1], ['STATUS', 2]];

  VAR
    status_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 2] of clt$parameter_descriptor := [

{ DATA_STRING DS }
    [[clc$optional_with_default, ^status_pdt_dv1], 1, 1, 1, 1, clc$value_range_not_allowed,
          [NIL, clc$string_value, 0, 32]],

{ STATUS }
    [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
          [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

  VAR
    status_pdt_dv1: [STATIC, READ, cls$pdt_names_and_defaults] string (29) :=
          '''keypoint_collection_utility''';

?? POP ??

  CONST
    utility_name = 'KCU                            ';

?? TITLE := 'clp$reserve_keypoint_env', EJECT ??

  PROCEDURE [XDCL] clp$reserve_keypoint_env
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{     PDT actkc_pdt (
{       environment,e: key job, j, system, s, sample_system, ss, sample_job, sj = job
{       collection_files,collection_file,cf: list of file = $required
{       monitor_mask,mm: list of integer 0..15 or key all = all
{       job_mask,jm: list of integer 0..15 or key all = all
{       wait,wai: boolean = true
{       multiprocessor,m: key single, all = single
{       keypoint_count,kc: integer 1..250000000 = 100000
{       keypoint_buffer_size,kbs: integer 1..32 = 1
{       data_string,ds: string 0..32 = 'keypoint collection utility'
{       performance: list of key memory, heap, swapping, aging, swap_trace, age_trace, disk, command, all,..
{            none = none
{       status)

?? PUSH (LISTEXT := ON) ??

  VAR
    actkc_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^actkc_pdt_names, ^actkc_pdt_params
  ];

  VAR
    actkc_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 21] of
  clt$parameter_name_descriptor := [['ENVIRONMENT', 1], ['E', 1], ['COLLECTION_FILES', 2], ['COLLECTION_FILE'
  , 2], ['CF', 2], ['MONITOR_MASK', 3], ['MM', 3], ['JOB_MASK', 4], ['JM', 4], ['WAIT', 5], ['WAI', 5], [
  'MULTIPROCESSOR', 6], ['M', 6], ['KEYPOINT_COUNT', 7], ['KC', 7], ['KEYPOINT_BUFFER_SIZE', 8], ['KBS', 8], [
  'DATA_STRING', 9], ['DS', 9], ['PERFORMANCE', 10], ['STATUS', 11]];

  VAR
    actkc_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 11] of clt$parameter_descriptor := [

{ ENVIRONMENT E }
    [[clc$optional_with_default, ^actkc_pdt_dv1], 1, 1, 1, 1, clc$value_range_not_allowed, [^actkc_pdt_kv1,
  clc$keyword_value]],

{ COLLECTION_FILES COLLECTION_FILE CF }
    [[clc$required], 1, clc$max_value_sets,1, 1, clc$value_range_not_allowed, [NIL, clc$file_value]],

{ MONITOR_MASK MM }
    [[clc$optional_with_default, ^actkc_pdt_dv3], 1, clc$max_value_sets,1, 1, clc$value_range_not_allowed, [^
  actkc_pdt_kv3, clc$integer_value, 0, 15]],

{ JOB_MASK JM }
    [[clc$optional_with_default, ^actkc_pdt_dv4], 1, clc$max_value_sets,1, 1, clc$value_range_not_allowed, [^
  actkc_pdt_kv4, clc$integer_value, 0, 15]],

{ WAIT WAI }
    [[clc$optional_with_default, ^actkc_pdt_dv5], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
  clc$boolean_value]],

{ MULTIPROCESSOR M }
    [[clc$optional_with_default, ^actkc_pdt_dv6], 1, 1, 1, 1, clc$value_range_not_allowed, [^actkc_pdt_kv6,
  clc$keyword_value]],

{ KEYPOINT_COUNT KC }
    [[clc$optional_with_default, ^actkc_pdt_dv7], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
  clc$integer_value, 1, 250000000]],

{ KEYPOINT_BUFFER_SIZE KBS }
    [[clc$optional_with_default, ^actkc_pdt_dv8], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
  clc$integer_value, 1, 32]],

{ DATA_STRING DS }
    [[clc$optional_with_default, ^actkc_pdt_dv9], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL,
  clc$string_value, 0, 32]],

{ PERFORMANCE }
    [[clc$optional_with_default, ^actkc_pdt_dv10], 1, clc$max_value_sets,1, 1, clc$value_range_not_allowed, [^
  actkc_pdt_kv10, clc$keyword_value]],

{ STATUS }
    [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$variable_reference,
  clc$array_not_allowed, clc$status_value]]];

  VAR
    actkc_pdt_kv1: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 8] of ost$name := ['JOB','J',
  'SYSTEM','S','SAMPLE_SYSTEM','SS','SAMPLE_JOB','SJ'];

  VAR
    actkc_pdt_kv3: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 1] of ost$name := ['ALL'];

  VAR
    actkc_pdt_kv4: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 1] of ost$name := ['ALL'];

  VAR
    actkc_pdt_kv6: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 2] of ost$name := ['SINGLE','ALL'];

  VAR
    actkc_pdt_kv10: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 10] of ost$name := ['MEMORY','HEAP'
  ,'SWAPPING','AGING','SWAP_TRACE','AGE_TRACE','DISK','COMMAND','ALL','NONE'];

  VAR
    actkc_pdt_dv1: [STATIC, READ, cls$pdt_names_and_defaults] string (3) := 'job';

  VAR
    actkc_pdt_dv3: [STATIC, READ, cls$pdt_names_and_defaults] string (3) := 'all';

  VAR
    actkc_pdt_dv4: [STATIC, READ, cls$pdt_names_and_defaults] string (3) := 'all';

  VAR
    actkc_pdt_dv5: [STATIC, READ, cls$pdt_names_and_defaults] string (4) := 'true';

  VAR
    actkc_pdt_dv6: [STATIC, READ, cls$pdt_names_and_defaults] string (6) := 'single';

  VAR
    actkc_pdt_dv7: [STATIC, READ, cls$pdt_names_and_defaults] string (6) := '100000';

  VAR
    actkc_pdt_dv8: [STATIC, READ, cls$pdt_names_and_defaults] string (1) := '1';

  VAR
    actkc_pdt_dv9: [STATIC, READ, cls$pdt_names_and_defaults] string (29) := '''keypoint collection utility'''
  ;

  VAR
    actkc_pdt_dv10: [STATIC, READ, cls$pdt_names_and_defaults] string (4) := 'none';

?? POP ??

    VAR
      number_of_files: 0 .. 0ff(16),
      keypoint_count,
      keypoint_buffer_size,
      processor_count,
      j,
      i: integer,
      str: string (32),
      ls: ost$status,
      as: [STATIC, READ, oss$job_paged_literal] array [1 .. 2] of fst$attachment_option := [
            {} [fsc$access_and_share_modes, {} [fsc$specific_access_modes,
            [fsc$append, fsc$shorten, fsc$modify]], {} [fsc$specific_share_modes, []]],
            {} [fsc$open_share_modes, [fsc$read, fsc$shorten, fsc$append, fsc$modify, fsc$execute]]],
      environment: ost$keypoint_environment,
      mpo: ost$keypoint_multipro_option,
      wait: ost$wait,
      value: clt$value,
      perf_keypoints: syt$perf_keypoints_enabled,
      count: 0 .. clc$max_value_sets,
      jm,
      mm,
      requested_mask: ost$keypoint_mask,
      mask_value: 0 .. 15,
      segp: amt$segment_pointer,
      fid_array: ^array [ * ] of amt$file_identifier,
      fid: array [1 .. osc$max_number_of_processors] of amt$file_identifier,
      pva: array [1 .. osc$max_number_of_processors] of ^cell,
      termination_complete: boolean,
      pva_array: ^array [ * ] of ^cell;

    clp$scan_parameter_list (parameter_list, actkc_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('ENVIRONMENT', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF (value.name.value = 'JOB') OR (value.name.value = 'J') THEN
      environment := osc$job_keypoints;
    ELSEIF (value.name.value = 'SAMPLE_JOB') OR (value.name.value = 'SJ') THEN
      environment := osc$job_sample_keypoints;
    ELSEIF (value.name.value = 'SAMPLE_SYSTEM') OR (value.name.value = 'SS') THEN
      environment := osc$system_sample_keypoints;
    ELSE
      environment := osc$system_keypoints;
    IFEND;

    requested_mask := $ost$keypoint_mask [];
    clp$get_set_count ('MONITOR_MASK', count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    FOR i := 1 TO count DO
      clp$get_value ('MONITOR_MASK', i, 1, clc$low, value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF value.kind = clc$name_value THEN
        requested_mask := -$ost$keypoint_mask [];
      ELSE
        mask_value := value.int.value;
        requested_mask := requested_mask + $ost$keypoint_mask [mask_value];
      IFEND;
    FOREND;
    mm := requested_mask + $ost$keypoint_mask [15];


    requested_mask := $ost$keypoint_mask [];
    clp$get_set_count ('JOB_MASK', count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    FOR i := 1 TO count DO
      clp$get_value ('JOB_MASK', i, 1, clc$low, value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF value.kind = clc$name_value THEN
        requested_mask := -$ost$keypoint_mask [];
      ELSE
        mask_value := value.int.value;
        requested_mask := requested_mask + $ost$keypoint_mask [mask_value];
      IFEND;
    FOREND;
    jm := requested_mask + $ost$keypoint_mask [15];

    clp$get_value ('WAIT', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF value.bool.value = TRUE THEN
      wait := osc$wait;
    ELSE
      wait := osc$nowait;
    IFEND;

    clp$get_value ('DATA_STRING', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    str := value.str.value (1, value.str.size);

    clp$get_value ('MULTIPROCESSOR', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF value.name.value = 'SINGLE' THEN
      mpo := osc$keypoints_single_processor;
    ELSE
      mpo := osc$keypoints_multi_processor;
    IFEND;

    clp$get_value ('KEYPOINT_COUNT', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    keypoint_count := value.int.value;

    clp$get_value ('KEYPOINT_BUFFER_SIZE', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    keypoint_buffer_size := value.int.value;

    clp$get_set_count ('COLLECTION_FILES', count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    number_of_files := 0;
    PUSH fid_array: [1 .. count];
    PUSH pva_array: [1 .. count];

    termination_complete := FALSE;

  /files_open/
    BEGIN
      FOR i := 1 TO count DO
        clp$get_value ('COLLECTION_FILES', i, 1, clc$low, value, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        check_collection_file_location (value.file.local_file_name, status);
        IF NOT status.normal THEN
          EXIT /files_open/;
        IFEND;
        fsp$open_file (value.file.local_file_name, amc$segment, ^as, NIL, NIL, NIL, NIL, fid_array^ [i],
              status);
        IF NOT status.normal THEN
          EXIT /files_open/;
        IFEND;
        number_of_files := number_of_files + 1;
        amp$get_segment_pointer (fid_array^ [i], amc$cell_pointer, segp, status);
        IF NOT status.normal THEN
          EXIT /files_open/;
        IFEND;
        pva_array^ [i] := segp.cell_pointer;
      FOREND;

      clp$get_set_count ('PERFORMANCE', count, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      perf_keypoints.memory_keypoints := FALSE;
      perf_keypoints.heap_keypoints := FALSE;
      perf_keypoints.swapping_keypoints := FALSE;
      perf_keypoints.aging_keypoints := FALSE;
      perf_keypoints.swapping_stack_trace := FALSE;
      perf_keypoints.aging_stack_trace := FALSE;
      perf_keypoints.disk_cache := FALSE;
      perf_keypoints.command_keypoints := FALSE;

      FOR i := 1 TO count DO
        clp$get_value ('PERFORMANCE', i, 1, clc$low, value, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        IF value.name.value = 'MEMORY' THEN
          perf_keypoints.memory_keypoints := TRUE;
        ELSEIF value.name.value = 'HEAP' THEN
          perf_keypoints.heap_keypoints := TRUE;
        ELSEIF value.name.value = 'SWAPPING' THEN
          perf_keypoints.swapping_keypoints := TRUE;
        ELSEIF value.name.value = 'AGING' THEN
          perf_keypoints.aging_keypoints := TRUE;
        ELSEIF value.name.value = 'SWAP_TRACE' THEN
          perf_keypoints.swapping_stack_trace := TRUE;
        ELSEIF value.name.value = 'AGE_TRACE' THEN
          perf_keypoints.aging_stack_trace := TRUE;
        ELSEIF value.name.value = 'DISK' THEN
          perf_keypoints.disk_cache := TRUE;
        ELSEIF value.name.value = 'COMMAND' THEN
          perf_keypoints.command_keypoints := TRUE;
        ELSEIF value.name.value = 'NONE' THEN
          perf_keypoints.memory_keypoints := FALSE;
          perf_keypoints.heap_keypoints := FALSE;
          perf_keypoints.swapping_keypoints := FALSE;
          perf_keypoints.aging_keypoints := FALSE;
          perf_keypoints.swapping_stack_trace := FALSE;
          perf_keypoints.aging_stack_trace := FALSE;
          perf_keypoints.disk_cache := FALSE;
          perf_keypoints.command_keypoints := FALSE;
        ELSE {value.name.value = 'ALL' THEN}
          perf_keypoints.memory_keypoints := TRUE;
          perf_keypoints.heap_keypoints := TRUE;
          perf_keypoints.swapping_keypoints := TRUE;
          perf_keypoints.aging_keypoints := TRUE;
          perf_keypoints.swapping_stack_trace := TRUE;
          perf_keypoints.aging_stack_trace := TRUE;
          perf_keypoints.disk_cache := TRUE;
          perf_keypoints.command_keypoints := TRUE;
        IFEND;
      FOREND;

      osp$reserve_keypoint_env (environment, mm, jm, pva_array, wait, mpo, keypoint_count,
            keypoint_buffer_size, str, perf_keypoints, status);
      IF NOT status.normal THEN
        EXIT /files_open/;
      IFEND;
      FOR i := 1 TO number_of_files DO
        pva [i] := pva_array^ [i];
        fid [i] := fid_array^ [i];
      FOREND;
      osp$collection_file_info (number_of_files, fid, pva, status);
    END /files_open/;

    IF NOT status.normal THEN
      FOR i := 1 TO number_of_files DO
        fsp$close_file (fid_array^ [i], ls);
        IF NOT ls.normal THEN
          osp$generate_message (ls, ls);
        IFEND;
      FOREND;
    IFEND;

  PROCEND clp$reserve_keypoint_env;
?? TITLE := 'check_collection_file_location', EJECT ??
{
{ Make sure the collection_file is not a served file.  The file server
{ is not prepared to handle the io requests issued for keypoint collection.
{

  PROCEDURE check_collection_file_location
    (    file: fst$file_reference;
     VAR status: ost$status);

    VAR
      evaluated_file_reference: fst$evaluated_file_reference,
      family_name: ost$family_name,
      family_ptr: ^fst$path_element_string,
      file_server_family: boolean,
      local_file: amt$local_file_name,
      p_queue_interface_table: dft$p_queue_interface_table,
      queue_index: dft$queue_index,
      served_family_table_index: dft$served_family_table_index,
      server_mainframe_id: pmt$binary_mainframe_id,
      server_state: dft$server_state;

    status.normal := TRUE;
    clp$convert_str_to_path_handle (file, FALSE, FALSE, TRUE, local_file, evaluated_file_reference, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    family_ptr := fsp$path_element (^evaluated_file_reference, 1);
    family_name := family_ptr^;

    dfp$locate_served_family (family_name, file_server_family, served_family_table_index, server_mainframe_id,
          p_queue_interface_table, queue_index, server_state);
    IF file_server_family THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$unimplemented_server_call,
            ' RESERVE_KEYPOINT_ENVIRONMENT CF=SERVER_FILE', status);
      RETURN;
    IFEND;

  PROCEND check_collection_file_location;

?? TITLE := 'clp$release_keypoint_env', EJECT ??

  PROCEDURE [XDCL] clp$release_keypoint_env
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      ls: ost$status,
      i,
      num_of_files: 0 .. 0ff(16),
      file_id_array: array [1 .. osc$max_number_of_processors] of amt$file_identifier,
      pva_array: array [1 .. osc$max_number_of_processors] of ^cell,
      segp: amt$segment_pointer,
      str: string (32),
      value: clt$value;

    clp$scan_parameter_list (parameter_list, status_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('DATA_STRING', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    str := value.str.value (1, value.str.size);

    num_of_files := osc$max_number_of_processors;
    osp$fetch_collection_file_info (pva_array, file_id_array, num_of_files);

    osp$release_keypoint_env (pva_array, str, status);

    FOR i := 1 TO num_of_files DO
      fsp$close_file (file_id_array [i], ls);
      IF NOT ls.normal THEN
        osp$generate_message (ls, ls);
      IFEND;
    FOREND;

  PROCEND clp$release_keypoint_env;
?? TITLE := 'clp$stop_keypoint_collection', EJECT ??

  PROCEDURE [XDCL] clp$stop_keypoint_collection
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      str: string (32),
      value: clt$value;

    clp$scan_parameter_list (parameter_list, status_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('DATA_STRING', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    str := value.str.value (1, value.str.size);

    osp$stop_keypoint_collection (str, status);

  PROCEND clp$stop_keypoint_collection;
?? TITLE := 'clp$start_keypoint_collection', EJECT ??

  PROCEDURE [XDCL] clp$start_keypoint_collection
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      str: string (32),
      value: clt$value;

    clp$scan_parameter_list (parameter_list, status_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('DATA_STRING', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    str := value.str.value (1, value.str.size);

    osp$start_keypoint_collection (str, status);

  PROCEND clp$start_keypoint_collection;
?? TITLE := 'clp$issue_string_as_keypoint', EJECT ??

  PROCEDURE [XDCL] clp$issue_string_as_keypoint
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{  PDT isssak_pdt (
{    data_string, ds: string 1 .. 32
{    status)

?? PUSH (LISTEXT := ON) ??

    VAR
      isssak_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^isssak_pdt_names, ^isssak_pdt_params];

    VAR
      isssak_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
            clt$parameter_name_descriptor := [['DATA_STRING', 1], ['DS', 1], ['STATUS', 2]];

    VAR
      isssak_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 2] of clt$parameter_descriptor := [

{ DATA_STRING DS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$string_value, 1, 32]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

?? POP ??

    VAR
      value: clt$value;

    clp$scan_parameter_list (parameter_list, isssak_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('DS', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$issue_string_as_keypoint (value.str.value (1, 32), status);

  PROCEND clp$issue_string_as_keypoint;
?? TITLE := 'clp$display_keypoint_env', EJECT ??

  PROCEDURE [XDCL] clp$display_keypoint_env
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    CONST
      max_attr_size = 31;

{  PDT diske_pdt (
{     output, o: file = OUTPUT
{     status)

?? PUSH (LISTEXT := ON) ??

    VAR
      diske_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^diske_pdt_names, ^diske_pdt_params];

    VAR
      diske_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
            clt$parameter_name_descriptor := [['OUTPUT', 1], ['O', 1], ['STATUS', 2]];

    VAR
      diske_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 2] of clt$parameter_descriptor := [

{ OUTPUT O }
      [[clc$optional_with_default, ^diske_pdt_dv1], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$file_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

    VAR
      diske_pdt_dv1: [STATIC, READ, cls$pdt_names_and_defaults] string (6) := 'OUTPUT';

?? POP ??
*copyc clv$display_variables

    VAR
      display_control: clt$display_control,
      value: clt$value,
      va: array [1 .. 16] of string (osc$max_name_size),
      ignore_status: ost$status,
      kc: ost$keypoint_control,
      perf_keypoints: syt$perf_keypoints_enabled,
      str: string (132),
      strl,
      vc,
      i,
      j: integer;

?? NEWTITLE := 'abort_handler', EJECT ??

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

      VAR
        ignore_status: ost$status;

      clp$close_display (display_control, ignore_status);

    PROCEND abort_handler;
*copyc clp$new_page_procedure
?? TITLE := 'put_subtitle', EJECT ??

    PROCEDURE put_subtitle
      (VAR display_control: clt$display_control;
       VAR status: ost$status);

    PROCEND put_subtitle;
?? TITLE := 'put_attribute', EJECT ??

    PROCEDURE put_attribute
      (    header: string ( * );
           value: string ( * ));

      VAR
        start_option: amt$term_option,
        edited_header: string (tab_over);

      CONST
        tab_over = max_attr_size + 3;

      status.normal := TRUE;
      start_option := amc$start;
      edited_header := header;
      edited_header (tab_over - 1) := ':';

      clp$put_partial_display (display_control, edited_header, clc$no_trim, start_option, status);
      IF NOT status.normal THEN
        EXIT clp$display_keypoint_env
      IFEND;
      clp$put_partial_display (display_control, value, clc$trim, amc$terminate, status);
      IF NOT status.normal THEN
        EXIT clp$display_keypoint_env
      IFEND;

    PROCEND put_attribute;
?? TITLE := 'put_attribute_list', EJECT ??

    PROCEDURE put_attribute_list
      (    header: string ( * );
           value_count: integer;
           value: array [ * ] of string (osc$max_name_size));

      VAR
        start_option: amt$term_option,
        edited_header: string (tab_over),
        value_index: integer;

      CONST
        tab_over = max_attr_size + 4;

      status.normal := TRUE;
      start_option := amc$start;
      edited_header := header;
      edited_header (tab_over) := '(';
      edited_header (tab_over - 2) := ':';

      clp$put_partial_display (display_control, edited_header, clc$no_trim, start_option, status);
      IF NOT status.normal THEN
        EXIT clp$display_keypoint_env
      IFEND;

      FOR value_index := 1 TO value_count DO
        IF (display_control.column_number + clp$trimmed_string_size (value [value_index]) + 2) >
              clv$page_width THEN
          clp$new_display_line (display_control, clc$next_display_line, status);
          IF NOT status.normal THEN
            EXIT clp$display_keypoint_env
          IFEND;
          clp$horizontal_tab_display (display_control, tab_over, status);
          IF NOT status.normal THEN
            EXIT clp$display_keypoint_env
          IFEND;
        IFEND;
        clp$put_partial_display (display_control, value [value_index], clc$trim, amc$continue, status);
        IF NOT status.normal THEN
          EXIT clp$display_keypoint_env
        IFEND;
        IF value_index = value_count THEN
          clp$put_partial_display (display_control, ')', clc$no_trim, amc$terminate, status);
          IF NOT status.normal THEN
            EXIT clp$display_keypoint_env
          IFEND;
        ELSE
          clp$put_partial_display (display_control, ', ', clc$no_trim, amc$continue, status);
          IF NOT status.normal THEN
            EXIT clp$display_keypoint_env
          IFEND;
        IFEND;
      FOREND;

    PROCEND put_attribute_list;
?? OLDTITLE ??
?? EJECT ??

    clp$scan_parameter_list (parameter_list, diske_pdt, status);
    IF NOT status.normal THEN
      RETURN
    IFEND;

    clp$get_value ('OUTPUT', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$display_keypoint_status (kc, perf_keypoints, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    display_control := clv$nil_display_control;
    #SPOIL (display_control);
    osp$establish_block_exit_hndlr (^abort_handler);

    clp$open_display (value.file, ^clp$new_page_procedure, display_control, status);
    IF NOT status.normal THEN
      osp$disestablish_cond_handler;
      RETURN
    IFEND;
    clv$titles_built := FALSE;
    clv$subtitles_built := FALSE;
    clv$command_name := 'display_keypoint_environment';

    IF display_control.page_width < clc$narrow_page_width THEN
      clv$page_width := clc$narrow_page_width;
    ELSEIF display_control.page_width > clc$wide_page_width THEN
      clv$page_width := clc$wide_page_width;
    ELSE
      clv$page_width := display_control.page_width;
    IFEND;

    vc := 0;
    FOR i := 0 TO 15 DO
      IF i IN kc.envmm THEN
        vc := vc + 1;
        va [vc] := '   ';
        STRINGREP (va [vc], strl, i);
      IFEND;
    FOREND;
    put_attribute_list ('monitor mask', vc, va);

    vc := 0;
    FOR i := 0 TO 15 DO
      IF i IN kc.envjm THEN
        vc := vc + 1;
        va [vc] := '   ';
        STRINGREP (va [vc], strl, i);
      IFEND;
    FOREND;
    put_attribute_list ('job mask', vc, va);

    CASE kc.environment OF
    = osc$job_keypoints =
      put_attribute ('environment', 'job');
    = osc$system_keypoints =
      put_attribute ('environment', 'system');
    = osc$job_sample_keypoints =
      put_attribute ('environment', 'job sample');
    = osc$system_sample_keypoints =
      put_attribute ('environment', 'system sample');
    CASEND;

    CASE kc.mpo OF
    = osc$keypoints_single_processor =
      put_attribute ('multiprocessor', 'single');
    = osc$keypoints_multi_processor =
      put_attribute ('multiprocessor', 'all');
    CASEND;

    STRINGREP (str, strl, kc.max_pages DIV 4);
    put_attribute ('keypoint buffer size', str (1, strl));

    STRINGREP (str, strl, kc.maximum_keypoints);
    put_attribute ('keypoint count', str (1, strl));

    IF kc.active THEN
      put_attribute ('collection status', 'started');
    ELSE
      put_attribute ('collection status', 'stopped');
    IFEND;

    IF kc.termination_status <> osc$kp_term_not_stopped THEN
      IF kc.termination_status = ose$kpt_coll_term_io_error THEN
        put_attribute ('termination status', 'i/o error');
      ELSEIF kc.termination_status = ose$kpt_coll_term_mbs_error THEN
        put_attribute ('termination status', 'buffer overflow');
      ELSEIF kc.termination_status = ose$kpt_coll_term_max_kpts THEN
        put_attribute ('termination status', 'keypoint count exceeded');
      ELSE
        STRINGREP (str, strl, kc.termination_status);
        put_attribute ('termination status', str (1, strl));
      IFEND;
    IFEND;

    FOR i := kc.first_active_processor TO kc.last_active_processor DO
      STRINGREP (str, strl, kc.cpus [i].offset DIV 8);
      put_attribute ('keypoints collected', str (1, strl));
    FOREND;

    IF perf_keypoints.memory_keypoints THEN
      put_attribute ('memory keypoints', 'enabled');
    IFEND;
    IF perf_keypoints.heap_keypoints THEN
      put_attribute ('heap keypoints', 'enabled');
    IFEND;
    IF perf_keypoints.swapping_keypoints THEN
      put_attribute ('swapping keypoints', 'enabled');
    IFEND;
    IF perf_keypoints.aging_keypoints THEN
      put_attribute ('aging keypoints', 'enabled');
    IFEND;
    IF perf_keypoints.swapping_stack_trace THEN
      put_attribute ('swapping stack trace', 'enabled');
    IFEND;
    IF perf_keypoints.aging_stack_trace THEN
      put_attribute ('aging stack_trace', 'enabled');
    IFEND;
    IF perf_keypoints.disk_cache THEN
      put_attribute ('disk cache keypoints', 'enabled');
    IFEND;
    IF perf_keypoints.command_keypoints THEN
      put_attribute ('command keypoints', 'enabled');
    IFEND;

    clp$close_display (display_control, ignore_status);

    osp$disestablish_cond_handler;

  PROCEND clp$display_keypoint_env;
?? TITLE := 'clp$test_keypoint_collection', EJECT ??

  PROCEDURE [XDCL] clp$test_keypoint_collection
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PDT test_pdt (
{       n: integer
{       status)

?? PUSH (LISTEXT := ON) ??

    VAR
      test_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^test_pdt_names, ^test_pdt_params];

    VAR
      test_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 2] of
            clt$parameter_name_descriptor := [['N', 1], ['STATUS', 2]];

    VAR
      test_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 2] of clt$parameter_descriptor := [

{ N }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$integer_value, clc$min_integer, clc$max_integer]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

?? POP ??

    VAR
      n,
      i: integer,
      value: clt$value;

    clp$scan_parameter_list (parameter_list, test_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('N', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    n := value.int.value;
    FOR i := 0 TO (n - 1) DO
      #KEYPOINT (13, i, 77);
    FOREND;

  PROCEND clp$test_keypoint_collection;
?? TITLE := 'clp$display_keypoint_file', EJECT ??

  PROCEDURE [XDCL] clp$display_keypoint_file
    (    pl: clt$parameter_list;
     VAR status: ost$status);

{ PDT diskf_pdt (
{   keypoint_file, kf: file = $required
{   display_option, do: key full, brief = brief
{   output, o: file = OUTPUT
{   status)

?? PUSH (LISTEXT := ON) ??

    VAR
      diskf_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^diskf_pdt_names, ^diskf_pdt_params];

    VAR
      diskf_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 7] of
            clt$parameter_name_descriptor := [['KEYPOINT_FILE', 1], ['KF', 1], ['DISPLAY_OPTION', 2],
            ['DO', 2], ['OUTPUT', 3], ['O', 3], ['STATUS', 4]];

    VAR
      diskf_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 4] of clt$parameter_descriptor := [

{ KEYPOINT_FILE KF }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$file_value]],

{ DISPLAY_OPTION DO }
      [[clc$optional_with_default, ^diskf_pdt_dv2], 1, 1, 1, 1, clc$value_range_not_allowed,
            [^diskf_pdt_kv2, clc$keyword_value]],

{ OUTPUT O }
      [[clc$optional_with_default, ^diskf_pdt_dv3], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$file_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

    VAR
      diskf_pdt_kv2: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 2] of
            ost$name := ['FULL', 'BRIEF'];

    VAR
      diskf_pdt_dv2: [STATIC, READ, cls$pdt_names_and_defaults] string (5) := 'brief';

    VAR
      diskf_pdt_dv3: [STATIC, READ, cls$pdt_names_and_defaults] string (6) := 'OUTPUT';

?? POP ??

    VAR
      as: [STATIC, READ, oss$job_paged_literal] array [1 .. 3] of fst$attachment_option := [
            {} [fsc$access_and_share_modes, {} [fsc$specific_access_modes, [fsc$read]],
            {} [fsc$specific_share_modes, [fsc$read, fsc$execute]]],
            {} [fsc$open_share_modes, [fsc$read, fsc$execute]],
            {} [fsc$create_file, FALSE]],
      as2: [STATIC, READ, oss$job_paged_literal] array [1 .. 2] of fst$attachment_option := [
            {} [fsc$access_and_share_modes, {} [fsc$specific_access_modes,
            [fsc$append, fsc$shorten, fsc$modify]], {} [fsc$specific_share_modes, []]],
            {} [fsc$open_share_modes, [fsc$read, fsc$shorten, fsc$append, fsc$modify, fsc$execute]]],
      value: clt$value,
      segp: amt$segment_pointer,
      seqp: ^SEQ ( * ),
      pcl15kp: ^ost$class_15_keypoint,
      pkp: ^ost$keypoint,
      class: array [0 .. 15] of integer,
      class_error,
      junkl,
      strl,
      i: integer,
      date: ost$date,
      time: ost$time,
      name: string (15),
      str: string (132),
      pjunk: ^array [1 .. * ] of cell,
      display_option: (full, brief),
      ls: ost$status,
      ba: amt$file_byte_address,
      kp_fid,
      output_fid: amt$file_identifier;

?? EJECT ??

    PROCEDURE abort_handler
      (    cond: pmt$condition;
           ci: ^pmt$condition_information;
           sa: ^ost$stack_frame_save_area;
       VAR hs: ost$status);

      fsp$close_file (kp_fid, hs);
      fsp$close_file (output_fid, hs);
      hs.normal := TRUE;

    PROCEND abort_handler;
?? EJECT ??

    clp$scan_parameter_list (pl, diskf_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('DO', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF value.name.value = 'FULL' THEN
      display_option := full;
    ELSE
      display_option := brief;
    IFEND;

    class_error := 0;
    FOR i := 0 TO 15 DO
      class [i] := 0;
    FOREND;

    kp_fid := amv$nil_file_identifier;
    #SPOIL (kp_fid);
    output_fid := amv$nil_file_identifier;
    #SPOIL (output_fid);
    osp$establish_block_exit_hndlr (^abort_handler);

  /files_open/
    BEGIN
      clp$get_value ('KEYPOINT_FILE', 1, 1, clc$low, value, status);
      IF NOT status.normal THEN
        EXIT /files_open/;
      IFEND;
      fsp$open_file (value.file.local_file_name, amc$segment, ^as, NIL, NIL, NIL, NIL, kp_fid, status);
      IF NOT status.normal THEN
        EXIT /files_open/;
      IFEND;
      amp$get_segment_pointer (kp_fid, amc$sequence_pointer, segp, status);
      IF NOT status.normal THEN
        EXIT /files_open/;
      IFEND;

      clp$get_value ('OUTPUT', 1, 1, clc$low, value, status);
      IF NOT status.normal THEN
        EXIT /files_open/;
      IFEND;
      fsp$open_file (value.file.local_file_name, amc$record, ^as2, NIL, NIL, NIL, NIL, output_fid, status);
      IF NOT status.normal THEN
        EXIT /files_open/;
      IFEND;

      junkl := 8 - (#SIZE (ost$class_15_keypoint) MOD 8);
      IF junkl = 8 THEN
        junkl := 0;
      IFEND;

      seqp := segp.sequence_pointer;
      RESET seqp;
      NEXT pkp IN seqp;

    /kpts/
      WHILE pkp <> NIL DO
        IF pkp^.keypoint_class <= 15 THEN
          class [pkp^.keypoint_class] := class [pkp^.keypoint_class] + 1;
        ELSE
          class_error := class_error + 1;
        IFEND;
        IF pkp^.keypoint_class = 15 THEN
          RESET seqp TO pkp;
          NEXT pcl15kp IN seqp;
          IF pcl15kp = NIL THEN
            EXIT /kpts/;
          IFEND;
          IF junkl <> 0 THEN
{ skip to next kpt
            NEXT pjunk: [1 .. junkl] IN seqp;
          IFEND;
        IFEND;
        IF display_option = full THEN
          IF pkp^.keypoint_class = 15 THEN
            CASE pcl15kp^.keypoint.keypoint_code OF
            = osc$keypoint_cl15_reserve =
              name := 'Reserve';
            = osc$keypoint_cl15_release =
              name := 'Release';
            = osc$keypoint_cl15_start =
              name := 'Start';
            = osc$keypoint_cl15_stop =
              name := 'Stop';
            = osc$keypoint_cl15_issue =
              name := 'Issue';
            ELSE
              name := 'Unknown';
            CASEND;
            pmp$format_compact_time (pcl15kp^.date_time, osc$millisecond_time, time, status);
            pmp$format_compact_date (pcl15kp^.date_time, osc$mdy_date, date, status);
            STRINGREP (str, strl, '  ', name, pcl15kp^.keypoint.keypoint_class: 4, '       ',
                  pcl15kp^.keypoint.keypoint_code: 8, ' ', pcl15kp^.user_data, ' ',
                  pcl15kp^.microsecond_clock, ' ', date.mdy, ' ', time.hms);
          ELSE
            STRINGREP (str, strl, '  ', pkp^.clock: 15, pkp^.keypoint_class: 4, pkp^.keypoint_data: 7: #(16),
                  pkp^.keypoint_code: 8);
          IFEND;
          amp$put_next (output_fid, #LOC (str), strl, ba, status);
        IFEND;
        NEXT pkp IN seqp;
      WHILEND /kpts/;
      IF class_error > 0 THEN
        STRINGREP (str, strl, ' class errors: ', class_error);
        amp$put_next (output_fid, #LOC (str), strl, ba, status);
      IFEND;
      FOR i := 0 TO 15 DO
        STRINGREP (str, strl, ' class: ', i: 4, ' count: ', class [i]);
        amp$put_next (output_fid, #LOC (str), strl, ba, status);
      FOREND;
    END /files_open/;
    fsp$close_file (kp_fid, ls);
    fsp$close_file (output_fid, ls);
    osp$disestablish_cond_handler;

  PROCEND clp$display_keypoint_file;
?? TITLE := 'clp$keypoint', EJECT ??

  PROCEDURE [XDCL] clp$keypoint
    (    keypoint_class: 0 .. 15;
         keypoint_code: 0 .. 0ffffffff(16));

{
{   The purpose of this procedure is to issue a keypoint instruction with
{  the specified keypoint class and keypoint code.
{
{        CLP$KEYPOINT (KEYPOINT_CLASS, KEYPOINT_CODE)
{
{  KEYPOINT_CLASS: (input) This parameter specifies the keypoint class.
{
{  KEYPOINT_CODE: (output) This parameter specifies the keypoint code.
{

    CASE keypoint_class OF
    = 0 =
      #KEYPOINT (0, keypoint_code, 0);
    = 1 =
      #KEYPOINT (1, keypoint_code, 0);
    = 2 =
      #KEYPOINT (2, keypoint_code, 0);
    = 3 =
      #KEYPOINT (3, keypoint_code, 0);
    = 4 =
      #KEYPOINT (4, keypoint_code, 0);
    = 5 =
      #KEYPOINT (5, keypoint_code, 0);
    = 6 =
      #KEYPOINT (6, keypoint_code, 0);
    = 7 =
      #KEYPOINT (7, keypoint_code, 0);
    = 8 =
      #KEYPOINT (8, keypoint_code, 0);
    = 9 =
      #KEYPOINT (9, keypoint_code, 0);
    = 10 =
      #KEYPOINT (10, keypoint_code, 0);
    = 11 =
      #KEYPOINT (11, keypoint_code, 0);
    = 12 =
      #KEYPOINT (12, keypoint_code, 0);
    = 13 =
      #KEYPOINT (13, keypoint_code, 0);
    = 14 =
      #KEYPOINT (14, keypoint_code, 0);
    = 15 =
      #KEYPOINT (15, keypoint_code, 0);
    CASEND;

  PROCEND clp$keypoint;
MODEND clm$keypoint_commands;
