?? NEWTITLE := '~~~~~   common deck DSI$DEADSTART_COMMAND_PROCESSOR', EJECT ??

  TYPE
    dsc_commands = (run, dump, panel, scd, tnvejob, dsoption,
          timelimit, vsn, density, endlst);

  CONST
*IF ($string($name(wev$target_operating_system))='NOS')
    bpi_1600 = 4,  { 1600 BPI (PE) for NOS tape request.
    bpi_6250 = 5;  { 6250 BPI (GE) for NOS tape request.
*ELSE
    bpi_1600 = 3,  { 1600 BPI (PE) for NOS/BE tape request.
    bpi_6250 = 1;  { 6250 BPI (GE) for NOS/BE tape request.
*IFEND

{  The following two variables are referenced by assembly language labelled tape
{  routines.  Each variable must be one 60 bit word.

  VAR
    dsv$dump_tape_density ALIAS 'dsv#den': [XDCL] integer := bpi_6250,
    dsv$dump_tape_vsn ALIAS 'dsv#vsn': [XDCL] ARRAY [1 .. 1] OF PACKED ARRAY [0 .. 9]
          OF 0 .. 3f(16) := [[04, 15(8), 20(8), 33(8), 33(8), 01, 55(8), 55(8), 55(8), 55(8)]],
    dsv$ssr_operator_intervention: 0 .. 1;

  VAR
    command: dsc_commands,
    critical_dump_allowed: boolean,
    memory_to_be_dumped: string (8),
    run_mode: boolean := TRUE,
    take_dump: boolean := TRUE,
    terminate_nve_job: boolean := FALSE,
    timeout_limit: integer := 1800; { 1800 seconds

?? EJECT ??

{  PURPOSE:
{    Get the next command from the input buffer.

  PROCEDURE do_command
    (inhibit_tape_commands: boolean;
     VAR command_error_flag: boolean);

    CONST
      cmrdck_specifier = 0fffff(16),
      display_specifier = 0ffff0(16);

    VAR
      command_list: [STATIC] ARRAY [dsc_commands] OF string (10) := ['*RUN',
        '*DUMP', '*PANEL', '*SCD', '*TNVEJOB', '*DSOPTION', '*TIMEOUT',
        '*VSN', '*DENSITY', '*ENDLST'];

    VAR
      d8st: PACKED RECORD
        fill_1: 0 .. 777777777777(8),
        scd_port: 0 .. 77(8),
        scd_pp: 0 .. 77(8),
        fill_2: 0 .. 7777(8),
      RECEND;

    VAR
      change_memory_error: boolean,
      dc_vsn_char_index: 0 .. 9,
      dc_vsn_word_index: integer,
      dump_tape_vsn: ARRAY [1 .. 1] OF PACKED ARRAY [0 .. 9] OF 0 .. 3f(16),
      eol: boolean,
      i: integer,
      next_param: param_type, {next command parameter
      panel_word_number,
      panel_word_value: integer,
      param_value: c180_word, {next parameter value
      param_is_false: boolean,
      param_is_true: boolean,
      save_text_line: string (line_width),
      source_index: ost$string_index,
      trial_command: dsc_commands;

    command_error_flag := FALSE;
    IF text_line (1) = ' ' THEN
      RETURN;
    IFEND;
    command_error_flag := TRUE;
    show_message (text_line, operator_echo_line, no_scroll);

  /process_command/
    BEGIN

    /search_period/
      FOR i := 1 TO line_width DO
        IF text_line (i) = '.' THEN
          EXIT /search_period/;
        IFEND;
      FOREND /search_period/;
      IF text_line (i) <> '.' THEN
        EXIT /process_command/;
      IFEND;

      extract_param (next_param, 0);

    /find_command/
      FOR trial_command := run TO endlst DO
        IF next_param = command_list [trial_command] THEN
          text_line (1) := ' ';
          EXIT /find_command/;
        IFEND;
      FOREND /find_command/;
      IF next_param <> command_list [trial_command] THEN
        EXIT /process_command/;
      IFEND;

{  Decode and process commands.

      extract_param (next_param, 1);
      IF (next_param = 'CRITICAL') AND (NOT critical_dump_allowed) THEN
        EXIT /process_command/;
      IFEND;
      param_is_true := (next_param = 'ON') OR (next_param = 'TRUE') OR
            (next_param = 'YES') OR (next_param = 'ALL') OR
            (next_param = 'CRITICAL') OR (next_param = 'NONE');
      param_is_false := (next_param = 'OFF') OR (next_param = 'FALSE') OR
            (next_param = 'NO');

      CASE trial_command OF

      = dsoption =

      = panel =
        make_number (next_param, param_value, error_flag, oct);
        IF error_flag = TRUE OR (param_value.left <> 0) THEN
          EXIT /process_command/;
        IFEND;
        panel_word_number := param_value.right;
        extract_param (next_param, 2);
        make_number (next_param, param_value, error_flag, oct);
        IF error_flag = TRUE OR (param_value.left <> 0) THEN
          EXIT /process_command/;
        IFEND;
        panel_word_value := param_value.right;
        IF panel_word_number = cmrdck_specifier THEN

          { Ignore the dcfile number, NOS/VE now retrieves the value from
          { the boot screens.

        ELSEIF panel_word_number = display_specifier THEN

          { Save the operator intervention bit to be saved in the SSR
          { during the update of the SSR.

          IF (panel_word_value < 0) OR (panel_word_value > 1) THEN
            EXIT /process_command/;
          IFEND;
          dsv$ssr_operator_intervention := panel_word_value;
        IFEND;

      = scd =
        make_number (next_param, param_value, error_flag, dec);
        IF error_flag OR (param_value.right > 1) OR (param_value.left <> 0)
              THEN
          EXIT /process_command/;
        IFEND;

{  Store the SCD port number in word D8ST of the EICB.

        get_dscb (dscb_d8st, ^d8st, 1);
        d8st.scd_port := param_value.right;
        put_dscb (dscb_d8st, ^d8st, 1);

{  System operation control commands.

      = dump =
        IF inhibit_tape_commands THEN
          command_error_flag := TRUE;
          EXIT /process_command/;
        ELSE
          IF param_is_false THEN
            take_dump := FALSE;
          ELSEIF param_is_true THEN
            take_dump := TRUE;
            memory_to_be_dumped := next_param;
          ELSE
            EXIT /process_command/;
          IFEND;
        IFEND;

      = run =
        run_mode := TRUE;

      = tnvejob =
        IF param_is_false THEN
          terminate_nve_job := FALSE;
        ELSEIF param_is_true THEN
          terminate_nve_job := TRUE;
        ELSE
          EXIT /process_command/;
        IFEND;

      = timelimit =
        make_number (next_param, param_value, error_flag, dec);
        timeout_limit := param_value.right;

      = density =
        IF inhibit_tape_commands THEN
          command_error_flag := TRUE;
          EXIT /process_command/;
        ELSE

{  Save density in global variables for assembly language labelled tape routines.

          IF next_param = 'PE' THEN
            dsv$dump_tape_density := bpi_1600;
          ELSEIF next_param = 'GE' THEN
            dsv$dump_tape_density := bpi_6250;
          ELSE
            EXIT /process_command/;
          IFEND;
        IFEND;

      = vsn =
        IF inhibit_tape_commands THEN
          command_error_flag := TRUE;
          EXIT /process_command/;
        ELSE

{  Convert ascii string to display code string and save in global variable for
{  assembly language labelled tape routines.

          dc_vsn_word_index := LOWERBOUND(dump_tape_vsn);
          dc_vsn_char_index := 0;
          source_index := 1;
          eol := FALSE;

{  Convert the vsn to display code.  The vsn is a maximum of 6 characters but next_param is
{  is longer than that so the display code string will be blank filled.

          utp$convert_string_to_dc_string (utc$ascii64, dump_tape_vsn, dc_vsn_word_index,
                 dc_vsn_char_index, next_param, source_index, eol);

        /check_vsn_length/
          FOR dc_vsn_char_index := 9 DOWNTO 0 DO
            IF dump_tape_vsn [LOWERBOUND(dump_tape_vsn)][dc_vsn_char_index] <> 55(8) THEN
              IF dc_vsn_char_index > 5 THEN
                EXIT /process_command/
              ELSE
                EXIT /check_vsn_length/;
              IFEND;
            ELSE
              IF dc_vsn_char_index = 0 THEN

{  Do not allow vsn of all blanks.

                EXIT /process_command/
              IFEND;
            IFEND;
          FOREND /check_vsn_length/;

          dsv$dump_tape_vsn := dump_tape_vsn;
        IFEND;

      = endlst =
        {do nothing
      ELSE
        EXIT /process_command/;
      CASEND;
      command_error_flag := FALSE;
      show_message (' ', message_line, no_scroll);
    END /process_command/;
    IF command_error_flag THEN
      save_text_line := text_line;
      text_line (1, 7) := '*ERROR ';
      text_line (8, * ) := save_text_line;
      show_message ('INPUT ERROR, IGNORED', message_line, no_scroll);
    IFEND;
    command := trial_command;
    show_message (text_line, line_position, auto);

  PROCEND do_command;
?? EJECT ??

{ PURPOSE:
{   Wait for the operator to perform an action.

  PROCEDURE wait_for_operator_action
    (inhibit_tape_commands: boolean;
     VAR error: boolean);

    VAR
      clock_value: integer,
      timeout_threshold: integer;

    gettime (clock_value);
    timeout_threshold := timeout_limit + clock_value;

    REPEAT
      convert_k_display;
      IF text_line (1) = ' ' THEN
        gettime (clock_value);
        IF clock_value > timeout_threshold THEN
          dyfstring ('operator timeout', system_dayf);
          run_mode := TRUE;
          do_command (inhibit_tape_commands, error);
        ELSE
          wakeup;
        IFEND;
      ELSE
        do_command (inhibit_tape_commands, error);
      IFEND;
    UNTIL run_mode;

  PROCEND wait_for_operator_action;
?? EJECT ??

{ PURPOSE:
{   Convert the k display from display code to ascii.

*copyc zutpd2s


  PROCEDURE convert_k_display;

    TYPE
      k_input_copy = ARRAY [1 .. 7] OF integer;


    VAR
      kinpb: [XREF] kdispb_line,
      k_input_buffer: ^k_input_copy,
      dcwi: integer,
      dcci: 0 .. 9,
      sl: ost$string_length,
      eol: boolean,
      i,
      j: integer;

    text_line := ' ';
    k_input_buffer := #LOC (kinpb);

    IF k_input_buffer^ [1] <> 0 THEN
      dcwi := 1;
      dcci := 0;
      eol := FALSE;
      utp$convert_dc_string_to_string (utc$ascii64, kinpb, dcwi, dcci,
            text_line, sl, eol);
      text_line := text_line (1, sl);
      FOR i := 1 TO 7 DO
        k_input_buffer^ [i] := 0;
      FOREND;
    IFEND;

  PROCEND convert_k_display;
?? EJECT ??

{ PURPOSE:
{  Get the next command from the current command file.

  VAR
    file_mark_position: file_mark,
    text_line: [STATIC] string (line_width);


  PROCEDURE get_next_command
    (VAR file_name: ^cell,
         char_no: integer);

    VAR
      line_end: boolean,
      lost_text: string (8),
      lost_char_cnt: integer,
      local_line: string (line_width);

{  Read next line from command file.

    lg#getpart (file_name, line_end, char_no, local_line);
    WHILE (line_end = FALSE) DO
      f#mark (file_name, file_mark_position);
      IF (file_mark_position = data#) THEN
        lg#getpart (file_name, line_end, lost_char_cnt, lost_text);
      IFEND;
    WHILEND;
    IF char_no = 0 THEN
      RETURN;
    IFEND;

{  Display command.

    text_line := local_line (1, char_no);

  PROCEND get_next_command;
?? EJECT ??

  PROCEDURE read_deadstart_command_file
    (inhibit_tape_commands: boolean);

    VAR
      command_length: integer,
      error_in_command,
      error: boolean;

    error_in_command := FALSE;

  /get_ds_commands/
    WHILE active_cmnds_file DO
      get_next_command (command_file, command_length);
      do_command (inhibit_tape_commands, error);
      IF error THEN
        error_in_command := TRUE;
      IFEND;
      IF (command = endlst) OR (command_length = 0) THEN
        EXIT /get_ds_commands/;
      IFEND;
    WHILEND /get_ds_commands/;
    IF error_in_command OR (sw2 IN jcr.sense_switches) THEN
      display;
      run_mode := FALSE;
      REPEAT
        convert_k_display;
        do_command (inhibit_tape_commands, error);
        wakeup;
      UNTIL run_mode;
    IFEND;

  PROCEND read_deadstart_command_file;
?? OLDTITLE ??
