?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE System Message Generator' ??
MODULE osm$system_message_generator;
?? RIGHT := 110 ??

{
{ PURPOSE:
{   This module contains the procedure responsible for processing the ost$status record
{   for human consumption.  This involves locating a message_module_dictionary entry corresponding
{   to a status condition code or status condition name and either formatting a message or
{   retrieving the condition's severity level, name, or code.

?? NEWTITLE := 'Global Declarations Referenced This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc oss$task_shared
*copyc clc$standard_file_names
*copyc osc$compression_identifier
*copyc cyd$run_time_error_condition
*copyc lle$load_map_diagnostics
*copyc fst$path
*copyc ost$caller_identifier
*copyc ost$get_message_part
*copyc ost$max_status_message_line
*copyc ost$message_parameters
*copyc ost$message_template_module
*copyc ost$status
*copyc ost$status_identifier
*copyc ost$status_message
*copyc ost$status_message_header_kind
*copyc ost$status_message_level
*copyc ost$status_message_line
*copyc ost$status_message_line_count
*copyc ost$status_message_line_size
*copyc ost$status_severity
?? POP ??
*copyc amp$fetch
*copyc amp$put_next
*copyc clp$convert_integer_to_string
*copyc clp$evaluate_unsigned_decimal
*copyc clp$extract_msg_module_contents
*copyc clp$find_command_list
*copyc clp$get_path_name
*copyc clp$get_system_file_id
*copyc clp$get_system_message_mod_ptr
*copyc clp$put_display
*copyc clp$put_error_output
*copyc clp$put_job_command_response
*copyc clp$put_job_output
*copyc clp$search_module_for_code
*copyc clp$search_msg_library_via_code
*copyc clp$search_msg_library_via_name
*copyc clp$trimmed_string_size
*copyc osp$convert_to_diagnos_severity
*copyc osp$convert_to_status_severity
*copyc osp$enforce_exception_policies
*copyc osp$establish_condition_handler
*copyc osp$expand_file_reference
*copyc osp$file_access_condition
*copyc osp$find_status_message_level
*copyc osp$set_status_from_condition
*copyc osp$status_condition_code
*copyc osp$unpack_status_condition
*copyc osp$unpack_status_identifier
*copyc osp$verify_system_privilege
*copyc pmp$continue_to_cause
*copyc pmp$load
*copyc pmp$log_ascii
*copyc osv$initial_exception_context
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Decalred by This Module', EJECT ??

  CONST
    osc$parameter_delimiter_limit = osc$max_string_size;

  TYPE
    ost$status_text = string ( * <= osc$max_string_size);

  TYPE
    t$output_procedure = ^procedure (    text: string ( * );
                                     VAR status: ost$status);

  VAR
    osv$severities: [XDCL, READ, oss$job_paged_literal] array [ost$status_severity] of record
      size: 5 .. 12,
      value: string (12),
    recend := [[11, 'INFORMATIVE'], [7, 'WARNING'], [5, 'ERROR'], [5, 'FATAL'], [12, 'CATASTROPHIC']];

  VAR
    subdued_severities: [STATIC, READ, oss$job_paged_literal] array [ost$status_severity] of record
      size: 5 .. 18,
      value: string (18),
    recend := [[11, 'Informative'], [7, 'Warning'], [5, 'Error'], [11, 'Fatal error'], [18,
          'Catastrophic error']];

  VAR
    default_template: [STATIC, READ, oss$job_paged_literal] string (19) := 'CC=+C TEXT=+T';

?? NEWTITLE := '[inline] P$GET_PAGE_WIDTH', EJECT ??

  PROCEDURE [INLINE] p$get_page_width
    (    local_file_name: amt$local_file_name;
     VAR page_width: amt$page_width);

    VAR
      file_attributes: array [1 .. 1] of amt$fetch_item,
      file_id: amt$file_identifier,
      status: ost$status;

    clp$get_system_file_id (local_file_name, file_id, status);
    IF status.normal THEN
      file_attributes [1].key := amc$page_width;
      amp$fetch (file_id, file_attributes, status);
    IFEND;

    IF (NOT status.normal) OR (file_attributes [1].page_width < osc$min_status_message_line) THEN
      page_width := osc$min_status_message_line;
    ELSEIF file_attributes [1].page_width > osc$max_status_message_line THEN
      page_width := osc$max_status_message_line;
    ELSE
      page_width := file_attributes [1].page_width;
    IFEND;

  PROCEND p$get_page_width;
?? OLDTITLE ??
?? TITLE := 'get_template_info_via_code', EJECT ??

  PROCEDURE get_template_info_via_code
    (    code: ost$status_condition_code;
         search_by_language: boolean;
     VAR name: ost$status_condition_name;
     VAR severity: ost$message_module_severity;
     VAR template: ^ost$message_template;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      current_entry: ^clt$command_list_entry,
      entry_found: boolean,
      i: integer,
      ignore_cmnd_list_found_in_task: boolean,
      local_library_name: amt$local_file_name,
      saved_default: boolean,
      search_cache: boolean,
      system_message_library_searched: boolean;

?? TITLE := 'search_msg_library_via_code', EJECT ??

    PROCEDURE [INLINE] search_msg_library_via_code;

      VAR
        context: ^ost$ecp_exception_context;

      context := NIL;

      REPEAT
        clp$search_msg_library_via_code (caller_id.ring, code, search_by_language, search_cache,
              local_library_name, name, severity, template, entry_found, saved_default, status);
        IF osp$file_access_condition (status) THEN
          IF context = NIL THEN
            PUSH context;
            context^ := osv$initial_exception_context;
            context^.file.selector := osc$ecp_file_reference;
            context^.file.file_reference := ^local_library_name;
          IFEND;
          context^.condition_status := status;
          osp$enforce_exception_policies (context^);
          status := context^.condition_status;
        IFEND;
      UNTIL status.normal OR (NOT osp$file_access_condition (status)) OR (NOT context^.wait);

    PROCEND search_msg_library_via_code;
?? OLDTITLE ??
?? EJECT ??
    status.normal := TRUE;
    #CALLER_ID (caller_id);
    severity := osc$mm_error_severity;
    template := NIL;
    name := 'UNKNOWN_CONDITION';
    search_cache := TRUE;
    saved_default := FALSE;
    entry_found := FALSE;
    system_message_library_searched := FALSE;

    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    current_entry := command_list^.entries.first_entry;

    WHILE current_entry <> NIL DO
      CASE current_entry^.kind OF

      = clc$library_commands =
        IF current_entry^.library_contains.message_modules AND NOT current_entry^.unaccessible_entry THEN
          local_library_name := current_entry^.local_file_name;
          search_msg_library_via_code;
          search_cache := FALSE;
          status.normal := TRUE {ignore bad status from search} ;
        IFEND;

      = clc$system_commands =
        IF (command_list^.system_command_library_lfn <> osc$null_name) AND
              command_list^.system_library_contains.message_modules THEN
          local_library_name := command_list^.system_command_library_lfn;
          search_msg_library_via_code;
          search_cache := FALSE;
          status.normal := TRUE {ignore bad status from search} ;
        IFEND;
        IF NOT entry_found THEN
          local_library_name := osc$null_name;
          search_msg_library_via_code;
          search_cache := FALSE;
          status.normal := TRUE {ignore bad status from search} ;
        IFEND;
        system_message_library_searched := TRUE;

      = clc$sub_commands =
        IF current_entry^.utility_info^.auxiliary_libraries <> NIL THEN
          FOR i := 1 TO UPPERBOUND (current_entry^.utility_info^.auxiliary_libraries^) DO
            IF current_entry^.utility_info^.auxiliary_libraries^ [i].contains.message_modules THEN
              local_library_name := current_entry^.utility_info^.auxiliary_libraries^ [i].name;
              search_msg_library_via_code;
              search_cache := FALSE;
              status.normal := TRUE {ignore bad status from search} ;
              IF entry_found THEN
                RETURN; {----->
              IFEND;
            IFEND;
          FOREND;
        IFEND;

      ELSE
        ;
      CASEND;

      IF entry_found THEN
        RETURN; {----->
      IFEND;
      current_entry := current_entry^.next_entry;
    WHILEND;

    IF NOT system_message_library_searched THEN
      IF (command_list^.system_command_library_lfn <> osc$null_name) AND
            command_list^.system_library_contains.message_modules THEN
        local_library_name := command_list^.system_command_library_lfn;
        search_msg_library_via_code;
        status.normal := TRUE {ignore bad status from search} ;
      IFEND;
      IF NOT entry_found THEN
        local_library_name := osc$null_name;
        search_msg_library_via_code;
        status.normal := TRUE {ignore bad status from search} ;
      IFEND;
    IFEND;

  PROCEND get_template_info_via_code;
?? TITLE := 'get_template_info_via_name', EJECT ??

  PROCEDURE get_template_info_via_name
    (    name: ost$status_condition_name;
         search_by_language: boolean;
     VAR code: ost$status_condition_code;
     VAR severity: ost$message_module_severity;
     VAR template: ^ost$message_template;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      command_list: ^clt$command_list,
      current_entry: ^clt$command_list_entry,
      entry_found: boolean,
      i: integer,
      ignore_cmnd_list_found_in_task: boolean,
      local_library_name: amt$local_file_name,
      saved_default: boolean,
      search_cache: boolean,
      system_message_library_searched: boolean;

?? TITLE := 'search_msg_library_via_name', EJECT ??

    PROCEDURE [INLINE] search_msg_library_via_name;

      VAR
        context: ^ost$ecp_exception_context;

      context := NIL;

      REPEAT
        clp$search_msg_library_via_name (caller_id.ring, name, search_by_language, search_cache,
              local_library_name, code, severity, template, entry_found, saved_default, status);
        IF osp$file_access_condition (status) THEN
          IF context = NIL THEN
            PUSH context;
            context^ := osv$initial_exception_context;
            context^.file.selector := osc$ecp_file_reference;
            context^.file.file_reference := ^local_library_name;
          IFEND;
          context^.condition_status := status;
          osp$enforce_exception_policies (context^);
          status := context^.condition_status;
        IFEND;
      UNTIL status.normal OR (NOT osp$file_access_condition (status)) OR (NOT context^.wait);

    PROCEND search_msg_library_via_name;
?? OLDTITLE ??
?? EJECT ??

    status.normal := TRUE;
    #CALLER_ID (caller_id);
    system_message_library_searched := FALSE;
    search_cache := TRUE;
    saved_default := FALSE;
    entry_found := FALSE;
    code := 0;
    severity := osc$mm_error_severity;
    template := NIL;

    clp$find_command_list (command_list, ignore_cmnd_list_found_in_task);
    current_entry := command_list^.entries.first_entry;

    WHILE current_entry <> NIL DO
      CASE current_entry^.kind OF

      = clc$library_commands =
        IF current_entry^.library_contains.message_modules AND NOT current_entry^.unaccessible_entry THEN
          local_library_name := current_entry^.local_file_name;
          search_msg_library_via_name;
          search_cache := FALSE;
          status.normal := TRUE {ignore bad status from search} ;
        IFEND;

      = clc$system_commands =
        IF (command_list^.system_command_library_lfn <> osc$null_name) AND
              command_list^.system_library_contains.message_modules THEN
          local_library_name := command_list^.system_command_library_lfn;
          search_msg_library_via_name;
          status.normal := TRUE {ignore bad status from search} ;
        IFEND;
        IF NOT entry_found THEN
          local_library_name := osc$null_name;
          search_msg_library_via_name;
          search_cache := FALSE;
          status.normal := TRUE {ignore bad status from search} ;
        IFEND;
        system_message_library_searched := TRUE;

      = clc$sub_commands =
        IF current_entry^.utility_info^.auxiliary_libraries <> NIL THEN
          FOR i := 1 TO UPPERBOUND (current_entry^.utility_info^.auxiliary_libraries^) DO
            IF current_entry^.utility_info^.auxiliary_libraries^ [i].contains.message_modules THEN
              local_library_name := current_entry^.utility_info^.auxiliary_libraries^ [i].name;
              search_msg_library_via_name;
              search_cache := FALSE;
              status.normal := TRUE {ignore bad status from search} ;
              IF entry_found THEN
                RETURN; {----->
              IFEND;
            IFEND;
          FOREND;
        IFEND;

      ELSE
        ;
      CASEND;

      IF entry_found THEN
        RETURN; {----->
      IFEND;
      current_entry := current_entry^.next_entry;
    WHILEND;

    IF NOT system_message_library_searched THEN
      IF (command_list^.system_command_library_lfn <> osc$null_name) AND
            command_list^.system_library_contains.message_modules THEN
        local_library_name := command_list^.system_command_library_lfn;
        search_msg_library_via_name;
        status.normal := TRUE {ignore bad status from search} ;
      IFEND;
      IF NOT entry_found THEN
        local_library_name := osc$null_name;
        status.normal := TRUE {ignore bad status from search} ;
        search_msg_library_via_name;
      IFEND;
    IFEND;

  PROCEND get_template_info_via_name;
?? TITLE := 'osp$format_multi_part_message', EJECT ??
*copy osh$format_multi_part_message

  PROCEDURE [XDCL, #GATE] osp$format_multi_part_message
    (    message_level: ost$format_message_level;
         message_header_kind: ost$status_message_header_kind;
         max_message_line: ost$status_message_line_size;
         status_condition: ost$status_condition;
         message_parameters: ^ost$message_parameters;
         get_message_part: ost$get_message_part;
     VAR message: SEQ ( * );
     VAR status: ost$status);

    VAR
      condition_name: ost$status_condition_name,
      message_module_severity: ost$message_module_severity,
      message_template: ^ost$message_template,
      status_identifier: ost$status_identifier,
      status_severity: ost$status_severity,
      template: ^ost$message_template,
      actual_message_level: ost$status_message_level,
      current_message_level: ^ost$status_message_level;

    status.normal := TRUE;
    IF message_level = osc$current_message_level THEN
      osp$find_status_message_level (current_message_level);
      actual_message_level := current_message_level^;
    ELSE
      actual_message_level := message_level;
    IFEND;

    get_template_info_via_code (status_condition, TRUE, condition_name, message_module_severity, template,
          status);
    IF (NOT status.normal) OR (template = NIL) OR (STRLENGTH (template^) = 0) THEN
      template := ^default_template;
    IFEND;

    status_severity := osp$convert_to_status_severity (message_module_severity);

    format_message (actual_message_level, message_header_kind, max_message_line,
          osp$status_condition_code (status_identifier, status_condition), status_severity, template,
          message_parameters, get_message_part, osc$status_parameter_delimiter, message, status);

  PROCEND osp$format_multi_part_message;
?? TITLE := 'format_message', EJECT ??

  PROCEDURE format_message
    (    message_level: ost$status_message_level;
         message_header_kind: ost$status_message_header_kind;
         max_line_size: osc$min_status_message_line - 1 .. osc$max_status_message_line - 1;
         status_condition: ost$status_condition_code,
         status_severity: ost$status_severity;
         original_template: ^ost$message_template;
         original_parameters: ^ost$message_parameters;
         get_message_part: ost$get_message_part;
         parameter_delimiter: char;
     VAR message: SEQ ( * );
     VAR status: ost$status);

    VAR
      delimiter_set: [STATIC, READ, oss$job_paged_literal] packed array [char] of boolean := [
            {---} REP 32 of FALSE,
            {' '} TRUE,
            {---} REP 11 of FALSE,
            {-,-} TRUE,
            {---} REP 211 of FALSE],
      non_delimiter_set: [STATIC, READ, oss$job_paged_literal] packed array [char] of boolean := [
            {---} REP 32 of TRUE,
            {' '} FALSE,
            {---} REP 11 of TRUE,
            {-,-} FALSE,
            {---} REP 211 of TRUE];

    VAR
      empty_string: ^string ( * ),
      indent_amount: integer,
      keep_pending: boolean,
      last_parameter: 0 .. osc$parameter_delimiter_limit,
      last_space_hard: boolean,
      line_count: ^ost$status_message_line_count,
      message_area: ^SEQ ( * ),
      message_parameters: ^ost$message_parameters,
      message_parameters_exhausted: boolean,
      next_line: string (osc$max_status_message_line),
      next_line_break_index: ost$status_message_line_size,
      next_line_secondary_break_index: ost$status_message_line_size,
      next_line_size: ost$status_message_line_size,
      template: ^ost$message_template,
      template_index: ost$message_template_index,
      soft_eol_pending: boolean;

?? NEWTITLE := 'put_standard_message_header', EJECT ??

    PROCEDURE [INLINE] put_standard_message_header;


      IF (message_level > osc$brief_message_level) OR (status_severity > osc$informative_status) OR
            (template = ^default_template) THEN
        put_string ('--');
        put_string (osv$severities [status_severity].value (1, osv$severities [status_severity].size));
        IF (message_level > osc$brief_message_level) AND (template <> ^default_template) THEN
          put_character (' ');
          osp$get_status_condition_string (status_condition, status_condition_string, status);
          IF NOT status.normal THEN
            EXIT format_message; {----->
          IFEND;
          put_string (status_condition_string.value (1, status_condition_string.size));
        IFEND;
      IFEND;
      put_string ('--  ');

    PROCEND put_standard_message_header;
?? TITLE := 'put_subdued_message_header', EJECT ??

    PROCEDURE [INLINE] put_subdued_message_header;


      IF (status_severity > osc$informative_status) OR (template = ^default_template) THEN
        put_string (subdued_severities [status_severity].value (1, subdued_severities [status_severity].
              size));
        IF (message_level > osc$brief_message_level) AND (template <> ^default_template) THEN
          put_character (' ');
          osp$get_status_condition_string (status_condition, status_condition_string, status);
          IF NOT status.normal THEN
            EXIT format_message; {----->
          IFEND;
          put_string (status_condition_string.value (1, status_condition_string.size));
        IFEND;
        put_string (': ');
      IFEND;

    PROCEND put_subdued_message_header;
?? TITLE := 'process_file_parameter', EJECT ??

    PROCEDURE [INLINE] process_file_parameter
      (    text: ost$message_parameter);

      VAR
        scan_index: 0 .. osc$max_string_size,
        scan_found_char: boolean,
        starting_position: 0 .. osc$max_string_size,
        end_position: 0 .. osc$max_string_size,
        file: fst$path;

      scan_index := 0;
      end_position := 0;
      starting_position := 0;

      WHILE ((end_position + 1) <= clp$trimmed_string_size (text)) DO
        #SCAN (non_delimiter_set, text (end_position + 1, * ), scan_index, scan_found_char);
        IF scan_found_char THEN
          IF starting_position <> 0 THEN
            put_string (', ');
          IFEND;
          starting_position := scan_index + end_position;
        ELSE
          IF (starting_position = 0) AND (starting_position <> end_position) THEN
            file := text;
            put_file_reference (file);
          IFEND;
          RETURN; {----->
        IFEND;

        #SCAN (delimiter_set, text (starting_position, * ), scan_index, scan_found_char);
        IF scan_found_char THEN
          end_position := scan_index + starting_position - 1;
          file := text (starting_position, end_position - starting_position);
          put_file_reference (file);
        ELSE
          file := text (starting_position, * );
          put_file_reference (file);
          RETURN; {----->
        IFEND;
      WHILEND;

    PROCEND process_file_parameter;
?? TITLE := 'put_file_reference', EJECT ??

    PROCEDURE [INLINE] put_file_reference
      (    file: fst$file_reference);

      VAR
        file_reference: fst$path,
        file_reference_size: fst$path_size,
        ignore_status: ost$status;

      IF (file (1) = ':') THEN
        put_string (file (1, clp$trimmed_string_size (file)));
      ELSE
        IF (file (1) = osc$compression_identifier) THEN
          osp$expand_file_reference (file, file_reference, file_reference_size, ignore_status);
        ELSE
          clp$get_path_name (file, osc$full_message_level, file_reference);
          file_reference_size := clp$trimmed_string_size (file_reference)
        IFEND;
        put_string (file_reference (1, file_reference_size));
      IFEND;

    PROCEND put_file_reference;
?? TITLE := 'put_string', EJECT ??

    PROCEDURE [INLINE] put_string
      (    s: string ( * ));

      VAR
        i: integer;


      FOR i := 1 TO STRLENGTH (s) DO
        put_character (s (i));
      FOREND;

    PROCEND put_string;
?? TITLE := 'put_character', EJECT ??

    PROCEDURE [INLINE] put_character
      (    c: char);


      IF next_line_size >= max_line_size THEN
        break_line;
      IFEND;

{ It is possible that indent_amount + extra_chars_length computed by break_line could be = max_line_size,
{ so check if the line needs to be broken again.  The check is '>=' for safety's sake.

      IF next_line_size >= max_line_size THEN
        break_line;
      IFEND;

      next_line_size := next_line_size + 1;
      CASE c OF

      = $CHAR (0) .. $CHAR (31), $CHAR (127) =
        next_line (next_line_size) := '?';
        IF NOT (soft_eol_pending OR keep_pending) THEN
          next_line_break_index := next_line_size;
        IFEND;

      = 'A' .. 'Z', 'a' .. 'z', '0' .. '9', '$', '#', '@', '[', '\', ']', '^', '`', '{', '|', '}', '~' =
        next_line (next_line_size) := c;

      = '_', '.', '(', ':' =
        next_line (next_line_size) := c;
        next_line_secondary_break_index := next_line_size;

      ELSE
        next_line (next_line_size) := c;
        IF NOT (soft_eol_pending OR keep_pending) THEN
          next_line_break_index := next_line_size;
        IFEND;

      CASEND;

    PROCEND put_character;
?? TITLE := 'break_line', EJECT ??

    PROCEDURE break_line;

      VAR
        extra_chars: string (osc$max_status_message_line),
        extra_chars_length: 0 .. osc$max_status_message_line,
        i: 1 .. osc$max_status_message_line,
        put_enabled: boolean;


      IF next_line_break_index = 0 THEN
        next_line_break_index := next_line_secondary_break_index;
      IFEND;

      IF next_line_break_index = 0 THEN
        extra_chars_length := 2;
        extra_chars := next_line (max_line_size - 1, 2);
        next_line (max_line_size - 1, 2) := '..';

      ELSEIF next_line_break_index < max_line_size THEN
        extra_chars_length := max_line_size - next_line_break_index;
        extra_chars := next_line (next_line_break_index + 1, * );
        next_line_size := next_line_break_index;

      ELSE
        extra_chars_length := 0;
      IFEND;

      flush_line;

      put_enabled := indent_amount > 0;
      FOR i := 1 TO extra_chars_length DO
        IF extra_chars (i) <> ' ' THEN
          put_enabled := TRUE;
        IFEND;
        IF put_enabled THEN
          put_character (extra_chars (i));
        IFEND;
      FOREND;

    PROCEND break_line;
?? TITLE := 'flush_line', EJECT ??

    PROCEDURE [INLINE] flush_line;

      VAR
        line: ^string ( * ),
        line_size: ^ost$status_message_line_size;


      IF NOT last_space_hard THEN
        WHILE (next_line_size > 0) AND (next_line (next_line_size) = ' ') DO
          next_line_size := next_line_size - 1;
        WHILEND;
      IFEND;

      NEXT line_size IN message_area;
      IF line_size = NIL THEN
        EXIT format_message; {----->
      IFEND;
      NEXT line: [next_line_size + 1] IN message_area;
      IF line = NIL THEN
        EXIT format_message; {----->
      IFEND;

      line_count^ := line_count^ +1;
      line_size^ := next_line_size + 1;
      line^ (1) := ' ';
      line^ (2, next_line_size) := next_line (1, next_line_size);

      IF indent_amount >= max_line_size THEN
        next_line_size := max_line_size;
      ELSE
        next_line_size := indent_amount;
      IFEND;

      soft_eol_pending := FALSE;
      next_line_break_index := 0;
      next_line_secondary_break_index := 0;
      next_line := '';

    PROCEND flush_line;
?? TITLE := 'get_parameter', EJECT ??

    PROCEDURE [INLINE] get_parameter
      (    count: integer;
       VAR parameter: ^ost$message_parameter);


      parameter := empty_string;

      IF message_parameters = NIL THEN
        message_parameters_exhausted := TRUE;
        RETURN; {----->

      ELSEIF count <= 0 THEN {get next parameter
        IF last_parameter >= UPPERBOUND (message_parameters^) THEN
          message_parameters_exhausted := TRUE;
          RETURN; {----->
        IFEND;

        last_parameter := last_parameter + 1;
        message_parameters_exhausted := last_parameter = UPPERBOUND (message_parameters^);

      ELSE {get a specific parameter
        IF count > UPPERBOUND (message_parameters^) THEN
          RETURN; {----->
        IFEND;

        last_parameter := count;
      IFEND;

      IF message_parameters^ [last_parameter] = NIL THEN
        RETURN; {----->
      IFEND;

      parameter := ^message_parameters^ [last_parameter]^ (1,
            clp$trimmed_string_size (message_parameters^ [last_parameter]^));

    PROCEND get_parameter;
?? TITLE := 'get_count', EJECT ??

    PROCEDURE [INLINE] get_count
      (VAR count_given: boolean;
       VAR count: integer);

      VAR
        integer_size: 0 .. osc$max_status_message,
        user_conditions: ost$user_conditions;

      count := 0;
      integer_size := 0;
      template_index := template_index + 2;

      WHILE ((template_index + integer_size) <= STRLENGTH (template^)) AND
            ('0' <= template^ (template_index + integer_size)) AND
            (template^ (template_index + integer_size) <= '9') DO
        integer_size := integer_size + 1;
      WHILEND;

      count_given := integer_size > 0;
      IF count_given THEN
        clp$evaluate_unsigned_decimal (template^ (template_index, integer_size), count, status);

{ status intentionally ignored

        status.normal := TRUE;
        template_index := template_index + integer_size;
      IFEND;

    PROCEND get_count;
?? OLDTITLE, EJECT ??

    VAR
      condition: ost$status_condition_code,
      condition_name: ost$status_condition_name,
      count: integer,
      count_given: boolean,
      current_character: char,
      end_of_message: boolean,
      file_reference: fst$path,
      last_character: char,
      local_file_name: fst$path,
      message_module_severity: ost$message_module_severity,
      next_character: char,
      number_string: ost$string,
      parameter: ^ost$message_parameter,
      repeat_info: boolean,
      save_template: ^ost$message_template,
      save_template_processing: boolean,
      status_condition_string: ost$string,
      status_identifier: ost$status_identifier;


    status.normal := TRUE;

    message_area := ^message;
    RESET message_area;
    NEXT line_count IN message_area;
    line_count^ := 0;

    IF original_template = NIL THEN
      RETURN; {----->
    IFEND;

    template := original_template;
    save_template := NIL;
    save_template_processing := FALSE;
    message_parameters := original_parameters;
    condition := status_condition;
    next_line_size := 0;
    next_line := '';
    next_line_break_index := 0;
    next_line_secondary_break_index := 0;
    indent_amount := 0;
    soft_eol_pending := FALSE;
    keep_pending := FALSE;
    template_index := 1;
    last_parameter := 0;
    last_space_hard := FALSE;
    repeat_info := FALSE;
    message_parameters_exhausted := FALSE;
    PUSH empty_string: [0];

    WHILE (template_index <= STRLENGTH (template^)) AND (template^ (template_index) = ' ') DO
      template_index := template_index + 1;
    WHILEND;

    IF (message_header_kind = osc$standard_status_message_hdr) OR
          ((message_header_kind = osc$error_status_message_hdr) AND
          (status_severity > osc$informative_status)) THEN
      put_standard_message_header;
    ELSEIF message_header_kind = osc$subdued_status_message_hdr THEN
      put_subdued_message_header;
    IFEND;

  /process_individual_template/
    WHILE TRUE DO

      REPEAT
        current_character := ' ';
        IF save_template_processing THEN
          repeat_info := FALSE;
        IFEND;

        WHILE template_index <= STRLENGTH (template^) DO
          last_character := current_character;
          current_character := template^ (template_index);
          IF template_index = STRLENGTH (template^) THEN
            next_character := ' ';
          ELSE
            next_character := template^ (template_index + 1);
          IFEND;
          IF current_character = '+' THEN
            CASE next_character OF

            = 'A', 'a' = {abort current line
              template_index := template_index + 2;
              soft_eol_pending := FALSE;
              next_line_break_index := 0;
              next_line_secondary_break_index := 0;
              next_line := '';
              next_line_size := 0;

            = 'C', 'c' = {condition code of status
              template_index := template_index + 2;
              osp$get_status_condition_string (condition, status_condition_string, status);
              IF NOT status.normal THEN
                EXIT format_message; {----->
              IFEND;
              put_string (status_condition_string.value (1, status_condition_string.size));

            = 'E', 'e' = {soft eol (end of line)
              get_count (count_given, count);
              soft_eol_pending := TRUE;
              next_line_break_index := next_line_size;
              indent_amount := count;

            = 'F', 'f' = {message parameter interpreted  as file name
              get_count (count_given, count);
              get_parameter (count, parameter);
              process_file_parameter (parameter^);

            = 'H', 'h' = {insert spaces to column
              get_count (count_given, count);
              IF NOT count_given THEN
                count := 8 - (next_line_size MOD 8);
              ELSEIF next_line_size >= count THEN
                count := 1;
              ELSE
                count := count - next_line_size - 1;
              IFEND;
              IF (next_line_size + count) < max_line_size THEN
                next_line_size := next_line_size + count;
              ELSE
                indent_amount := 0;
                flush_line;
              IFEND;

            = 'I', 'i' = {product identifier of status
              template_index := template_index + 2;
              osp$unpack_status_identifier (condition, status_identifier);
              put_string (status_identifier);

            = 'K', 'k' = {toggle keeping together of a group of characters
              template_index := template_index + 2;
              keep_pending := NOT keep_pending;

            = 'N', 'n' = {hard eol (end of line)
              get_count (count_given, count);
              next_line_break_index := next_line_size;
              indent_amount := count;
              flush_line;
              indent_amount := 0;

            = 'P', 'p' = {message parameter
              get_count (count_given, count);
              get_parameter (count, parameter);
              put_string (parameter^);

            = 'R', 'r' = {begin/end repeating information
              IF save_template_processing THEN
                ;
              ELSEIF NOT repeat_info THEN {+R
                IF message_parameters <> NIL THEN
                  message_parameters_exhausted := last_parameter + 1 >= UPPERBOUND (message_parameters^);
                ELSE
                  message_parameters_exhausted := TRUE;
                IFEND;
                IF NOT message_parameters_exhausted THEN
                  repeat_info := TRUE;
                IFEND;
                template := ^template^ ((template_index + 2), * );
                template_index := 1;
                current_character := ' ';

              ELSEIF ((template_index + 2) <= STRLENGTH (template^)) AND ((template^ (template_index + 2) =
                    'E') OR (template^ (template_index + 2) = 'e')) THEN {+R .. +RE

                IF save_template = NIL THEN
                  save_template := ^template^ ((template_index + 3), * );
                  template := ^template^ (1, template_index + 2);
                IFEND;
                IF message_parameters_exhausted THEN
                  template_index := template_index + 3;
                ELSE
                  template_index := 1;
                IFEND;
              IFEND;

            = 'S', 's' = {severity of status
              template_index := template_index + 2;
              put_string (osv$severities [status_severity].value (1, osv$severities [status_severity].size));

            = 'T', 't' = {all of text field from message_status record, i.e. all message parameters
              template_index := template_index + 2;
              IF message_parameters <> NIL THEN
                FOR count := 1 TO UPPERBOUND (message_parameters^) DO
                  put_character (parameter_delimiter);
                  put_string (message_parameters^ [count]^);
                FOREND;
              IFEND;

            = 'X', 'x' = {expand count as blanks
              get_count (count_given, count);
              IF NOT count_given THEN
                count := 1;
              IFEND;
              IF (next_line_size + count) < max_line_size THEN
                next_line_size := next_line_size + count;
                last_space_hard := TRUE;
              ELSE
                indent_amount := 0;
                flush_line;
              IFEND;

            = '+' = {the control sequence ++ => +
              template_index := template_index + 2;
              put_character ('+');

            = '-' = {NULL sequence (to allow for concatenation)
              template_index := template_index + 2;

            ELSE {this '+' is just another character
              template_index := template_index + 1;
              put_character ('+');
            CASEND;

          ELSEIF (last_character = ' ') AND (current_character = ' ') THEN
            template_index := template_index + 1;
            last_space_hard := TRUE;
          ELSE
            template_index := template_index + 1;
            put_character (current_character);
            last_space_hard := current_character = ' ';
          IFEND;

        WHILEND;
        IF repeat_info THEN
          template_index := 1;
          IF message_parameters_exhausted AND (save_template <> NIL) THEN
            template := save_template;
            save_template_processing := TRUE;
            save_template := NIL;
            message_parameters_exhausted := FALSE;
          IFEND;
        IFEND;
      UNTIL (NOT repeat_info) OR message_parameters_exhausted;

      IF get_message_part = NIL THEN
        EXIT /process_individual_template/; {----->
      IFEND;
      get_message_part^ (condition, message_parameters, end_of_message, status);
      IF (NOT status.normal) OR (end_of_message) THEN
        EXIT /process_individual_template/; {----->
      IFEND;

      get_template_info_via_code (condition, TRUE, condition_name, message_module_severity, template, status);
      IF (NOT status.normal) OR (template = NIL) OR (STRLENGTH (template^) = 0) THEN
        template := ^default_template;
      IFEND;

      keep_pending := FALSE;
      template_index := 1;
      last_parameter := 0;
      repeat_info := FALSE;
      message_parameters_exhausted := FALSE;
    WHILEND /process_individual_template/;

    IF next_line_size > 0 THEN
      flush_line;
    IFEND;

  PROCEND format_message;
?? TITLE := 'setup_status_message_formatting', EJECT ??

  PROCEDURE [INLINE] setup_status_message_formatting
    (    message_status: ^ost$status;
         message_level: ost$format_message_level;
     VAR actual_message_level: ost$status_message_level;
     VAR severity: ost$status_severity;
     VAR text: ^ost$status_text;
     VAR delimiter_count: 0 .. osc$parameter_delimiter_limit;
     VAR parameter_delimiter: char;
     VAR template: ^ost$message_template);

    VAR
      current_message_level: ^ost$status_message_level,
      message_status_text_size: ost$string_size,
      condition_name: ost$status_condition_name,
      message_module_severity: ost$message_module_severity,
      text_index: ost$string_index,
      status: ost$status;


    IF message_level = osc$current_message_level THEN
      osp$find_status_message_level (current_message_level);
      actual_message_level := current_message_level^;
    ELSE
      actual_message_level := message_level;
    IFEND;

    get_template_info_via_code (message_status^.condition, TRUE, condition_name, message_module_severity,
          template, status);
    IF (NOT status.normal) OR (template = NIL) OR (STRLENGTH (template^) = 0) THEN
      template := ^default_template;
    IFEND;

    severity := osp$convert_to_status_severity (message_module_severity);

    IF message_status^.text.size > osc$max_string_size THEN
      message_status_text_size := 0;
    ELSE
      message_status_text_size := message_status^.text.size;
    IFEND;

    text := ^message_status^.text.value (1, message_status_text_size);
    parameter_delimiter := message_status^.text.value (1);
    delimiter_count := 0;
    FOR text_index := 1 TO message_status_text_size DO
      IF text^ (text_index) = parameter_delimiter THEN
        delimiter_count := delimiter_count + 1;
      IFEND;
    FOREND;

  PROCEND setup_status_message_formatting;
?? TITLE := 'setup_status_message_parameters', EJECT ??

  PROCEDURE [INLINE] setup_status_message_parameters
    (    text: ^ost$status_text;
         parameter_delimiter: char;
     VAR message_parameters {input, output} : ost$message_parameters);

    VAR
      empty_string: ^string ( * ),
      message_parameter_index: integer,
      parameter_size: ost$string_size,
      start_of_parameter: ost$string_index,
      text_index: ost$string_index;


    PUSH empty_string: [0];
    FOR message_parameter_index := 1 TO UPPERBOUND (message_parameters) DO
      message_parameters [message_parameter_index] := empty_string;
    FOREND;
    parameter_size := 0;
    start_of_parameter := 2;
    message_parameter_index := 1;

  /fill_in_message_parameters/
    FOR text_index := 2 TO STRLENGTH (text^) DO
      IF text^ (text_index) <> parameter_delimiter THEN
        parameter_size := parameter_size + 1;
      ELSE
        IF message_parameter_index > UPPERBOUND (message_parameters) THEN
          EXIT /fill_in_message_parameters/; {----->
        IFEND;
        message_parameters [message_parameter_index] := ^text^ (start_of_parameter, parameter_size);
        message_parameter_index := message_parameter_index + 1;
        parameter_size := 0;
        start_of_parameter := text_index + 1;
      IFEND;
    FOREND /fill_in_message_parameters/;
    IF (parameter_size > 0) AND (message_parameter_index <= UPPERBOUND (message_parameters)) THEN
      message_parameters [message_parameter_index] := ^text^ (start_of_parameter, parameter_size);
    IFEND;

  PROCEND setup_status_message_parameters;
?? TITLE := 'osp$format_message', EJECT ??
*copy osh$format_message

  PROCEDURE [XDCL, #GATE] osp$format_message ALIAS 'ospfmsg'
    (    message_status: ost$status;
         message_level: ost$format_message_level;
         max_message_line: ost$max_status_message_line;
     VAR message: ost$status_message;
     VAR status: ost$status);

    VAR
      actual_message_level: ost$status_message_level,
      delimiter_count: 0 .. osc$parameter_delimiter_limit,
      format_message_level: ost$format_message_level,
      identifier: ost$status_identifier,
      line_count: ^ost$status_message_line_count,
      maximum_message_line: ost$max_status_message_line,
      message_area: ^ost$status_message,
      message_parameters: ^ost$message_parameters,
      parameter_delimiter: char,
      severity: ost$status_severity,
      template: ^ost$message_template,
      text: ^ost$status_text;

    status.normal := TRUE;

    IF message_status.normal THEN
      message_area := ^message;
      RESET message_area;
      NEXT line_count IN message_area;
      line_count^ := 0;

    ELSE
      IF (message_level < LOWERVALUE (ost$format_message_level)) OR
            (message_level > UPPERVALUE (ost$format_message_level)) THEN
        format_message_level := osc$current_message_level;
      ELSE
        format_message_level := message_level;
      IFEND;

      IF max_message_line < LOWERVALUE (ost$max_status_message_line) THEN
        maximum_message_line := LOWERVALUE (ost$max_status_message_line);
      ELSEIF max_message_line > UPPERVALUE (ost$max_status_message_line) THEN
        maximum_message_line := UPPERVALUE (ost$max_status_message_line);
      ELSE
        maximum_message_line := max_message_line;
      IFEND;

      setup_status_message_formatting (^message_status, format_message_level, actual_message_level, severity,
            text, delimiter_count, parameter_delimiter, template);
      IF delimiter_count = 0 THEN
        message_parameters := NIL;
      ELSE
        PUSH message_parameters: [1 .. delimiter_count];
        setup_status_message_parameters (text, parameter_delimiter, message_parameters^);
      IFEND;
      format_message (actual_message_level, osc$standard_status_message_hdr, maximum_message_line - 1,
            message_status.condition, severity, template, message_parameters, NIL, parameter_delimiter,
            message, status);
    IFEND;

  PROCEND osp$format_message;
?? TITLE := 'osp$format_help_message', EJECT ??
*copyc osh$format_help_message

  PROCEDURE [XDCL, #GATE] osp$format_help_message
    (    message_template: ^ost$message_template;
         message_parameters: ^ost$message_parameters;
         max_message_line: ost$max_status_message_line;
     VAR message: ost$status_message;
     VAR status: ost$status);

    VAR
      maximum_message_line: ost$max_status_message_line;

    status.normal := TRUE;

    IF max_message_line < LOWERVALUE (ost$max_status_message_line) THEN
      maximum_message_line := LOWERVALUE (ost$max_status_message_line);
    ELSEIF max_message_line > UPPERVALUE (ost$max_status_message_line) THEN
      maximum_message_line := UPPERVALUE (ost$max_status_message_line);
    ELSE
      maximum_message_line := max_message_line;
    IFEND;

    format_message (osc$brief_message_level, osc$no_status_message_hdr, maximum_message_line - 1, 0,
          osc$informative_status, message_template, message_parameters, NIL, osc$status_parameter_delimiter,
          message, status);

  PROCEND osp$format_help_message;
?? TITLE := 'osp$generate_message', EJECT ??
*copyc osh$generate_message

  PROCEDURE [XDCL, #GATE] osp$generate_message ALIAS 'ospgmsg'
    (    message_status: ost$status;
     VAR status: ost$status);

    VAR
      page_width: amt$page_width;

    p$get_page_width (clc$job_command_response, page_width);
    generate_message (page_width, ^clp$put_job_command_response, osc$current_message_level,
          osc$standard_status_message_hdr, message_status, status);

  PROCEND osp$generate_message;
?? TITLE := 'osp$generate_message_display', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$generate_message_display
    (    message_status: ost$status;
     VAR display_control: clt$display_control;
     VAR status: ost$status);

?? NEWTITLE := 'P$PUT_DISPLAY', EJECT ??

    PROCEDURE p$put_display
      (    text: string ( * );
       VAR status: ost$status);

      clp$put_display (display_control, text, clc$trim, status);

    PROCEND p$put_display;
?? OLDTITLE ??
?? EJECT ??
    generate_message (display_control.page_width, ^p$put_display, osc$current_message_level,
          osc$standard_status_message_hdr, message_status, status);

  PROCEND osp$generate_message_display;
?? TITLE := 'osp$generate_error_message', EJECT ??
*copyc osh$generate_error_message

  PROCEDURE [XDCL, #GATE] osp$generate_error_message ALIAS 'ospgemg'
    (    message_status: ost$status;
     VAR status: ost$status);

    VAR
      page_width: amt$page_width;

    p$get_page_width (clc$error_output, page_width);
    generate_message (page_width, ^clp$put_error_output, osc$full_message_level,
          osc$standard_status_message_hdr, message_status, status);

  PROCEND osp$generate_error_message;
?? TITLE := 'osp$generate_log_message', EJECT ??
*copyc osh$generate_log_message

  PROCEDURE [XDCL, #GATE] osp$generate_log_message ALIAS 'ospglgm'
    (    logs: pmt$ascii_logset;
         message_status: ost$status;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      destination_logs: pmt$ascii_logset;

?? SKIP := 2 ??

    PROCEDURE put_log_line
      (    text: string ( * );
       VAR status: ost$status);


      pmp$log_ascii (text, destination_logs, pmc$msg_origin_system, status);

    PROCEND put_log_line;
?? SKIP := 2 ??

    #CALLER_ID (caller_id);
    status.normal := TRUE;

    IF (caller_id.ring > osc$tsrv_ring) THEN
      destination_logs := logs - $pmt$ascii_logset [pmc$system_log];
    ELSE
      destination_logs := logs;
    IFEND;

    IF destination_logs <> $pmt$ascii_logset [] THEN
      generate_message (osc$max_status_message_line, ^put_log_line, osc$full_message_level,
            osc$standard_status_message_hdr, message_status, status);
    IFEND;

  PROCEND osp$generate_log_message;
?? TITLE := 'osp$generate_output_message', EJECT ??
*copyc osh$generate_output_message

  PROCEDURE [XDCL, #GATE] osp$generate_output_message
    (    message_status: ost$status;
     VAR status: ost$status);

    VAR
      page_width: amt$page_width;

    p$get_page_width (clc$job_output, page_width);
    generate_message (page_width, ^clp$put_job_output, osc$current_message_level,
          osc$subdued_status_message_hdr, message_status, status);

  PROCEND osp$generate_output_message;
?? TITLE := 'GENERATE_MESSAGE', EJECT ??

  PROCEDURE generate_message
    (    page_width: amt$page_width;
         output_procedure: t$output_procedure;
         message_level: ost$format_message_level;
         message_header_kind: ost$status_message_header_kind;
         message_status: ost$status;
     VAR status: ost$status);

    VAR
      actual_message_level: ost$status_message_level,
      delimiter_count: 0 .. osc$parameter_delimiter_limit,
      message: ost$status_message,
      message_area: ^ost$status_message,
      message_line: ^string ( * ),
      message_line_count: ^ost$status_message_line_count,
      message_line_index: 1 .. osc$max_status_message_lines,
      message_line_size: ^ost$status_message_line_size,
      message_parameters: ^ost$message_parameters,
      parameter_delimiter: char,
      severity: ost$status_severity,
      template: ^ost$message_template,
      text: ^ost$status_text;

?? NEWTITLE := 'abort_condition_handler', EJECT ??

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

      VAR
        run_time_message_status: ^ost$status,
        ignore_status: ost$status;


      CASE condition.selector OF
      = pmc$system_conditions, mmc$segment_access_condition =
        osp$set_status_from_condition ('CL', condition, save_area, status, ignore_status);
        EXIT generate_message; {----->
      = pmc$user_defined_condition =
        IF condition.user_condition_name = cye$run_time_condition THEN
          run_time_message_status := run_time_status;
          status := run_time_message_status^;
          EXIT generate_message; {----->
        IFEND;
      ELSE
        ;
      CASEND;

      pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);

    PROCEND abort_condition_handler;
?? OLDTITLE, EJECT ??
    status.normal := TRUE;
    osp$establish_condition_handler (^abort_condition_handler, FALSE);

    message_area := ^message;
    RESET message_area;
    NEXT message_line_count IN message_area;

    IF message_status.normal THEN
      message_line_count^ := 0;
      RETURN; {----->
    IFEND;

    setup_status_message_formatting (^message_status, message_level, actual_message_level, severity, text,
          delimiter_count, parameter_delimiter, template);
    IF delimiter_count = 0 THEN
      message_parameters := NIL;
    ELSE
      PUSH message_parameters: [1 .. delimiter_count];
      setup_status_message_parameters (text, parameter_delimiter, message_parameters^);
    IFEND;
    format_message (actual_message_level, message_header_kind, page_width - 1, message_status.condition,
          severity, template, message_parameters, NIL, parameter_delimiter, message, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    FOR message_line_index := 1 TO message_line_count^ DO
      NEXT message_line_size IN message_area;
      NEXT message_line: [message_line_size^] IN message_area;
      output_procedure^ (message_line^, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    FOREND;

  PROCEND generate_message;
?? TITLE := 'osp$get_status_severity', EJECT ??
*copy osh$get_status_severity

  PROCEDURE [XDCL, #GATE] osp$get_status_severity ALIAS 'ospgss'
    (    condition: ost$status_condition;
     VAR severity: ost$status_severity;
     VAR status: ost$status);

    VAR
      condition_name: ost$status_condition_name,
      message_module_severity: ost$message_module_severity,
      template: ^ost$message_template;

    get_template_info_via_code (condition, FALSE, condition_name, message_module_severity, template, status);

    severity := osp$convert_to_status_severity (message_module_severity);

  PROCEND osp$get_status_severity;
?? TITLE := 'osp$get_diagnostic_severity', EJECT ??
*copy osh$get_diagnostic_severity

  PROCEDURE [XDCL, #GATE] osp$get_diagnostic_severity ALIAS 'ospgss'
    (    condition: ost$status_condition;
     VAR severity: ost$diagnostic_severity;
     VAR status: ost$status);

    VAR
      condition_name: ost$status_condition_name,
      message_module_severity: ost$message_module_severity,
      template: ^ost$message_template;

    get_template_info_via_code (condition, FALSE, condition_name, message_module_severity, template, status);

    severity := osp$convert_to_diagnos_severity (message_module_severity);

  PROCEND osp$get_diagnostic_severity;
?? TITLE := 'osp$get_status_message_by_code', EJECT ??
*copyc osh$get_status_message_by_code

  PROCEDURE [XDCL, #GATE] osp$get_status_message_by_code
    (    condition_code: ost$status_condition_code;
     VAR condition_name: ost$status_condition_name;
     VAR status_severity: ost$status_severity;
     VAR diagnostic_severity: ost$diagnostic_severity;
     VAR message_template: ^ost$message_template;
     VAR status: ost$status);

    VAR
      severity: ost$message_module_severity;

    get_template_info_via_code (condition_code, TRUE, condition_name, severity, message_template, status);

    status_severity := osp$convert_to_status_severity (severity);
    diagnostic_severity := osp$convert_to_diagnos_severity (severity);

  PROCEND osp$get_status_message_by_code;
?? TITLE := 'osp$get_status_condition_name', EJECT ??
*copyc osh$get_status_condition_name

  PROCEDURE [XDCL, #GATE] osp$get_status_condition_name ALIAS 'ospgscn'
    (    code: ost$status_condition_code;
     VAR name: ost$status_condition_name;
     VAR status: ost$status);

    VAR
      severity: ost$message_module_severity,
      template: ^ost$message_template;

    get_template_info_via_code (code, FALSE, name, severity, template, status);

  PROCEND osp$get_status_condition_name;
?? TITLE := 'osp$get_status_condition_code', EJECT ??
*copyc osh$get_status_condition_code

  PROCEDURE [XDCL, #GATE] osp$get_status_condition_code
    (    name: ost$status_condition_name;
     VAR code: ost$status_condition_code;
     VAR status: ost$status);

    VAR
      severity: ost$message_module_severity,
      template: ^ost$message_template;

    get_template_info_via_name (name, FALSE, code, severity, template, status);

  PROCEND osp$get_status_condition_code;
?? TITLE := 'osp$get_status_condition_string', EJECT ??
*copyc osh$get_status_condition_string

  PROCEDURE [XDCL, #GATE] osp$get_status_condition_string
    (    condition: ost$status_condition_code;
     VAR str: ost$string;
     VAR status: ost$status);

    VAR
      identifier: ost$status_identifier,
      number: ost$status_condition_number,
      str_length: integer,
      str_value: ost$name;

    status.normal := TRUE;
    osp$unpack_status_condition (condition, identifier, number);

    #SPOIL (identifier); { !!! NEEDED TO GET AROUND CYBIL INSTRUCTION SCHEDULING BUG !!! }

    IF (' ' <= identifier (1)) AND (identifier (1) <= '~') AND (' ' <= identifier (2)) AND (identifier (2) <=
          '~') THEN
      STRINGREP (str_value, str_length, identifier, number);
      str.size := str_length;
      str.value := str_value;
    ELSE
      clp$convert_integer_to_string (condition, 10, FALSE, str, status);
    IFEND;

  PROCEND osp$get_status_condition_string;
?? TITLE := 'osp$get_message_level', EJECT ??
*copyc osh$get_message_level

  PROCEDURE [XDCL, #GATE] osp$get_message_level
    (VAR message_level: ost$status_message_level;
     VAR status: ost$status);

    VAR
      message_level_ptr: ^ost$status_message_level;

    status.normal := TRUE;

    osp$find_status_message_level (message_level_ptr);
    message_level := message_level_ptr^;

  PROCEND osp$get_message_level;
?? TITLE := 'osp$log_system_status_message', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$log_system_status_message
    (    logs: pmt$ascii_logset;
         message_status: ost$status;
     VAR status: ost$status);

    VAR
      actual_message_level: ost$status_message_level,
      caller_id: ost$caller_identifier,
      delimiter_count: 0 .. osc$parameter_delimiter_limit,
      found: boolean,
      ignore_status: ost$status,
      language: ost$natural_language,
      message: ost$status_message,
      message_area: ^ost$status_message,
      message_line: ^string ( * ),
      message_line_count: ^ost$status_message_line_count,
      message_line_index: 1 .. osc$max_status_message_lines,
      message_line_size: ^ost$status_message_line_size,
      message_module: ^ost$message_template_module,
      message_parameters: ^ost$message_parameters,
      message_status_text_size: ost$string_size,
      name: ost$status_condition_name,
      parameter_delimiter: char,
      severity: ost$message_module_severity,
      status_severity: ost$status_severity,
      template: ^ost$message_template,
      text: ^ost$status_text,
      text_index: ost$string_index;

    osp$verify_system_privilege;
    status.normal := TRUE;
    #CALLER_ID (caller_id);

    IF (caller_id.ring <= osc$tsrv_ring)
{ } AND (logs <> $pmt$ascii_logset []) AND (NOT message_status.normal) THEN
      language := osc$us_english;
      clp$get_system_message_mod_ptr (message_module);
      IF message_module <> NIL THEN
        clp$search_module_for_code (message_module, message_status.condition, language, name, severity,
              template, found, ignore_status);
        IF found THEN
          status_severity := osp$convert_to_status_severity (severity);
          message_area := ^message;
          RESET message_area;
          NEXT message_line_count IN message_area;

          IF message_status.text.size > osc$max_string_size THEN
            message_status_text_size := 0;
          ELSE
            message_status_text_size := message_status.text.size;
          IFEND;

          text := ^message_status.text.value (1, message_status_text_size);
          parameter_delimiter := message_status.text.value (1);
          delimiter_count := 0;
          FOR text_index := 1 TO message_status_text_size DO
            IF text^ (text_index) = parameter_delimiter THEN
              delimiter_count := delimiter_count + 1;
            IFEND;
          FOREND;

          IF delimiter_count = 0 THEN
            message_parameters := NIL;
          ELSE
            PUSH message_parameters: [1 .. delimiter_count];
            setup_status_message_parameters (text, parameter_delimiter, message_parameters^);
          IFEND;
          format_message (actual_message_level, osc$standard_status_message_hdr,
                osc$max_status_message_line - 1, message_status.condition, status_severity, template,
                message_parameters, {get_message_part} NIL, parameter_delimiter, message, status);
          IF status.normal THEN
            FOR message_line_index := 1 TO message_line_count^ DO
              NEXT message_line_size IN message_area;
              NEXT message_line: [message_line_size^] IN message_area;
              pmp$log_ascii (message_line^, logs, pmc$msg_origin_system, ignore_status);
            FOREND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND osp$log_system_status_message;
?? TITLE := 'osp$output_status_message', EJECT ??
*copyc osh$output_status_message

  PROCEDURE [XDCL, #GATE] osp$output_status_message
    (    file_id: amt$file_identifier;
         message_level: ost$format_message_level;
         message_header_kind: ost$status_message_header_kind;
         message_status: ost$status;
     VAR status: ost$status);

    VAR
      byte_address: amt$file_byte_address,
      file_attributes: array [1 .. 1] of amt$fetch_item;

?? NEWTITLE := 'P$PUT_DISPLAY', EJECT ??

    PROCEDURE p$put_display
      (    text: string ( * );
       VAR status: ost$status);

      amp$put_next (file_id, ^text, STRLENGTH (text), byte_address, status);

    PROCEND p$put_display;
?? OLDTITLE ??
?? EJECT ??
    file_attributes [1].key := amc$page_width;
    amp$fetch (file_id, file_attributes, status);
    IF (NOT status.normal) OR (file_attributes [1].page_width < osc$min_status_message_line) THEN
      file_attributes [1].page_width := osc$min_status_message_line;
    ELSEIF file_attributes [1].page_width > osc$max_status_message_line THEN
      file_attributes [1].page_width := osc$max_status_message_line;
    IFEND;

    generate_message (file_attributes [1].page_width, ^p$put_display, message_level, message_header_kind,
          message_status, status);

  PROCEND osp$output_status_message;
?? OLDTITLE ??
MODEND osm$system_message_generator;
