$UCSD ON$
$SYSPROG$
$SEARCH '*IO.', '*INTERFACE.',
        'KRMIO', 'KRMGUTS', 'KRMCMD', 'KRMWNDW',
        'KRMRPT', 'KRMIO'$

{

This file, KRMMAIN.TEXT, contains the Kermit main program block.  It
calls the appropriate procedures in the proper order to read a command
line, parse it, and execute the command.

}
PROGRAM KERMIT (input, output, keyboard);

import  terminal,               { for the SerialFlush error recovery }
        krmguts,
        command,
        krmrpt,
        iodeclarations,
        general_3;
        
const

{ Command keyword values.  Each defined command has an associated value that
  is returned by parse when its keyword is parsed.
}
cmd_exit = 1;
cmd_receive = 2;
cmd_send = 3;
cmd_set = 4;
cmd_show = 5;
cmd_tn = 6;
  
set_debug = 1;                  { options of the set command }
set_half = 2;
set_log = 3;
set_verb = 4;

var
  ck : keyword_table_ptr;       { pointer to command keyword table }
  setk : keyword_table_ptr;     { pointer to set option keyword table }
  prompt, word, report, state_msg : text_string;
  rpos : integer;               { position within report }
  ior : integer;
  deflogfile, logfile : text_string;

procedure initcmd;
  begin
  init_cmd_windows;
  prompt := 'HP-Kermit>';
  
  new(ck);                   { Build the command keyword table }
  ck^[1].ks := 'EXIT';
  ck^[1].kv := cmd_exit;
  ck^[2].ks := 'RECEIVE';
  ck^[2].kv := cmd_receive;
  ck^[3].ks := 'SEND';
  ck^[3].kv := cmd_send;
  ck^[4].ks := 'SET';
  ck^[4].kv := cmd_set;
  ck^[5].ks := 'SHOW';
  ck^[5].kv := cmd_show;
  ck^[6].ks := 'TN';
  ck^[6].kv := cmd_tn;
  ck^[7].ks := '';           { table terminated by null string }
  ck^[7].kv := 0;
  
  new(setk);
  setk^[1].ks := 'DEBUG';
  setk^[1].kv := set_debug;
  setk^[2].ks := 'HALFDUPLEX';
  setk^[2].kv := set_half;
  setk^[3].ks := 'LOGFILE';
  setk^[3].kv := set_log;
  setk^[4].ks := 'VERBOSITY';
  setk^[4].kv := set_verb;
  setk^[5].ks := '';
  setk^[5].kv := 0;
  
  end;  { procedure initcmd }

{

proc_command    Process command line.

Reads a command line and searches the keyword table pointed to by ck.
Decodes the keyword, and reads the proper arguments, and branches to
the associated action routine.  Returns true if the command indicated
that the program should exit (eg, EXIT command).
}
function proc_command : boolean;
  label 1000;
  var done : boolean;
      files : filename_list;
      setflag : integer;
  begin
  done := false;
  parse_init(prompt);
  parse_keyword_table := ck;       { use command keyword table }
  parse(p_keyword, required);
  state_msg := 'parsing command keyword'; 
  if check_error( parse_result, state_msg )
     then goto 1000;
  
  setstrlen(report,0);
  case arg_integer of
    cmd_exit    :       done := true;
    cmd_receive :       begin
           parse(p_text, required);
           if check_error( parse_result, parse_result_str)
              then goto 1000;
           parse(p_eol, optional);
           files[1] := arg_text;        { get file name to receive }
           setstrlen(files[2],0);
           RunType := Receive;
           RecvSwitch( files );         { receive the file }
           end;  { receive }
    cmd_send    :       begin
           parse( p_text, required );
           if check_error( parse_result, parse_result_str)
              then goto 1000;
           parse(p_eol, required);
           files[1] := arg_text;        { get file name to send }
           setstrlen(files[2],0);
           RunType := Transmit;
           SendSwitch( files );         { send the file }
           end;  { send }
    cmd_set     :     begin
           parse_keyword_table := setk;
           parse( p_keyword, required );
           if check_error(parse_result, parse_result_str)
              then goto 1000;
           setflag := arg_integer;
           if setflag in [set_debug, set_half, set_verb]
              then begin
                parse(p_boolean, required);
                if check_error(parse_result, parse_result_str)
                   then goto 1000;
              end;
           if setflag = set_log
              then begin  { read log file name }
                arg_text := '';
                parse(p_text, optional);
                if check_error(parse_result, parse_result_str)
                   then goto 1000;
              end;  { read log file name }
           parse(p_eol, required);
           case setflag of
              set_debug :  debug := arg_boolean;
              set_half  :  {halfduplex := arg_boolean};
              set_log   :  set_logfile(arg_text);
              set_verb  :  verbosity := arg_boolean;
              end;  { case }
    
           end;  { set }
    cmd_show  :  begin
           parse(p_eol,required);
           clear_status_window;
           setstrlen(report,0);
           strwrite(report,1,rpos,'Verbosity    ',verbosity);
           report_status(report);
           setstrlen(report,0);
           strwrite(report,1,rpos,'Debug        ',debug);
           report_status(report);
           setstrlen(report,0);
           get_logfile(logfile);
           strwrite(report,1,rpos,'Log file     ',logfile);
           report_status(report);
           end;  { show }
    cmd_tn      :     begin
           TN;                          { connect to the host }
           end;  { tn }
    end;  { case }
1000:
  proc_command := done;
  end;  { procedure proc_command }

{ Main Program }
 BEGIN
 try
   SYSInit;                     { do system dependent initialization }
   ParmInit;                    { initialize parameters to defaults }
   OneWayOnly := false;
   Verbosity := FALSE;           { default to false / only valid if local }
   Debug := FALSE;
   deflogfile := '';
   set_logfile( deflogfile );
   
   initcmd;                     { initialize command processor }
   
repeat
   KermitInit;                  { initialize protocol machine and }
                                { default options}
    
until proc_command;             { parse command and dispatch to
                                  proper command action routine }


recover
   begin
   writeln;
   if escapecode = ioescapecode
      then begin                { I/O library error occurred }
           writeln(ioerror_message(ioe_result));
           if ioe_result = 5    { if buffer overflowed }
              then begin
                   writeln;
                   write(' Serial input buffer overflow :  size = ');
                   writeln( SerialData );
                   writeln('Flushing input buffer');
                   SerialFlush;
                   end
              else escape(ioescapecode);
           end         { I/O library error occurred }
                 
      else begin                { not I/O library error }
         if escapecode = -10
            then begin
              ior := ioresult;
              writeln('I/O error #',ior:4);
              end
            else escape(escapecode);
         end;  { not I/O library error }
   end;   { recover }

END.    { Program KERMIT }

