home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c / ucapp2.pas < prev    next >
Pascal/Delphi Source File  |  2020-01-01  |  186KB  |  5,642 lines

  1. (*=== KERMIT.TEXT ===*)
  2. (* >>>>>>>> KERMIT.TEXT ***********************************************)
  3.  
  4. (*$S+*)
  5. (*$I-*)
  6. (*$R-*)
  7. (*$V-*) 
  8.  
  9. PROGRAM kermit;
  10.  
  11.  
  12. USES  kermglob,
  13.       kermacia,
  14.       kermutil,
  15.       kermpack,
  16.       kermsetshw,
  17.       sender,
  18.       receiver,
  19.       helper,
  20.       kerminit,
  21.       parser;
  22.  
  23. PROCEDURE kermterm(BS_to_DEL, Esc_Char, Xon_Char, Xoff_Char : CHAR;
  24.                    Xoff_W_Time : INTEGER;
  25.                    No_Ffeed,Print, Half_Duplex ,
  26.                    Reject_Cntrl_Char, Emulate : BOOLEAN); FORWARD;
  27.  
  28.  
  29.  
  30.  
  31. SEGMENT PROCEDURE Connect;
  32.  
  33. VAR Close_Term, Print : BOOLEAN;
  34.     Ch : CHAR;
  35.     SSC_pass : PACKED ARRAY[0..1] OF CHAR;
  36.  
  37. PROCEDURE Switch_Printer;
  38. BEGIN
  39.   IF Print_enable THEN
  40.     BEGIN
  41.       WRITE('Screendump is ');
  42.       IF Ch = 'P' THEN BEGIN
  43.                          Print := TRUE;
  44.                          WRITELN('on');
  45.                        END
  46.                   ELSE BEGIN
  47.                          WRITELN(Pr);
  48.                          WRITELN('off');
  49.                          Print := FALSE;
  50.                        END;
  51.     END;
  52. END;
  53.       
  54.       
  55. PROCEDURE Show_List;
  56. BEGIN
  57.   WRITELN;
  58.   WRITELN('<?>   Show this list.');
  59.   WRITELN('<S>   Show all current Kermit parameter settings.');
  60.   WRITELN('<C>   Close connection and return to Kermit UCSD command level.');
  61.   Write_Ctl( Esc_Char );
  62.   WRITELN(' Send escape character itself to the remote host.');
  63.   IF ( Acia_implem = A6551 ) OR ( Acia_implem = A6850 )  THEN
  64.     BEGIN
  65.       IF Acia_implem = A6551 THEN
  66.       BEGIN
  67.         WRITE('<Z>   Tell Super Serial Card to pass <^A> to host for ');
  68.                      WRITELN('correct file transfer.');
  69.       END;
  70.       WRITELN('<B>   Send a break signal to the remote host.');
  71.       WRITELN('      Hit any key to turn off break signal.');
  72.     END;
  73.   IF Print_enable THEN
  74.     BEGIN
  75.      WRITELN;
  76.      WRITELN('<P>   Screen output also to printer.');
  77.      WRITELN('<Q>   Turnoff screendump.');
  78.     END;
  79. END;
  80.  
  81.     
  82. BEGIN
  83.   Close_Term := FALSE; Print := FALSE; Ch := ' ';
  84.   SSC_pass[0] := CHR(1); SSC_pass[1] := 'Z';
  85.   PAGE( Output );
  86.   WRITE('>Kermterm connecting to host   (type '); Write_Ctl(Esc_Char);
  87.   WRITELN(' <C> to exit)');
  88.   UNITCLEAR( Inport );
  89.   REPEAT
  90.     UNITCLEAR( Keyport );
  91.     Kermterm(BS_to_DEL, Esc_Char, Xon_Char, Xoff_Char, Xoff_W_Time,
  92.              No_Ffeed, Print, Half_Duplex, Reject_Cntrl_Char, Emulate );
  93.     REPEAT
  94.     WRITELN; WRITE('>Kermterm (<?> <B> <C> <P> <Q> <S> <Z>) =>');
  95.     UNITCLEAR( Keyport );
  96.     UNITREAD( Keyport, Ch, 1 ); WRITELN;
  97.     IF Ch IN ['a'..'z'] THEN Ch := CHR( ORD(Ch) - ORD('a') + ORD('A') );
  98.     IF Ch IN ['B','C','P','Q','S','Z','?' ]
  99.       THEN CASE Ch OF
  100.            'B' : Send_Break( Acia_Comm_Reg );
  101.            'C' : Close_Term := TRUE;
  102.        'P','Q' : Switch_Printer;
  103.            'S' : BEGIN Noun := All_Sym; Show_Parms END;
  104.            'Z' : UNITWRITE( Outport, SSC_pass, 2,, 12);
  105.            '?' : Show_List;
  106.            END; (* of then case *)
  107.     UNTIL Ch <> '?';
  108.     IF Ch = Esc_Char THEN UNITWRITE( Outport, Ch, 1,, 12 );
  109.     IF NOT Close_Term THEN WRITELN('Back to host.');
  110.   UNTIL Close_Term;
  111.   WRITELN('Back to Apple Kermit UCSD')
  112. END;
  113.  
  114.  
  115. PROCEDURE Kermterm; EXTERNAL;
  116.  
  117.  
  118. PROCEDURE closeup;
  119.  
  120. begin
  121.   check_apple_char( all_sp_char );
  122.   page( output )
  123. end; (* closeup *)
  124.  
  125.  
  126. begin (* main kermit program *)
  127.   {$N+}
  128.   {$R kermglob,kermacia,kermutil,kermpack,kermsetshw,parser }
  129.  initialize;
  130.  repeat
  131.    write('Kermit-UCSD> ');
  132.    read_str(line);
  133.    case parse of
  134.      unconfirmed   : writeln('Unconfirmed');
  135.      parm_expected : writeln('Parameter expected');
  136.      ambiguous     : writeln('Ambiguous');
  137.      unrec         : writeln('Unrecognized command');
  138.      fn_expected   : writeln('File name expected');
  139.      pn_expected   : writeln('Volume name expected');
  140.      ch_expected   : writeln('Single character expected');
  141.      num_expected  : writeln('Number > 0 expected');
  142.      null          : case verb of
  143.                        consym   : connect;
  144.              phelpsym, helpsym  : help;
  145.                        recsym   : begin
  146.                                     rec_sw( rec_ok );
  147.                                     write( chr(bell) );
  148.                                     gotoxy( 0, prompt_line - 1 );
  149.                                     if not rec_ok then write('Un');
  150.                                     write( 'succesfull receive' );
  151.                                     close( rec_file, lock ); 
  152.                                     gotoxy( 0, prompt_line );
  153.                                   end;
  154.                        sendsym  : begin
  155.                                     send_sw( send_ok );
  156.                                     write( chr(bell) );
  157.                                     gotoxy( 0, prompt_line - 1 );
  158.                                     if not send_ok then write('Un');
  159.                                     write('succesfull send');
  160.                                     close( applefile ); 
  161.                                     gotoxy( 0, prompt_line );
  162.                                   end;
  163.                        setsym   : set_parms;
  164.               dirsym, pdirsym,
  165.            pshowsym, show_sym   : show_parms;
  166.                      end; (* case verb *)
  167.    end; (* case parse *)
  168.  until (verb = exitsym) or (verb = quitsym);
  169.  closeup
  170. end. (* kermit *)
  171.  
  172. (*=== KERMGLOB.TEXT ===*)
  173. (* >>>> KERMGLOB.TEXT  ************************************************)
  174.  
  175. (*$S+*)
  176. (*$I-*)
  177. (*$R-*)
  178. (*$V-*)
  179.  
  180. UNIT kermglob;   INTRINSIC CODE 16   DATA  17;
  181.  
  182. INTERFACE
  183.  
  184.   CONST version = 'RUG/PT 1.0';
  185.         cs_file = 'CONSOLE:';
  186.         pr_file = 'PRINTER:';
  187.         setup_file = '*KERMIT.DATA';
  188.         sys_misc_file = '*SYSTEM.MISCINFO';
  189.         blk_size = 512;
  190.         page_size = 1024;
  191.         outport = 8;        (* output port #  remout*)
  192.         inport = 7;         (* input  port #  remin *)
  193.         keyport = 2;
  194.         consol  = 1;
  195.         line_printer = 6;
  196.         bell = 7;           (* ASCII bell *)
  197.         linefeed = 10;      (* ASCII line feed *)
  198.         formfeed = 12;      (* ASCII formfeed *)
  199.         backspace = 8;      (* ASCII backspace *)
  200.         del = 127;          (* ASCII delete char *)
  201.         xdle = 16;          (* ASCII DLE *)
  202.                             (* space compression prefix for p_system *)
  203.         eoline = 13;        (* end of line character  *)
  204.         at_eof = -1;        (* value to return if at eof *)
  205.         def_maxpack = 94;   (* default max packet size I can handle *)
  206.         max_buf = 96;       (* max packetsize(94) + 2 *)
  207.  
  208.     (* screen control information *)
  209.     (* console line on which to put specified info *)
  210.     
  211.         title_line = 0;
  212.         status_line = 2;
  213.         packet_line = 3;
  214.         retry_line = 5;
  215.         file_line = 7;
  216.         error_line = 8;
  217.         debug_line = 10;
  218.         pack_line = 13;
  219.         ack_line = 17;
  220.         prompt_line = 23;
  221.     (* position on line to put info *)
  222.         statuspos = 36;
  223.         packet_pos = 19;
  224.         retry_pos = 17;
  225.         file_pos = 11;
  226.         
  227. (*-------------------------------------------------------------------*)
  228.  
  229. TYPE packettype = packed array[ 0..maxbuf ] of char;
  230.  
  231.      parity_type = (nopar, oddpar, evenpar, markpar, spacepar);
  232.  
  233.      statustype = (null, at_eol, unconfirmed, parm_expected, ambiguous,
  234.                    unrec, fn_expected, pn_expected, ch_expected, num_expected);
  235.                    
  236.      vocab = (nullsym, allsym, baudsym, consym, debugsym, delsym, dirsym,
  237.               emulatesym, eolnsym, escsym, evensym, exitsym, filewarnsym,
  238.               helpsym, ibmsym, localsym, marksym, maxtrysym, maxpsym, nofeedsym,
  239.               nonesym, oddsym, offsym, onsym, paritysym, pdirsym, phelpsym,
  240.               prefixsym, pshowsym, quitsym, recsym, rejectsym, sendsym,
  241.               setsym, showsym, spacesym, stopbsym, textfsym, timeoutsym,
  242.               wordlensym, xoffsym, xoffwaitsym, xonsym);
  243.  
  244.      scrcommands = (sc_up, sc_right, sc_clreol, sc_clreos, sc_home,
  245.                     sc_delchar, sc_clrall, sc_clrline, sc_left, sc_down);
  246.                     
  247.      rem_stat_rec = (all_sp_char, stop_flush_break_sp_char, scr_40_sp_char,
  248.                      no_sp_char, mask_msbit_remin, no_mask_msbit_remin);
  249.                      
  250.      cntrl_word_rec = packed record
  251.                          channel    : ( out, inp );
  252.                          purpose    : ( status, control );
  253.                          reserved   :   0..2047  ;
  254.                          special_req: ( none, rw_req );
  255.                          filler     :   0..3 ;
  256.                       end;
  257.      
  258.      acia_type   =  ( unknown, A6551, A6850, Fut1, Fut2, Fut3 );
  259.                        
  260. (*--------------------------------------------------------------------*)
  261.  
  262. VAR rec_pkt, packet  : packet_type;
  263.  
  264.     noun, verb, adj: vocab;
  265.  
  266.     vocablist: ARRAY[vocab] OF STRING;
  267.     
  268.     err_string, prefix_vol, newprefix_vol, xfilename, line: STRING;
  269.     
  270.     newescchar, escchar, bstodel, newxonchar, xonchar, newxoffchar, xoffchar,
  271.     newxeolchar, xeolchar, eolnchar, sohchar, mypchar, padchar, quote,
  272.     currstate, prefix, rlf, ndfs, eraseol, eraseos, home, delchar, clrscreen,
  273.     clrline, backsp, lf, cr, ff, xdle_char, int_key, my_quote : CHAR;
  274.     
  275.     expected: SET OF vocab;
  276.     ctl_set, ctlq_set : SET OF CHAR;
  277.     
  278.     my_time, max_try, init_try,  data_bit, stop_bit, baud, newdbit, newstopbit,
  279.     newbaud, xoffwtime, newxoffwait, newtimeout, newmaxtry, vol_num, crpos,
  280.     bufpos, bufend, maxpack,mypad, pad, xtime, errplen, iostatus,
  281.     acia_cntrl_reg, acia_comm_reg, temp, new_maxpack, spsiz, max1_data,
  282.     max2_data : INTEGER;
  283.   
  284.     def : FILE OF INTEGER;   (* setup file at init  *)
  285.     p, pr : INTERACTIVE; (* printer or console file *)
  286.     untyped_f, apple_file, rec_file : FILE;
  287.     
  288.     reject_cntrl_char, fwarn, ibm, half_duplex, debug, pr_out,
  289.     text_file, print_enable, no_ffeed,  send_ok, rec_ok, dle_flag, emulate
  290.      : BOOLEAN;
  291.     
  292.     acia_implem : acia_type;
  293.     
  294.     new_par, parity : parity_type;
  295.     
  296.     control_word : cntrl_word_rec;
  297.     
  298.     no_sfb_char, sfb_char : rem_stat_rec;
  299.     
  300.     prefixed : ARRAY[scr_commands] OF BOOLEAN;
  301.     
  302.     filebuf: PACKED ARRAY[1..page_size] OF CHAR;
  303.  
  304. (*-----------------------------------------------------------------------*)
  305.  
  306. PROCEDURE Dummy;
  307.  
  308. IMPLEMENTATION
  309.  
  310. PROCEDURE dummy;
  311. begin
  312. end;
  313.     
  314. BEGIN
  315. END. { kermglob }
  316.  
  317. (*=== KERMACIA.TEXT ===*)
  318. (************* UNIT KERMACIA ********************************************)
  319.  
  320. (*$S+*)
  321. (*$I-*)
  322. (*$R-*)
  323. (*$V-*)
  324.  
  325. UNIT KERMACIA;  intrinsic code 18   data 19;
  326.  
  327.  
  328. INTERFACE
  329.  
  330. USES  kermglob;
  331.  
  332. PROCEDURE send_break ( adr_comm_reg : integer );
  333.  
  334. PROCEDURE get_acia_parms( var xpar : parity_type;
  335.                           var xdbit, xstopbit, xbaud : integer );
  336.                           
  337. PROCEDURE set_acia_parms(  xpar : parity_type;
  338.                            xdbit, xstopbit, xbaud : integer );
  339.                           
  340. IMPLEMENTATION
  341.  
  342. { This unit implements the possibility to change baud rates, parity, number }
  343. { of databits and stopbits  for outgoing characters and the possibility to  }
  344. { send a break signal to the remote host.                                   }
  345. { This unit is dependent on a special unitstatus call, provided by the      }
  346. { attached driver for remin: ( see file remdriver.text ).                   }
  347. { The code below is specific for the 6551 acia on a AP2 serial card from IBS}
  348. { and for the 6850 acia on a CCS model 7710 ASI1 card, that is probably     }
  349. { similar to the Apple Com Card and the Hayes micromodem card.              }
  350. { On the CCS card it is not possible to change the baud rate by soft command}
  351. { nor is it possible to set space parity.                                   }
  352. { If you have a different serial card then this unit should be adapted to   }
  353. { the requirements of that card's acia. If you do not know how to or do not }
  354. { want to rewrite this unit's implementation, then you can set the value of }
  355. { 'acia_implem' in the kermit.data file to 0 (= unknown). The settable      }
  356. { parameters   will then equal the default values , but can no longer be    }
  357. { changed at run time. The procedure send_break will then do nothing.       } 
  358.  
  359. {     acia_cntrl_reg   = -16209;     =$C0AF  Specific for a 6551 acia on a  }
  360. {     acia_comm_reg    = -16210;     =$C0AE  AP2 serial card in slot 2.     }
  361. {     acia_comm_reg    = -16224;     =$C0A0  Specific for CCS 6850  acia.   }
  362. {                                            The 6850 does not have a       }
  363. {                                            control register.              }
  364. { These 2 adresses are declared in unit kermglob.                           }
  365. { If your card also has a 6551  acia then these adresses will               }
  366. { probably be different. They can then be changed in the kermit.data file.  }
  367.        
  368. TYPE   baud_types      = (B16ext, B50, B75, B110, B135, B150, B300, B600,
  369.                           B1200, B1800, B2400, B3600, B4800, B7200, B9600,
  370.                           B19200);  { 6551 specific }
  371.                           
  372.        dbit_types      = (dbit8, dbit7, dbit6, dbit5 ); { 6551 specific }
  373.        
  374.        cntrl_6551      = PACKED RECORD
  375.                           baudr  : baud_types;
  376.                           freq   : ( ext, int );
  377.                           wordlen: dbit_types;
  378.                           stpbit : ( one, variable );
  379.                           msb1   : 0..255 ;
  380.                          END;
  381.        
  382.        comm_6551       = PACKED RECORD
  383.                           dont_change :  0..31 ;
  384.                           set_par     :  BOOLEAN;
  385.                           par_type    : ( p_odd, p_even, p_mark, p_space );
  386.                           msb2        :  0..255 ;
  387.                          END;
  388.        
  389.        comm_6850       = PACKED RECORD
  390.                           filler1     :  0..3 ;
  391.                           serdata     : ( d7pes2, d7pos2, d7pes1, d7pos1,
  392.                                           d8pns2, d8pns1, d8pes1, d8pos1 );
  393.                 { d=databits, p=parity, e=even, o=odd, n=none, s=stopbit }
  394.                           filler2     :  0..7 ;
  395.                           msb3        :  0..255;
  396.                          END;
  397.        
  398.        stat_rec1      =  RECORD
  399.                           adres1   : INTEGER;
  400.                           content1 : cntrl_6551;
  401.                          END;
  402.                          
  403.        stat_rec2      =  RECORD
  404.                           adres2   : INTEGER;
  405.                           content2 : comm_6551;
  406.                          END;
  407.        
  408.        stat_rec3      =  RECORD
  409.                           adres3   : INTEGER;
  410.                           content3 : comm_6850;
  411.                          END;
  412.                          
  413. VAR    baud_rate             : ARRAY[ baud_types ] OF INTEGER;
  414.        dbits                 : ARRAY[ dbit_types ] OF INTEGER;
  415.        reg_6551_control      : stat_rec1;
  416.        reg_6551_komm         : stat_rec2;
  417.        reg_6850_comm         : stat_rec3;
  418.        cw_status, cw_control : cntrl_word_rec;
  419.        
  420.        
  421.  
  422.  
  423. PROCEDURE get_6551_parms ( var xpar:parity_type; 
  424.                            var xdbit, xstopbit, xbaud : integer );
  425.  
  426. BEGIN
  427.   reg_6551_control.adres1 := acia_cntrl_reg;
  428.   reg_6551_komm.adres2    := acia_comm_reg;
  429.   UNITSTATUS( inport, reg_6551_control, cw_status );
  430.   UNITSTATUS( inport, reg_6551_komm,    cw_status );
  431.   WITH reg_6551_komm.content2 DO
  432.     BEGIN
  433.       IF set_par THEN BEGIN
  434.                         CASE par_type OF
  435.                           p_odd    : xpar := odd_par;
  436.                           p_even   : xpar := even_par;
  437.                           p_mark   : xpar := mark_par;
  438.                           p_space  : xpar := space_par;
  439.                         END;
  440.                       END
  441.                  ELSE xpar := no_par;
  442.     END; { with }
  443.   WITH reg_6551_control.content1 DO
  444.     BEGIN
  445.       xbaud  := baud_rate[ baudr ];
  446.       xdbit  := dbits[ wordlen ];
  447.       CASE stpbit OF
  448.         one      : xstopbit := 1;
  449.         variable : BEGIN
  450.                      xstopbit := 2;
  451.                      IF ( xpar <> no_par ) and ( word_len = dbit8 )
  452.                        THEN xstopbit := 1;
  453.                      IF ( xpar =  no_par ) and ( word_len = dbit5 )
  454.                        THEN xstopbit := 15;
  455.                    END;
  456.       END; { case stpbit }
  457.     END; { with }
  458. END; { get_6551_parms }
  459.  
  460. { NOTE : xstopbit = 15 actually means 1.5 stopbit }
  461.  
  462.  
  463.  
  464.  
  465. PROCEDURE get_acia_parms{ var xpar:parity_type;
  466.                           var xdbit,xstopbit,xbaud : integer};
  467.  
  468. begin
  469.   if acia_implem = A6551 then get_6551_parms( xpar, xdbit, xstopbit, xbaud );
  470. end;  { get_acia_parms }
  471.  
  472.  
  473.  
  474. PROCEDURE set_6551_parms (  xpar:parity_type;
  475.                             xdbit, xstopbit, xbaud : integer );
  476.  
  477. VAR oldpar : parity_type;
  478.     oldbaud, olddbit, oldstopb : INTEGER;
  479.     i : baud_types;
  480.     j : dbit_types;
  481.     
  482. BEGIN
  483.    get_6551_parms( oldpar, olddbit, oldstopb, oldbaud );
  484.    WITH reg_6551_komm.content2 DO
  485.      BEGIN
  486.        set_par := TRUE;
  487.        CASE xpar OF
  488.          no_par    : set_par  := FALSE;
  489.          odd_par   : par_type := p_odd;
  490.          even_par  : par_type := p_even;
  491.          mark_par  : par_type := p_mark;
  492.          space_par : par_type := p_space;
  493.        END; { case }
  494.      END; { with }
  495.    UNITSTATUS( inport, reg_6551_komm, cw_control );
  496.    WITH reg_6551_control.content1 DO
  497.      BEGIN
  498.        FOR i := B50 TO B19200 DO IF baud_rate[ i ] = xbaud THEN baudr := i;
  499.        FOR j := dbit8 TO dbit5 DO IF dbits[ j ] = xdbit THEN word_len := j;
  500.        IF xstopbit = 1 THEN stpbit := one
  501.                        ELSE stpbit := variable;
  502.      END; { with  }
  503.    UNITSTATUS( inport, reg_6551_control, cw_control );
  504. END; { set_6551_parms }
  505.  
  506.  
  507. PROCEDURE set_6850_parms(  xpar:parity_type; xdbit,xstop : integer);
  508.  
  509. BEGIN
  510.   WITH reg_6850_comm.content3 DO
  511.     BEGIN
  512.       IF (xdbit=7) and (xpar=evenpar) and (xstop=1) THEN serdata := d7pes1 ELSE
  513.       IF (xdbit=7) and (xpar= oddpar) and (xstop=1) THEN serdata := d7pos1 ELSE
  514.       IF (xdbit=7) and (xpar=evenpar) and (xstop=2) THEN serdata := d7pes2 ELSE
  515.       IF (xdbit=7) and (xpar= oddpar) and (xstop=2) THEN serdata := d7pos2 ELSE
  516.       IF (xdbit=8) and (xpar=markpar) and (xstop=1) THEN serdata := d8pns2 ELSE
  517.       IF (xdbit=8) and (xpar=  nopar) and (xstop=1) THEN serdata := d8pns1 ELSE
  518.       IF (xdbit=8) and (xpar= oddpar) and (xstop=1) THEN serdata := d8pos1 ELSE
  519.       IF (xdbit=8) and (xpar=evenpar) and (xstop=1) THEN serdata := d8pes1 ELSE
  520.       EXIT( set_6850_parms );
  521.     END;  { WITH }
  522.   reg_6850_comm.content3.filler1 := 3;
  523.   reg_6850_comm.content3.filler2 := 0;
  524.   reg_6850_comm.adres3 := acia_comm_reg;
  525.   UNITSTATUS( inport, reg_6850_comm, cw_control );
  526.   { first give an acia master reset }
  527.   reg_6850_comm.content3.filler1 := 1;
  528.   UNITSTATUS( inport, reg_6850_comm, cw_control );
  529.   { set acia command register to desired value }
  530.   parity := xpar;
  531.   stopbit := xstop;
  532.   databit := xdbit;
  533. END;  { set_6850_parms }
  534.  
  535.  
  536. PROCEDURE set_acia_parms {  xpar : parity_type;
  537.                             xdbit, xstopbit, xbaud : integer };
  538.  
  539. begin
  540.   case acia_implem of
  541.     A6551 : set_6551_parms( xpar, xdbit, xstopbit, xbaud );
  542.     A6850 : set_6850_parms( xpar, xdbit, xstopbit );
  543.   end;
  544. end;   { set_acia_parms }
  545.           
  546.           
  547.           
  548. PROCEDURE  send_6551_break ( adr_comm_reg : INTEGER ); EXTERNAL;
  549. PROCEDURE  send_6850_break ( adr_comm_reg : INTEGER ); EXTERNAL;
  550. { See file asm.acia.text }
  551.  
  552. PROCEDURE send_break { adr_comm_reg : integer };
  553.  
  554. { sends a break signal to the host. Signal is shut off by typing any key. }
  555. { The command register is restored to the previous value.                 }
  556.  
  557. begin
  558.   case acia_implem of
  559.     A6551 : send_6551_break( adr_comm_reg );
  560.     A6850 : begin
  561.               send_6850_break( adr_comm_reg );
  562.               set_acia_parms( parity, databit, stopbit, baud );
  563.             end;
  564.   end;
  565. end;   { send_break }
  566.  
  567.  
  568.  
  569. BEGIN
  570.   baud_rate[ B16ext ] :=     0;
  571.   baud_rate[ B50    ] :=    50;
  572.   baud_rate[ B75    ] :=    75;
  573.   baud_rate[ B110   ] :=   110;
  574.   baud_rate[ B135   ] :=   135;
  575.   baud_rate[ B150   ] :=   150;
  576.   baud_rate[ B300   ] :=   300;
  577.   baud_rate[ B600   ] :=   600;
  578.   baud_rate[ B1200  ] :=  1200;
  579.   baud_rate[ B1800  ] :=  1800;
  580.   baud_rate[ B2400  ] :=  2400;
  581.   baud_rate[ B3600  ] :=  3600;
  582.   baud_rate[ B4800  ] :=  4800;
  583.   baud_rate[ B7200  ] :=  7200;
  584.   baud_rate[ B9600  ] :=  9600;
  585.   baud_rate[ B19200 ] := 19200;
  586.   dbits[ dbit8 ] := 8;
  587.   dbits[ dbit7 ] := 7;
  588.   dbits[ dbit6 ] := 6;
  589.   dbits[ dbit5 ] := 5;
  590.   WITH cw_status DO
  591.     BEGIN
  592.       channel      := inp;
  593.       purpose      := status;
  594.       special_req  := rw_req;
  595.       reserved     := 0;
  596.       filler       := 0;
  597.     END;
  598.   cw_control := cw_status;
  599.   cw_control.purpose  :=  control;
  600.   { set serial data for 6850 acia to pascal defaults }
  601.   parity := no_par;
  602.   stopbit := 1;
  603.   databit := 8;
  604. END.
  605.  
  606. (*=== KERMUTIL.TEXT ===*)
  607. (*>>>>>>>>>>>>>>KERMUTIL>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*)
  608.  
  609. {$S+}
  610. {$I-}
  611. {$R-}
  612. {$V-}
  613.  
  614. UNIT kermutil;  INTRINSIC CODE 20;
  615.  
  616. INTERFACE
  617.  
  618.    USES  kermglob;
  619.    
  620.    PROCEDURE upper_case( VAR s : STRING );
  621.    
  622.    FUNCTION  interrupt( int_key : CHAR ) : BOOLEAN;
  623.    
  624.    PROCEDURE error(VAR p: packettype; len: INTEGER);
  625.  
  626.    PROCEDURE io_error(i: INTEGER);
  627.  
  628.    PROCEDURE debugwrite( s: STRING);
  629.    
  630.    PROCEDURE packet_write( VAR p : packettype; len : INTEGER );
  631.    
  632.    PROCEDURE ack_write( ptype: CHAR; len,num: INTEGER; VAR data: packettype);
  633.    
  634.    PROCEDURE write_bool( s: STRING; b: BOOLEAN);
  635.    
  636.    PROCEDURE read_str( VAR s : STRING);
  637.    
  638.    PROCEDURE write_ctl( ch : CHAR);
  639.  
  640.    FUNCTION  test_printer : BOOLEAN;
  641.  
  642.    FUNCTION min(x,y: INTEGER): INTEGER;
  643.  
  644.    FUNCTION tochar(ch: CHAR): CHAR;
  645.  
  646.    FUNCTION unchar(ch: CHAR): CHAR;
  647.  
  648.    PROCEDURE screen( scrcmd: scrcommands );
  649.  
  650.    PROCEDURE writescreen( s: STRING);
  651.  
  652.    PROCEDURE refresh_screen(numtry, num: INTEGER);
  653.    
  654.    PROCEDURE check_apple_char( check: rem_stat_rec);
  655.    
  656.    FUNCTION ctl( ch : CHAR ) : CHAR;
  657.    
  658.    FUNCTION calc_checksum( VAR packet: packettype; len : INTEGER ) : CHAR;
  659.  
  660.  
  661. IMPLEMENTATION
  662.  
  663. PROCEDURE uppercase {var s: string};
  664.  
  665. var i: integer;
  666.  
  667. begin
  668.  for i := 1 to length(s) do
  669.      if s[i] in ['a'..'z'] then
  670.          s[i] := chr(ord(s[i]) - ord('a') + ord('A'))
  671. end; (* uppercase *)
  672.  
  673.  
  674.  
  675. FUNCTION interrupt{ (int_key : char) : boolean };
  676.  
  677. var buflen : packed array[0..7] of 0..255;
  678.     ch : char;
  679.  
  680. begin
  681.   interrupt := false;  ch := ' ';
  682.   unitstatus( keyport, buflen[0], control_word );
  683.   if buflen[0] > 0
  684.     then begin
  685.            unitread( keyport, ch, 1,, 12 );
  686.            if ch = int_key then interrupt := true;
  687.          end;
  688. end;   {  interrupt  }
  689.  
  690.  
  691.  
  692. PROCEDURE screen{ scrcmd: scr_commands };
  693.  
  694. begin
  695.   if prefixed[ scrcmd ] then unitwrite( consol, prefix, 1,,12 );
  696.   case scrcmd of
  697.      sc_up      : unitwrite( consol, rlf      , 1,,12 );
  698.      sc_right   : unitwrite( consol, ndfs     , 1,,12 );
  699.      sc_clreol  : unitwrite( consol, eraseol  , 1,,12 );
  700.      sc_clreos  : unitwrite( consol, eraseos  , 1,,12 );
  701.      sc_home    : unitwrite( consol, home     , 1,,12 );
  702.      sc_delchar : unitwrite( consol, delchar  , 1,,12 );
  703.      sc_clrall  : unitwrite( consol, clrscreen, 1,,12 );
  704.      sc_clrline : unitwrite( consol, clrline  , 1,,12 );
  705.      sc_left    : unitwrite( consol, backsp   , 1,,12 );
  706.      sc_down    : unitwrite( consol, lf       , 1,,12 );
  707.   end; { case }
  708. end; { procedure screen }
  709.  
  710.  
  711.  
  712. PROCEDURE error{ var p: packettype; len: integer };
  713.  
  714. (* writes error message sent by remote host *)
  715.  
  716. begin
  717.   gotoxy(0,errorline);
  718.   screen( sc_clreol );
  719.   write('Host error : ');
  720.   unitwrite( consol, p[0], len,, 12 );
  721.   gotoxy(0,promptline);
  722. end; (* error *)
  723.  
  724.  
  725.  
  726. PROCEDURE io_error{ i: integer };
  727.  
  728. begin
  729.  gotoxy( 0, errorline );
  730.  screen( sc_clreol );
  731.  write('IO_ERROR : ');
  732.  case i of
  733.       0: writeln('No error');
  734.       1: writeln('Bad Block, Parity error (CRC)'); {not used for Apple}
  735.       2: writeln('Bad Unit Number');
  736.       3: writeln('Bad Mode, Illegal operation');
  737.       4: writeln('Undefined hardware error'); {not used for Apple}
  738.       5: writeln('Lost unit, Unit is no longer on-line');
  739.       6: writeln('Lost file, File is no longer in directory');
  740.       7: writeln('Bad Title, Illegal file name');
  741.       8: writeln('No room, insufficient space');
  742.       9: writeln('No unit, No such volume on line');
  743.      10: writeln('No file, No such file on volume');
  744.      11: writeln('Duplicate file');
  745.      12: writeln('Not closed, attempt to open an open file');
  746.      13: writeln('Not open, attempt to close a closed file');
  747.      14: writeln('Bad format, error in reading real or integer');
  748.      15: writeln('Ring buffer overflow');
  749.      16: writeln('Diskette is write protected');
  750.    end; (* case *)
  751.  if i = 64 then writeln('Bad block on diskette');
  752.  gotoxy(0,promptline)
  753. end; (* io_error *)
  754.  
  755.  
  756.  
  757. PROCEDURE debugwrite{  s: string };
  758.  
  759. (* writes a debugging message *)
  760.  
  761. var j: integer;
  762.  
  763. begin
  764.   gotoxy( 0, debug_line );
  765.   screen( sc_clreol );
  766.   write('Debug state is ', s );
  767. end; (* debugwrite *)
  768.  
  769.  
  770. PROCEDURE packet_write{  var p:packettype; len: integer };
  771.  
  772. (* writes a packet to the screen for debugging purposes *)
  773.  
  774. var i : integer;
  775.  
  776. begin
  777.   gotoxy( 0, pack_line + 2 ); screen( sc_clreol ); gotoxy( 0, pack_line + 1 );
  778.   screen( sc_clreol );
  779.   unitwrite( consol, p[1], ( len-2 ), , 12 );
  780. end; { packet_write }
  781.  
  782.  
  783.  
  784. PROCEDURE ack_write{ ptype: char; len,num: integer; var data: packettype};
  785.  
  786. (* writes a ack/nack package to the screen for debugging purposes *)
  787.  
  788. var i : integer;
  789.  
  790. begin
  791.   gotoxy( 0, ack_line + 1 ); 
  792.   screen( sc_clreos );
  793.   writeln('type= ',ptype);
  794.   writeln('num = ',num);
  795.   writeln('len = ',len);
  796.   unitwrite(consol, data[0], len,, 12 );
  797. end;  { ack_write }
  798.  
  799. PROCEDURE write_bool{ s: string; b: boolean};
  800.  
  801. (* writes message & 'on' if b, 'off' if not b *)
  802.  
  803. begin
  804.   write(p, s);
  805.   case b of
  806.       true: writeln(p,'ON');
  807.       false: writeln(p,'OFF');
  808.     end; (* case *)
  809. end; (* write_bool *)
  810.  
  811.  
  812.  
  813. PROCEDURE write_ctl{ ch : char };
  814.  
  815. begin
  816.   if ord(ch) < 32
  817.    then begin
  818.           if ord(ch) = 27  then write(p,'<ESC>')
  819.                            else write(p,'<^',chr(ord(ch)+64),'> ');
  820.         end
  821.    else begin
  822.           if ord(ch) = 127 then write(p,'<DEL>')
  823.                            else write(p,'<',ch,'>  ');
  824.         end;
  825. end;  { write_ctl }
  826.  
  827.  
  828. PROCEDURE read_str{ var s : string };
  829.  
  830. var i, j, k : integer;
  831.          ch : char;
  832.          
  833. begin
  834.   i := 0; s := ''; ch := ' ';
  835.   repeat
  836.     unitread( keyport, ch, 1 );
  837.     if ch = backsp
  838.       then begin
  839.              if i > 0
  840.                then begin
  841.                       if s[i] in ctl_set then j := 5 else j := 1;
  842.                       for k := 1 to j do write( ch, ' ', ch );
  843.                       delete( s, i, 1 );
  844.                       i := i - 1;
  845.                     end;
  846.            end
  847.       else begin
  848.              if  ch  <>  cr
  849.                then begin
  850.                       if i < 80 
  851.                         then begin
  852.                                if ch in ctl_set then write_ctl( ch )
  853.                                                 else write( ch );
  854.                                i := i + 1;
  855.                                s := concat( s, ' ' );
  856.                                s[i] := ch;
  857.                              end
  858.                         else write( chr(bell) );
  859.                     end;
  860.            end;
  861.   until ch = cr;
  862.   writeln;
  863. end;  { read_str }
  864.  
  865.  
  866.  
  867. FUNCTION  test_printer;
  868.  
  869. { this function only tests for the presence of a printerinterface card }
  870.  
  871. begin
  872.   close( pr );
  873.   reset( pr, pr_file );
  874.   test_printer := ( ioresult = 0 );
  875. end;
  876.  
  877.  
  878.  
  879. FUNCTION min{(x,y: integer): integer };
  880.  
  881. (* returns smaller of two integers *)
  882.  
  883. begin
  884.  if x < y then min := x else min := y
  885. end; (* min *)
  886.  
  887.  
  888.  
  889. FUNCTION tochar{ (ch: char): char };
  890.  
  891. (* tochar converts a control character to a printable one by adding space *)
  892.  
  893. begin
  894.  tochar := chr(ord(ch) + ord(' '))
  895. end; (* tochar *)
  896.  
  897.  
  898.  
  899. FUNCTION unchar{ (ch: char): char };
  900.  
  901. (* unchar undoes tochar *)
  902.  
  903. begin
  904.   unchar := chr(ord(ch) - ord(' '))
  905. end; (* unchar *)
  906.  
  907.  
  908.  
  909.  
  910. PROCEDURE writescreen{  s: string };
  911.  
  912. (* sets up the screen for receiving or sending files *)
  913.  
  914. begin
  915.    page(output);
  916.    gotoxy( 11, titleline); write('Kermit UCSD p-System : ', s );
  917.    gotoxy( 50, statusline - 1 );
  918.    write('( type '); write_ctl( int_key );
  919.    write(' to break off )');
  920.    gotoxy(0,packetline);
  921.    write('Number of Packets: ');
  922.    gotoxy(0,retryline);
  923.    write('Number of Tries: ');
  924.    gotoxy(0,fileline);
  925.    write('File Name: ');
  926.    if debug then
  927.      begin
  928.        gotoxy(0,packline);
  929.        write('Outgoing Packet:');
  930.        gotoxy(0,ackline);
  931.        write('Incoming Packet:');
  932.      end;
  933. end; (* writescreen *)
  934.  
  935.  
  936.  
  937. PROCEDURE refresh_screen{ numtry, num: integer };
  938.  
  939. (* keeps track of packet count on screen *)
  940.  
  941. begin
  942.    gotoxy(retrypos,retryline);
  943.    write(numtry: 5);
  944.    gotoxy(packetpos,packetline);
  945.    write(num: 5)
  946. end; (* refresh_screen *)
  947.  
  948.  
  949. PROCEDURE check_apple_char {  check : rem_stat_rec };
  950.  
  951. { this procedure only works with a special implementation of unitstatus }
  952. { in the attached remin driver. special character checking can be turned}
  953. { off or on depending on the value of 'check'. also the remin driver can}
  954. { be instructed to pass 7 or 8 bit characters to pascal.                }
  955.  
  956. var  control_word : cntrl_word_rec;
  957.  
  958. begin
  959.   with control_word do
  960.     begin
  961.       channel := inp;  purpose := control;   special_req := none;
  962.       reserved := 0; filler := 0;
  963.     end;
  964.   unitstatus( inport, check, control_word );
  965. end;  { check_apple_char }
  966.  
  967.  
  968. FUNCTION ctl{ ( ch : char ) : char }; EXTERNAL;
  969.  
  970. { toggles bit 7 of a character: ' controllifies or decontrollifies ' }
  971.  
  972. FUNCTION calc_checksum{ (var packet:packettype; len:integer):char }; EXTERNAL;
  973.  
  974. { calculates one character checksum of a packet }
  975.  
  976.  
  977. begin 
  978. end. { kermutil }
  979.  
  980. (*=== KERMPACK.TEXT ===*)
  981. (* >>>> KERMPACK.TEXT  *************************************************)
  982.  
  983. (*$I-*)
  984. (*$R-*)
  985. (*$S+*)
  986. (*$V-*)
  987.  
  988. UNIT kermpack;  INTRINSIC CODE 21  ;
  989.  
  990.  
  991. INTERFACE
  992.  
  993. USES  kermglob,
  994.       kermutil;
  995.  
  996.  
  997. PROCEDURE spar;
  998.  
  999. PROCEDURE rpar;
  1000.  
  1001. PROCEDURE spack( ptype: CHAR; num, len: INTEGER );
  1002.  
  1003. PROCEDURE send_errpack( num : INTEGER );
  1004.  
  1005. FUNCTION  rpack(spnum: INTEGER; VAR len, rpnum: INTEGER; VAR data: packettype;
  1006.                 timeout: INTEGER; soh_char: CHAR ) : CHAR;
  1007.  
  1008. FUNCTION  bufill_t : INTEGER;
  1009.  
  1010. FUNCTION  bufill_i : INTEGER;
  1011.  
  1012. PROCEDURE bufemp_t( len : INTEGER );
  1013.  
  1014. PROCEDURE bufemp_i( len : INTEGER );
  1015.  
  1016.  
  1017. IMPLEMENTATION
  1018.  
  1019.  
  1020. FUNCTION bufill_t (* : integer*);
  1021.  
  1022. (* fill a packet with data from a textfile...manages a 2 block buffer *)
  1023.  
  1024. var i, j, count: integer;
  1025.     ch : char;
  1026.  
  1027. begin
  1028.   i := 4; (* start at packet[4] for data chars *) 
  1029.   (* while file has some data & packet has some room we'll keep going *)
  1030.   while ((bufpos <= bufend) or (not eof(applefile))) and (i < max1_data) do
  1031.     begin
  1032.       (* if we need more data from disk then *)
  1033.       if (bufpos > bufend) and (not eof(applefile)) then
  1034.         begin
  1035.           (* read a textpage = 2 blocks *)
  1036.           bufend := blockread(applefile,filebuf[1],2) * blksize;
  1037.           io_status := ioresult;
  1038.           if io_status <> 0 then exit( bufill_t );
  1039.           (* and adjust buffer pointer *)
  1040.           bufpos := 1
  1041.         end; (* if *)
  1042.       if (bufpos <= bufend) then          (* if we're within buffer bounds *)
  1043.         begin
  1044.           ch := filebuf[bufpos];          (* get a character *)
  1045.           bufpos := bufpos + 1;           (* increase buffer pointer *)
  1046.           if (ch = xdle_char) then        (* if it's space compression char, *)
  1047.             begin
  1048.               count := ord(unchar(filebuf[bufpos])); (* get # of spaces *)
  1049.               bufpos := bufpos + 1;       (* read past # *)
  1050.               ch := ' ';                  (* and make current char a space *)
  1051.             end (* if *)
  1052.             else                          (* otherwise, it's just a char *)
  1053.               count := 1;                 (* so only 1 copy of it *)
  1054.           if (ch in ctlq_set) then        (* if a control char *)
  1055.             begin
  1056.               if (ch = cr) then           (* if a carriage return *)
  1057.                 begin
  1058.                   packet[i] := quote;     (* put (quoted) CR in packet *)
  1059.                   i := i + 1;
  1060.                   packet[i] := ctl( cr );
  1061.                   i := i + 1;
  1062.                   ch := lf;               (* and we'll stick a LF after *)
  1063.                 end; (* if *)
  1064.               packet[i] := quote;         (* put the quote in packet *)
  1065.               i := i + 1;
  1066.               if ch <> quote then
  1067.                       ch := ctl(ch);      (* and un-controllify char *)
  1068.             end (* if *)
  1069.         end; (* if *)
  1070.       j := 1;
  1071.       while (j <= count) and (i < max2_data) do
  1072.         begin                             (* put all the chars in packet *)
  1073.           if ch <> chr(0) then            (* so long as not a NUL *)
  1074.             begin
  1075.               packet[i] := ch;
  1076.               i := i + 1;
  1077.             end (* if *)
  1078.           else bufpos := bufend +1;       (* if is a NUL so *)
  1079.                                           (* skip to end of block *)
  1080.                                           (* since rest will be NULs *)
  1081.           j := j + 1
  1082.         end; (* while *)
  1083.     end; (* while *)
  1084.   if (i = 4) then                         (* if we're at end of file, *)
  1085.       bufill_t := (at_eof)                (* indicate it *)
  1086.   else                                    (* else *)
  1087.     begin
  1088.       if (j <= count) then                (* if didn't all fit in packet *)
  1089.         begin
  1090.           bufpos := bufpos - 2;           (* put buf pointer at DLE *)
  1091.                                           (* and update compress count *)
  1092.           filebuf[bufpos + 1] := tochar(chr(count-j+1));
  1093.         end; (* if *)
  1094.       bufill_t := i                       (* return # of data in packet + 4 *)
  1095.     end; (* else *)
  1096. end; (* bufill_t *)
  1097.  
  1098.  
  1099. FUNCTION bufill_i { : integer };
  1100.  
  1101. { fills packet with data form another type of file than a textfile.  }
  1102. { This will only work if serial wordlength can be set to 8 databits, }
  1103. { no parity and if both sides plus the transport medium do not change}
  1104. { in any way the most significant bit of the byte send.              }
  1105.  
  1106. var i : integer;
  1107.     ch : char;
  1108.     
  1109. begin
  1110.   i := 4; ch := ' ';
  1111.   while ((bufpos <= bufend) or ( not eof(applefile))) and ( i < spsiz ) do
  1112.     begin
  1113.       if (bufpos > bufend) and ( not eof(applefile) ) then
  1114.         begin
  1115.           bufend := blockread( applefile, filebuf[1], 1) * blksize;
  1116.           io_status := ioresult;
  1117.           if io_status <> 0 then exit( bufill_i );
  1118.           bufpos := 1;
  1119.         end;
  1120.       if (bufpos <= bufend) then
  1121.         begin
  1122.           ch := filebuf[bufpos];
  1123.           bufpos := bufpos + 1;
  1124.           if ch in ctlq_set then begin
  1125.                                    packet[i] := quote;
  1126.                                    i := i + 1;
  1127.                                    if ch <> quote then ch := ctl( ch );
  1128.                                   end;
  1129.           packet[i] := ch;
  1130.           i := i + 1;
  1131.         end;
  1132.     end; { while }
  1133.   if i = 4 then bufill_i := at_eof
  1134.            else bufill_i := i;
  1135. end; { bufill_i }
  1136.  
  1137.  
  1138.  
  1139. PROCEDURE bufemp_t { len : integer };
  1140.  
  1141. var ch : char;
  1142.     i, j : integer;
  1143.     
  1144. begin
  1145.   i := 0;
  1146.   while i < len do
  1147.   begin
  1148.     if bufpos < ( page_size - 1 )
  1149.       then begin
  1150.              ch := rec_pkt[i];
  1151.              if ch = quote
  1152.                then begin
  1153.                       i := i + 1;
  1154.                       ch := rec_pkt[i];
  1155.                       if ch = quote
  1156.                         then begin
  1157.                                filebuf[bufpos] := ch;
  1158.                                bufpos := bufpos + 1;
  1159.                              end
  1160.                         else begin
  1161.                                ch := ctl( ch );
  1162.                                if ch in [ cr, ff ] then
  1163.                                  begin
  1164.                                    if ch = ff then if no_ffeed
  1165.                                                    then ch := cr;
  1166.                                    filebuf[bufpos]   := ch;
  1167.                                    filebuf[bufpos+1] := xdle_char;
  1168.                                    filebuf[bufpos+2] := ' ';
  1169.                                    crpos := bufpos;
  1170.                                    bufpos := bufpos + 3;
  1171.                                    dle_flag := true;
  1172.                                  end;
  1173.                              end;
  1174.                     end
  1175.                else begin
  1176.                       if ( ch = ' ' ) and dle_flag
  1177.                         then filebuf[bufpos-1] := succ( filebuf[bufpos-1] )
  1178.                         else begin
  1179.                                dle_flag := false;
  1180.                                filebuf[bufpos] := ch;
  1181.                                bufpos := bufpos + 1;
  1182.                              end;
  1183.                     end;
  1184.              i := i + 1;
  1185.            end
  1186.       else begin
  1187.              j := blockwrite( rec_file, filebuf[1], 1 );
  1188.              bufpos := bufpos - crpos;
  1189.              moveleft( filebuf[crpos], filebuf[1], bufpos );
  1190.              fillchar( filebuf[crpos], pagesize + 1 - crpos, chr(0) );
  1191.              j := blockwrite( rec_file, filebuf[blk_size + 1], 1 );
  1192.              io_status := ioresult;
  1193.              if j <> 1 then io_status := 8;
  1194.              if io_status <> 0 then exit( bufemp_t );
  1195.              bufpos := bufpos + 1;
  1196.              crpos := pagesize - 1;
  1197.            end;
  1198.   end;
  1199. end;  { bufemp_t }
  1200.                     
  1201.                     
  1202.  
  1203.  
  1204. PROCEDURE bufemp_i { len : integer };
  1205.  
  1206. var ch : char;
  1207.     i, j : integer;
  1208.     
  1209. begin
  1210.   i := 0;
  1211.   while i < len do
  1212.   begin
  1213.     if bufpos <= blk_size
  1214.       then begin
  1215.              ch := rec_pkt[i];
  1216.              if ch = quote
  1217.                then begin
  1218.                       i := i + 1;
  1219.                       ch := rec_pkt[i];
  1220.                       if ch <> quote then ch := ctl( ch );
  1221.                     end;
  1222.              filebuf[bufpos] := ch;
  1223.              bufpos := bufpos + 1;
  1224.              i := i + 1;
  1225.            end
  1226.       else begin
  1227.              j := blockwrite( rec_file, filebuf[1], 1 );
  1228.              bufpos := 1;
  1229.              io_status := ioresult;
  1230.              if j <> 1 then io_status := 8;
  1231.              if io_status <> 0 then exit( bufemp_i );
  1232.            end;
  1233.   end;
  1234. end;  { bufemp_i }
  1235.                     
  1236.  
  1237.                     
  1238.  
  1239.  
  1240. PROCEDURE spar;
  1241.  
  1242. (* fills packet with my send-init parameters *)
  1243.  
  1244.   begin
  1245.     packet[4] := tochar(chr(maxpack));   (* biggest packet i can receive *)
  1246.     packet[5] := tochar(chr(mytime));    (* when i want to be timed out *)
  1247.     packet[6] := tochar(chr(mypad));     (* how much padding i need *)
  1248.     packet[7] := ctl(mypchar);           (* padding char i want *)
  1249.     packet[8] := tochar(eoln_char);      (* end of line character i want *)
  1250.     packet[9] := myquote;                (* control-quote char i want *)
  1251.     packet[10]:= chr(0);                 (* I won't do 8-bit quoting *)
  1252.   end; (* spar *)
  1253.  
  1254.  
  1255.  
  1256. PROCEDURE rpar;
  1257.  
  1258. (* gets their init params *)
  1259.  
  1260. begin
  1261.   spsiz     := ord(unchar(rec_pkt[0]));         (* max send packet size     *)
  1262.   max1_data := spsiz - 2;                       (* calculate maximal        *)
  1263.   max2_data := spsiz + 1;                       (* data limits for bufill_t *)
  1264.   xtime     := ord(unchar(rec_pkt[1]));         (* when i should time out   *)
  1265.   pad       := ord(unchar(rec_pkt[2]));         (* number of pads to send   *)
  1266.   padchar   := ctl(rec_pkt[3]);                 (* padding char to send     *)
  1267.   xeol_char := unchar(rec_pkt[4]);              (* eol char i must send     *)
  1268.   quote     := rec_pkt[5];                      (* incoming data quote char *)
  1269. end; (* rpar *)
  1270.  
  1271.  
  1272. PROCEDURE spack(*ptype: char; num: integer; len: integer*);
  1273.  
  1274. (* send a packet *)
  1275.  
  1276. const mtry = 10000;
  1277.  
  1278. var j, i, count: integer;
  1279.     ch: char;
  1280.  
  1281. begin
  1282.   if ibm and (currstate <> 's') then           (* if ibm and not SINIT then *)
  1283.     begin
  1284.       count := 0; ch := ' ';
  1285.       repeat                                   (* wait for an xon *)
  1286.         repeat
  1287.             count := count + 1;
  1288.             unitstatus( inport, j, control_word );
  1289.         until ( j > 0 ) or ( count > mtry );
  1290.         unitread( inport, ch, 1,, 12 );
  1291.       until (ch = xon_char) or (count > mtry);
  1292.       if count > mtry then exit( spack ); (* if wait too long then get out *)
  1293.     end; (* if *)
  1294.  
  1295.   if pad > 0 then
  1296.     begin
  1297.       for i := 1 to pad do
  1298.       unitwrite( outport, padchar, 1,, 12 ); (* write out any padding chars *)
  1299.     end;
  1300.   packet[0] := soh_char;                     (* packet sync character *)
  1301.   packet[1] := tochar(chr(len - 1));         (* character count *)
  1302.   packet[2] := tochar(chr(num));             (* packet number *)
  1303.   packet[3] := ptype;                        (* packet type *)
  1304.    (* data chars have already been filled in by by the bufill procedure *)
  1305.                                              (* compute final chksum *)
  1306.                                              (* len=data chars + 4 *)
  1307.   packet[len]   := tochar( calc_checksum( packet, len ) );
  1308.   packet[len+1] := xeol_char;
  1309.   if debug then packet_write( packet, len+2 );
  1310.   unitwrite( outport, packet[0], len+2,, 12 );
  1311. end; (* spack *)
  1312.  
  1313.  
  1314. PROCEDURE  send_errpack { num : integer };
  1315.  
  1316. var len : integer;
  1317.  
  1318. begin
  1319.   len := length ( err_string );
  1320.   moveleft( err_string[1], packet[4], len );
  1321.   spack( 'E', num, len+4 );
  1322. end;  { send_errpack }
  1323.  
  1324.  
  1325. FUNCTION rpack{ (spnum:integer; var len,rpnum:integer; data:packettype;  }
  1326.               {  timeout:integer; soh_char:char) : char } ; EXTERNAL;
  1327.            
  1328. { this function listens to the serial input port, detects a kermit }
  1329. { package, decodes it and returns the data part of the packet.     }
  1330. { its function value is the type of the received packet. If there  }
  1331. { was a receive error or the timeout period (1..31 sec) was        }
  1332. { exhausted without receiving a valid packet the function returns  }
  1333. { with '@' as value, with rpnum=spnum and with len = 0.            }
  1334.  
  1335.  
  1336. begin
  1337. end. { kermpack }
  1338. (*=== SENDER.TEXT ===*)
  1339. (* >>>> SENDER.TEXT  ***************************************************)
  1340.  
  1341. (*$I-*)
  1342. (*$R-*)
  1343. (*$S+*)
  1344. (*$V-*)
  1345.  
  1346. UNIT sender;    INTRINSIC CODE 26   ;
  1347.  
  1348. INTERFACE
  1349.  
  1350. USES  kermglob,
  1351.       kermutil,
  1352.       kermpack;
  1353.  
  1354. PROCEDURE sendsw( VAR send_ok: BOOLEAN );
  1355.  
  1356.  
  1357. IMPLEMENTATION
  1358.  
  1359.  
  1360. PROCEDURE  sendsw{ var send_ok : boolean };
  1361.  
  1362. VAR size, numtry, spnum, rpnum, len : INTEGER;
  1363.     ch : CHAR;
  1364.     leg_fname : STRING;
  1365.     ready : boolean;
  1366.  
  1367.  
  1368.  
  1369. FUNCTION  openfile : BOOLEAN;
  1370.  
  1371. (* resets file & gets past first 2 blocks in case of textfile *)
  1372.  
  1373. var b : integer;
  1374.  
  1375. begin
  1376.   reset( apple_file,  xfile_name ); 
  1377.   io_status := ioresult;
  1378.   if io_status = 0 then
  1379.     begin
  1380.       if text_file then
  1381.         b := blockread( apple_file, filebuf[1], 2 );
  1382.         { for a textfile skip past the first two blocks }
  1383.         io_status := ioresult;
  1384.         bufend := 0;
  1385.         bufpos := 1;
  1386.     end;
  1387.   openfile := ( io_status = 0 );
  1388.   
  1389. end; { open_file }
  1390.  
  1391.  
  1392. PROCEDURE legalize( var fn : string ); 
  1393.  
  1394. { make filename acceptable to host }
  1395. { filename is already uppercase and cannot contain a ':' as last char. }
  1396.  
  1397. var i, point_pos, len : integer;
  1398.  
  1399. begin
  1400.   delete( fn, 1, pos( ':', fn ) );   { strip off volumename }
  1401.   len := length( fn );
  1402.   i := 1; point_pos := 1;
  1403.   repeat
  1404.     if fn[i] = '.' then point_pos := i; { save last occurrence of '.' }
  1405.     if not ( fn[i] in [ '0'..'9', 'A'..'Z' ] )  then fn[i] := 'X';
  1406.     { replace every non alphanumeric character with a 'X' }
  1407.     i := i + 1;
  1408.   until i > len;
  1409.   if point_pos > 1 then fn[point_pos] := '.';
  1410.   { restore last encountered '.', except when '.' was in first position }
  1411. end; { legalize }
  1412.  
  1413.  
  1414.  
  1415.  
  1416. FUNCTION sinit: char;
  1417.  
  1418. (* send init packet & receive other side's *)
  1419.  
  1420. begin
  1421.   sinit := 's';    { default state remains 's' }
  1422.   if debug then debugwrite('sinit');
  1423.   if interrupt(int_key) or (num_try > init_try) then
  1424.     begin
  1425.       sinit := 'a';
  1426.       send_errpack( spnum );
  1427.       exit( sinit )
  1428.     end;
  1429.   num_try := num_try + 1;
  1430.   spar;
  1431.   refresh_screen( numtry, spnum );
  1432.   spack( 'S', spnum, 10 );
  1433.   unitclear( inport );            { clear remin buffer }
  1434.   ch := rpack( spnum, len, rpnum, recpkt, xtime, soh_char );
  1435.   if debug then ack_write(  ch, len, rpnum, recpkt );
  1436.   if ch = 'Y' then begin
  1437.                      if spnum <> rpnum then exit( sinit );  { stay in 's' }
  1438.                      rpar;  { get other side init package }
  1439.                      if xeol_char = chr(0) then xeol_char := eoln_char;
  1440.                      if quote= chr(0) then quote:= my_quote;
  1441.                      if xtime= 0 then xtime:= my_time;
  1442.                      if xtime>32 then xtime:= 31;
  1443.                      { use my parameters if other side did not specify them }
  1444.                      if text_file then ctlq_set := ctl_set + [quote] - [chr(0)]
  1445.                                   else
  1446.                      ctlq_set := ctl_set + [quote,chr(128)..chr(159),chr(255)];
  1447.                      { for image transfer add msbit control chars to set }
  1448.                      numtry := 0;
  1449.                      spnum := 1;
  1450.                      sinit := 'f';  { go to next state }
  1451.                    end  { then }
  1452.               else if ( ch <> 'N' ) and ( ch <> '@' ) then
  1453.                 begin
  1454.                   sinit := 'a';   { for nack or receive failure stay in 's' }
  1455.                                   { for every other state : abort }
  1456.                   if ch = 'E' then error( recpkt, len );
  1457.                 end;  { else }
  1458. end; (* sinit *)
  1459.  
  1460.  
  1461.  
  1462.  
  1463. FUNCTION sdata: char;
  1464.  
  1465. (* send file data *)
  1466.  
  1467. begin
  1468.   if debug then debug_write( 'sdata' );
  1469.   if text_file then size := bufill_t
  1470.                else size := bufill_i;
  1471.   if io_status <> 0 then begin
  1472.                            io_error( io_status );
  1473.                            send_errpack( spnum );
  1474.                            sdata := 'a';
  1475.                            exit( sdata );
  1476.                          end;
  1477.   while ( currstate = 'd' ) do
  1478.     begin
  1479.       if interrupt(int_key) or (numtry > maxtry) then
  1480.         begin
  1481.           sdata := 'a';
  1482.           send_errpack( spnum );
  1483.           exit( sdata )
  1484.         end;
  1485.       numtry := numtry + 1;
  1486.       refresh_screen( numtry, spnum );
  1487.       spack( 'D', spnum, size );
  1488.       unitclear( inport );
  1489.       ch := rpack( spnum, len, rpnum, recpkt, xtime, soh_char ); 
  1490.       if debug then ack_write( ch, len, rpnum, recpkt );
  1491.       if ch = 'N'
  1492.         then if ((spnum+1) mod 64 ) <> rpnum
  1493.                then ch := '@'   { if a nack and not the right num: stay in 'd'}
  1494.                else begin
  1495.                       rpnum := (rpnum+63) mod 64;  { if a nack for the next }
  1496.                       ch := 'Y';                   { packet: same as ack for}
  1497.                     end;   { this packet: indicate an ack. }
  1498.       if ch = 'Y'
  1499.         then begin
  1500.                if spnum = rpnum   { right ack received }
  1501.                  then begin
  1502.                         if text_file then size := bufill_t
  1503.                                      else size := bufill_i;
  1504.                         if io_status <> 0 
  1505.                           then begin
  1506.                                  io_error( io_status );
  1507.                                  send_errpack( spnum );
  1508.                                  sdata := 'a';
  1509.                                  exit( sdata );
  1510.                                end;
  1511.                         if size = at_eof then currstate := 'z';
  1512.                         spnum := (spnum+65) mod 64;
  1513.                         numtry := 0;
  1514.                         { go to next state if data is exhausted, else }
  1515.                         { stay in the same state and send next packet }
  1516.                       end;
  1517.               end
  1518.          else if ch <> '@' 
  1519.                 then begin
  1520.                        currstate := 'a';
  1521.                        if ch = 'E' then error( recpkt, len );
  1522.                      end;
  1523.     end;  { while }
  1524.   sdata := currstate;
  1525. end; (* sdata *)
  1526.  
  1527.  
  1528.  
  1529.  
  1530. FUNCTION sfile: char;
  1531.  
  1532. (* send file header *)
  1533.  
  1534. begin
  1535.   sfile := 'f';
  1536.   if debug then debugwrite('sfile');
  1537.   if interrupt(int_key) or ( numtry > maxtry ) then
  1538.     begin
  1539.       sfile := 'a';
  1540.       send_errpack( spnum );
  1541.       exit( sfile )
  1542.     end;
  1543.   numtry := numtry + 1;
  1544.   len := length( leg_fname );
  1545.   moveleft( leg_fname[1], packet[4], len ); (* move filename into  packet *)
  1546.   gotoxy( filepos, fileline );
  1547.   write( xfile_name, ' ==> ', leg_fname );
  1548.   refresh_screen( numtry, spnum );
  1549.   spack( 'F', spnum , len + 4 );          (* send file header packet *)
  1550.   unitclear( inport );
  1551.   ch := rpack( spnum, len, rpnum, recpkt, xtime, soh_char );
  1552.   if debug then ack_write( ch, len, rpnum, recpkt );
  1553.   if ch = 'N' then begin
  1554.                      if ((spnum + 1 ) mod 64) <> rpnum
  1555.                        then exit( sfile )  { a nack for the next packet is an }
  1556.                        else begin          { ack for the current packet       }
  1557.                               rpnum := (rpnum+63) mod 64; { r = r - 1 }
  1558.                               ch := 'Y';
  1559.                             end;
  1560.                    end;
  1561.    if ch = 'Y' then begin
  1562.                       if spnum <> rpnum then exit( sfile );  { stay in 'f' }
  1563.                       numtry := 0;
  1564.                       spnum := ( spnum + 65 ) mod 64; { s = s + 1 }
  1565.                       sfile := 'd';  { go to next state }
  1566.                     end
  1567.                 else if ch <> '@' then begin
  1568.                                          sfile := 'a';
  1569.                                          if ch = 'E' then error( recpkt, len );
  1570.                                        end;
  1571.                { for rec. failure stay in 'f', other states : abort }
  1572. end; (* sfile *)
  1573.  
  1574.  
  1575.  
  1576.  
  1577. FUNCTION seof: char;
  1578.  
  1579. (* send end of file *)
  1580.  
  1581. begin
  1582.   seof := 'z';
  1583.   if debug then debugwrite('seof');
  1584.   if interrupt(int_key) or (numtry > maxtry) then (*if too many tries, give up*)
  1585.     begin
  1586.       seof := 'a';
  1587.       send_errpack( spnum );
  1588.       exit(seof)
  1589.     end;
  1590.   numtry := numtry + 1;
  1591.   refresh_screen( numtry, spnum );
  1592.   spack( 'Z', spnum, 4 );    (* send end of file packet *)
  1593.   unitclear( inport );
  1594.   ch := rpack( spnum, len, rpnum, recpkt, xtime, soh_char );
  1595.   if debug then ack_write( ch, len, rpnum, recpkt );
  1596.   if ch = 'N' then
  1597.     if ((spnum+1) mod 64) <> rpnum then exit( seof )
  1598.                                    else begin
  1599.                                           rpnum := (rpnum+63) mod 64;
  1600.                                           ch := 'Y';
  1601.                                         end;
  1602.   if ch = 'Y' 
  1603.     then begin
  1604.            if spnum <> rpnum then exit( seof )
  1605.                              else begin
  1606.                                     numtry := 0;
  1607.                                     spnum := (spnum+65) mod 64;
  1608.                                     seof := 'b';
  1609.                                   end;
  1610.          end
  1611.     else if ch <> '@' then begin
  1612.                              seof := 'a';
  1613.                              if ch = 'E' then error( recpkt, len );
  1614.                            end;
  1615. end; (* seof *)
  1616.  
  1617.  
  1618.  
  1619. FUNCTION sbreak: char;
  1620.  
  1621. (* send break (end of transmission) *)
  1622.  
  1623. begin
  1624.   sbreak := 'b';
  1625.   if debug then debugwrite('sbreak');
  1626.   if interrupt(int_key) or (numtry > maxtry) then (*if too many tries, give up*)
  1627.     begin
  1628.       sbreak := 'a';
  1629.       send_errpack( spnum );
  1630.       exit(sbreak)
  1631.     end;
  1632.   numtry := numtry + 1;
  1633.   refresh_screen(numtry, spnum);
  1634.   spack( 'B', spnum, 4);    (* send end of file packet *)
  1635.   unitclear( inport );
  1636.   ch := rpack( spnum, len, rpnum, recpkt, xtime, soh_char );
  1637.   if debug then ack_write( ch, len, rpnum, recpkt );
  1638.   if ch = 'N' then
  1639.     if ((spnum+1) mod 64) <> rpnum then exit( sbreak )
  1640.                                    else begin
  1641.                                           rpnum := (rpnum+63) mod 64;
  1642.                                           ch := 'Y';
  1643.                                         end;
  1644.   if ch = 'Y'
  1645.     then begin
  1646.            if spnum <> rpnum then exit( sbreak );
  1647.            sbreak := 'c';
  1648.          end
  1649.     else if ch <> '@' then begin
  1650.                              sbreak := 'a';
  1651.                              if ch = 'E' then error( recpkt, len );
  1652.                            end;
  1653. end; (* sbreak *)
  1654.  
  1655.  
  1656.  
  1657. {   PROCEDURE sendsw   }
  1658.  
  1659. (* state table switcher for sending *)
  1660.  
  1661. begin (* sendsw *)
  1662.   unitclear( inport );
  1663.   write_screen('Sending ');
  1664.   if text_file and ( pos( '.TEXT', xfile_name ) = 0 )
  1665.     then xfile_name := concat( xfile_name, '.TEXT' );
  1666.   gotoxy( filepos, fileline ); write( xfile_name );
  1667.   if not openfile then
  1668.     begin
  1669.       io_error(io_status);
  1670.       send_ok := false;
  1671.       exit(sendsw)
  1672.     end;
  1673.   leg_fname := xfile_name;
  1674.   legalize( leg_fname );
  1675.   if not text_file then check_apple_char( no_mask_msbit_remin );
  1676.   { for image transfer leave msbit unchanged }
  1677.   check_apple_char( sfb_char );
  1678.   { restore action of ^S, ^F, ^@ keys during send }
  1679.   currstate := 's';
  1680.   spnum:= 0;       (* set packet # *)
  1681.   numtry := 0;
  1682.   ready := false;
  1683.   while not ready do
  1684.     begin
  1685.       if currstate in ['d', 'f', 'z', 's', 'b', 'c', 'a'] then
  1686.         case currstate of
  1687.             'd': currstate := sdata;
  1688.             'f': currstate := sfile;
  1689.             'z': currstate := seof;
  1690.             's': currstate := sinit;
  1691.             'b': currstate := sbreak;
  1692.             'c': begin
  1693.                    send_ok := true;
  1694.                    ready := true;
  1695.                  end; (* case c *)
  1696.             'a': begin
  1697.                    send_ok := false;
  1698.                    ready := true;
  1699.                  end (* case a *)
  1700.           end (* case *)
  1701.       else (* state not in legal states *)
  1702.         begin
  1703.           send_ok := false;
  1704.           ready := true;
  1705.         end (* else *)
  1706.     end; { of while }
  1707.   check_apple_char( mask_msbit_remin );
  1708.   check_apple_char( no_sfb_char );
  1709. end; (* sendsw *)
  1710.  
  1711.  
  1712. begin
  1713. end. { sender }
  1714.  
  1715. (*=== RECEIVER.TEXT ===*)
  1716. (* >>>> RECEIVER.TEXT  *************************************************)
  1717.  
  1718. {$I-}
  1719. {$R-}
  1720. {$S+}
  1721. {$V-}
  1722.  
  1723. UNIT receiver;    INTRINSIC CODE 25   ;
  1724.  
  1725. INTERFACE
  1726.  
  1727. USES  kermglob,
  1728.       kermutil,
  1729.       kermpack;
  1730.  
  1731.  
  1732. PROCEDURE recsw( VAR rec_ok: BOOLEAN );
  1733.  
  1734.  
  1735. IMPLEMENTATION
  1736.  
  1737.  
  1738. PROCEDURE recsw{ var rec_ok: boolean };
  1739.  
  1740. var  oldtry, numtry, spnum, rpnum, len : integer;
  1741.      ch : char;
  1742.      host_fname : string;
  1743.      ready : boolean;
  1744.      
  1745.  
  1746.  
  1747. FUNCTION open_file( var fn : string ) : boolean;
  1748.  
  1749. var i : integer;
  1750.  
  1751. begin
  1752.   rewrite( rec_file , concat( prefix_vol, fn ) );
  1753.   iostatus := ioresult;
  1754.   if iostatus = 0 then
  1755.       if text_file then begin
  1756.                           fillchar( filebuf[1], page_size, chr(0) );
  1757.                           i := blockwrite( rec_file, filebuf[1], 2);
  1758.                           iostatus := ioresult;
  1759.                           if i <> 2 then io_status := 8;
  1760.                         end;
  1761.   open_file := ( io_status = 0 );
  1762.   bufpos := 1;
  1763.   crpos  := page_size - 1;
  1764.   dle_flag := false;
  1765. end;   { open_file }
  1766.  
  1767.  
  1768. FUNCTION close_file : boolean;
  1769.  
  1770. var file_end, num_block, i : integer;
  1771.  
  1772. begin
  1773.   if text_file then begin
  1774.                       file_end := page_size;
  1775.                       num_block := 2;
  1776.                     end
  1777.                else begin
  1778.                       file_end := blk_size;
  1779.                       num_block := 1;
  1780.                     end;
  1781.   fillchar( filebuf[bufpos], (file_end - bufpos), chr(0) );
  1782.   i := blockwrite( rec_file, filebuf[1], num_block );
  1783.   iostatus := ioresult;
  1784.   if i <> num_block then io_status := 8;
  1785.   close_file := ( io_status = 0 );
  1786.   close( rec_file, lock );
  1787. end;  { close_file }
  1788.  
  1789.      
  1790.      
  1791.      
  1792. FUNCTION exist( var fn : string ) : boolean;
  1793.  
  1794. begin
  1795.   reset( rec_file, concat( prefix_vol, fn ) );
  1796.   exist := ( ioresult = 0 );
  1797.   close( rec_file )
  1798. end; { exist }
  1799.  
  1800.  
  1801. PROCEDURE check_name( var fn : string );
  1802.  
  1803. var ch : char;
  1804.      i : integer;
  1805.      
  1806. begin
  1807.   i := 1;
  1808.   while ( i <= length( fn ) ) and exist( fn ) do
  1809.     begin
  1810.       ch := 'A';
  1811.       while ( ch in [ 'A'..'Z' ] ) and exist( fn ) do
  1812.         begin
  1813.           fn[ i ] := ch;
  1814.           ch := succ( ch );
  1815.         end;
  1816.       i := i + 1;
  1817.     end;
  1818. end;  { check_name }
  1819.  
  1820.  
  1821. PROCEDURE make_name( var rpkt: packettype; var fn : string; len : integer );
  1822.  
  1823. { change the received filename into a legal apple ucsd filename }
  1824.  
  1825. var i : integer;
  1826.  
  1827. begin
  1828.   host_fname[0] := chr( min( 80, len ) ); 
  1829.   moveleft( rpkt[0], host_fname[1], min( 80, len ) );
  1830.   fn := copy( host_fname, 1, min( 15, len ) );
  1831.   { take left part of received filename, max 15 long }
  1832.   uppercase( fn );
  1833.   if  text_file 
  1834.     then begin
  1835.            if ( length(fn) < 5 ) or ( pos('.TEXT',fn) <> length(fn) - 4 )
  1836.              then begin
  1837.                     if length(fn) > 10 then fn := copy(fn,1,10);
  1838.                     fn := concat( fn, '.TEXT' );
  1839.                   end;
  1840.          end;
  1841.   { add .TEXT if the expected file is a textfile }
  1842.   for i := 1 to length( fn ) do
  1843.     if fn[i] in [ chr(0)..chr(31),':','$',',','=','?','[' ] then fn[i] := 'X';
  1844.   { replace apple ucsd incompatible char's in filename with 'X' }
  1845.   if fwarn then checkname( fn );
  1846. end;  { make_name }
  1847.   
  1848.  
  1849.  
  1850.  
  1851. FUNCTION rdata: char;
  1852.  
  1853. (* send file data *)
  1854.  
  1855.  
  1856. begin
  1857.   if debug then debug_write( 'rdata' );
  1858.   repeat
  1859.     currstate := 'a';
  1860.     if interrupt(int_key) or (numtry > maxtry) then
  1861.       begin
  1862.         rdata := 'a';
  1863.         send_errpack( spnum );
  1864.         exit( rdata )
  1865.       end;
  1866.     num_try := num_try + 1;
  1867.     unitclear( inport );
  1868.     ch := rpack(spnum, len, rpnum, recpkt, xtime, sohchar );{ receive a packet }
  1869.     refresh_screen( numtry, spnum );
  1870.     if debug then ack_write( ch, len, rpnum, recpkt );
  1871.     case ch of
  1872.     'D' : { got data packet. if wrong packet number : abort. }
  1873.           { if previous packet : ack it again but not more than maxtry times }
  1874.           begin
  1875.             if spnum = rpnum
  1876.               then begin
  1877.                      if text_file then bufemp_t( len )
  1878.                                   else bufemp_i( len );
  1879.                      if io_status <> 0
  1880.                        then begin
  1881.                               io_error( io_status );
  1882.                               send_errpack( spnum );
  1883.                             end
  1884.                        else begin
  1885.                               spack( 'Y', spnum, 4 );
  1886.                               numtry := 0;
  1887.                               spnum := ( spnum + 65 ) mod 64;
  1888.                               currstate := 'd';
  1889.                             end;
  1890.                    end
  1891.               else begin
  1892.                      if ( (spnum-1) mod 64 ) = rpnum
  1893.                        then begin
  1894.                               if oldtry > maxtry then begin
  1895.                                                         rdata := 'a';
  1896.                                                         exit( rdata );
  1897.                                                       end;
  1898.                               spack( 'Y', rpnum, 4 );
  1899.                               numtry := 0;
  1900.                               oldtry := oldtry + 1;
  1901.                               currstate := 'd';
  1902.                             end;
  1903.                    end;
  1904.           end;  { case 'D' }
  1905.     'F' : { got file header packet again: if it was previous packet }
  1906.           { ack it again but not more than maxtry times. any other  }
  1907.           { packet number : abort }
  1908.           begin
  1909.             if ( (spnum-1) mod 64 ) = rpnum
  1910.               then begin
  1911.                      if oldtry > maxtry then begin
  1912.                                                rdata := 'a';
  1913.                                                exit( rdata );
  1914.                                              end;
  1915.                      spack ( 'Y', rpnum, 4 );
  1916.                      numtry := 0;
  1917.                      oldtry := oldtry + 1;
  1918.                      currstate := 'd';
  1919.                    end;
  1920.           end;  { case 'F' }
  1921.     'E' : { error packet received : write it to screen and abort }
  1922.           error( recpkt, len );
  1923.     '@' : { in case of receive failure send nack and stay in this state }
  1924.           begin
  1925.             spack( 'N', spnum, 4 );
  1926.             currstate := 'd';
  1927.           end;
  1928.     'Z' : { end-of-file packet received : if it has the right packet number }
  1929.           { close the current file and go to rfile state to check whether   }
  1930.           { another file haeder packet is coming or an end-of-transmission  }
  1931.           { packet. }
  1932.           begin
  1933.             if spnum = rpnum
  1934.               then begin
  1935.                      if debug then debugwrite( 'reof' );
  1936.                      if not close_file
  1937.                        then begin
  1938.                               io_error( io_status );
  1939.                               send_errpack( spnum );
  1940.                             end
  1941.                        else begin
  1942.                               spack( 'Y', spnum, 4 );
  1943.                               spnum := ( spnum + 65 ) mod 64;
  1944.                               numtry := 0;
  1945.                               oldtry := 0;
  1946.                               currstate := 'f';
  1947.                             end;
  1948.                    end;
  1949.           end;  { case 'Z' }
  1950.     end;  { case ch }
  1951.   until (currstate <> 'd');
  1952.   rdata := currstate
  1953. end;  { rdata } 
  1954.  
  1955.  
  1956.  
  1957.  
  1958. FUNCTION rfile: char;
  1959.  
  1960. (* receive file header *)
  1961.  
  1962. begin (* rfile *)
  1963.   currstate := 'a';                 (* set default state for rfile to abort *)
  1964.   if debug then debug_write( 'rfile' );
  1965.   if interrupt(int_key) or (numtry > maxtry) then
  1966.     begin
  1967.       rfile := 'a';
  1968.       send_errpack( spnum );
  1969.       exit( rfile )
  1970.     end;
  1971.   numtry := numtry + 1;
  1972.   unitclear( inport );
  1973.   ch := rpack(spnum, len, rpnum, recpkt, xtime, sohchar); (* receive a packet *)
  1974.   refresh_screen( numtry, spnum );
  1975.   if debug then ack_write( ch, len, rpnum, recpkt );
  1976.   
  1977.   case ch of
  1978.   'S' : { maybe our ack for packet 0 was lost: send it again, but not more }
  1979.         { than maxtry times }
  1980.         begin
  1981.           if ((spnum-1) mod 64) = rpnum
  1982.             then begin
  1983.                    if oldtry > maxtry then begin rfile := 'a'; exit(rfile) end;
  1984.                    spar;
  1985.                    spack( 'Y', rpnum, 10 );
  1986.                    numtry := 0;
  1987.                    oldtry := oldtry + 1;
  1988.                    currstate := 'f';   { stay in same state }
  1989.                  end;                  { for any other packet num: abort }
  1990.         end;  { case 'S' }
  1991.   'Z' : { maybe our ack for the eof packet was lost: ack it again }
  1992.         begin
  1993.           if ((spnum-1) mod 64) = rpnum
  1994.             then begin
  1995.                    if oldtry > maxtry then begin rfile := 'a'; exit(rfile) end;
  1996.                    spack( 'Y', rpnum, 4 );
  1997.                    numtry := 0;
  1998.                    oldtry := oldtry + 1;
  1999.                    currstate := 'f';     { stay in same state }
  2000.                  end;                    { for any other packet num: abort }
  2001.         end;  { case 'Z' }
  2002.   'B' : { if the right packet num for the eot packet then ack it and go }
  2003.         { to the complete state; else abort }
  2004.         begin
  2005.           if spnum = rpnum
  2006.             then begin
  2007.                    if debug then debug_write( 'rbreak' );
  2008.                    spack( 'Y', spnum, 4 );
  2009.                    currstate := 'c';
  2010.                  end;                { if not the right num: abort }
  2011.         end;  { case 'B' }
  2012.   '@' : { in case of receive failure send nack and stay in this state }
  2013.         begin
  2014.           spack( 'N', spnum, 4 );
  2015.           currstate := 'f';
  2016.         end;  { case '@' }
  2017.   'E' : { error packet received: write it on screen and abort }
  2018.         error( recpkt, len );
  2019.   'F' : { fileheader packet received which is what we really want: }
  2020.         { if not the right packetnumber : abort }
  2021.         { if a new file cannot be opened : send error packet to host and abort}
  2022.         { if new file is opened : go to receive data state }
  2023.         begin
  2024.           if spnum = rpnum
  2025.             then begin
  2026.                    makename( recpkt, xfilename, len );
  2027.                    gotoxy( file_pos, file_line );
  2028.                    write( host_fname, ' ==> ', concat(prefix_vol, xfilename));
  2029.                    if not open_file( xfilename )
  2030.                      then begin
  2031.                             io_error( io_status );
  2032.                             send_errpack( spnum );
  2033.                           end
  2034.                      else begin
  2035.                             spack( 'Y', spnum, 4 );
  2036.                             numtry := 0;
  2037.                             oldtry := 0;
  2038.                             spnum := ( spnum + 65 ) mod 64;
  2039.                             currstate := 'd';
  2040.                           end;
  2041.                  end;
  2042.         end; { case 'F' }
  2043.   end;  { case ch }
  2044.   rfile := currstate;
  2045. end; (* rfile *)
  2046.  
  2047.  
  2048.  
  2049.  
  2050. FUNCTION rinit: char;
  2051.  
  2052. (* receive initialization *)
  2053.  
  2054. begin
  2055.   rinit := 'r';   { stay in 'r' in case reception failed: ptype = '@'  }
  2056.   if debug then debug_write( 'rinit' );
  2057.   if interrupt(int_key) or (numtry > init_try) then
  2058.     begin
  2059.       rinit := 'a';
  2060.       send_errpack( spnum );
  2061.       exit( rinit )
  2062.     end;
  2063.   
  2064.   { too many tries : abort. inittry is five times maxtry in case other }
  2065.   { side waits before starting to send.                                }
  2066.  
  2067.   numtry := numtry + 1;
  2068.   unitclear( inport );
  2069.   ch := rpack(spnum, len, rpnum, recpkt, mytime, sohchar);(* receive a packet *)
  2070.   refresh_screen(num_try, spnum);
  2071.   if debug then ack_write( ch, len, rpnum, recpkt );
  2072.   
  2073.   if (ch = 'S') then                        (* send init packet *)
  2074.     begin
  2075.       rpar;                         (* get other side's init data *)
  2076.       spar;                         (* fill packet with my init data *)
  2077.       numtry := 0;                          (* start a new counter *)
  2078.       oldtry := 0;                          (* start oldtry for rfile *)
  2079.       spack( 'Y', spnum, 10 );       (* send my init parameters *)
  2080.       spnum := (spnum + 65) mod 64;         (* bump packet number *)
  2081.       rinit := 'f';                         (* enter file send state *)
  2082.     end { if 'S' }
  2083.   else if (ch <> '@') then                  (* abort for every other packet *)
  2084.          begin                              (* except when rec failed, then *)
  2085.            rinit := 'a';
  2086.            if ch = 'E' then error( recpkt, len )
  2087.          end 
  2088.          else spack( 'N', spnum, 4);        (* send a NACK packet *)
  2089. end; (* rinit *)
  2090.   
  2091.   
  2092. {   PROCEDURE RECSW   }
  2093.  
  2094. (* state table switcher for receiving packets *)
  2095.  
  2096.  
  2097. begin (* recsw *)
  2098.   unitclear(inport);
  2099.   writescreen('Receiving');
  2100.   if not text_file then check_apple_char( no_mask_msbit_remin );
  2101.   { for image transfer leave msbit unchanged }
  2102.   check_apple_char( sfb_char );
  2103.   { restore action of ^S, ^F, ^@ keys during receive }
  2104.   ready := false;
  2105.   currstate := 'r';            (* initial state is send *)
  2106.   spnum := 0;                  (* set packet # *)
  2107.   numtry := 0;                 (* no tries yet *)
  2108.  
  2109.   while not ready do
  2110.     begin
  2111.       if currstate in ['d', 'f', 'r', 'c', 'a'] then
  2112.         case currstate of
  2113.           'd': currstate := rdata;
  2114.           'f': currstate := rfile;
  2115.           'r': currstate := rinit;
  2116.           'c': begin
  2117.                  rec_ok := true;
  2118.                  ready := true;
  2119.                end; (* case c *)
  2120.           'a': begin
  2121.                  rec_ok := false;
  2122.                  ready := true;
  2123.                end (* case a *)
  2124.         end (* case *)
  2125.       else (* state not in legal states *)
  2126.       begin
  2127.         rec_ok := false;
  2128.         ready := true;
  2129.       end; (* else *)
  2130.     end; { while }
  2131.   check_apple_char( mask_msbit_remin );
  2132.   check_apple_char( no_sfb_char );
  2133. end; (* recsw *)
  2134.   
  2135.   
  2136. begin
  2137. end. { receiver }
  2138.  
  2139. (*=== PARSER.TEXT ===*)
  2140. (*>>>>>>>>>>>>PARSER>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*)
  2141.  
  2142. (*$S+*)
  2143. (*$I-*)
  2144. (*$R-*)
  2145. (*$V-*)
  2146.  
  2147. UNIT parser;   INTRINSIC CODE 23  DATA 24;
  2148.  
  2149.  
  2150. INTERFACE
  2151.  
  2152. USES  kermglob,
  2153.       kermutil;
  2154.  
  2155. FUNCTION parse: statustype;
  2156.  
  2157.  
  2158. IMPLEMENTATION
  2159.  
  2160. VAR first_sym, last_sym : vocab;
  2161.  
  2162.  
  2163.   
  2164. PROCEDURE isolate_word ( var line, word : string; var wlen : integer );
  2165.  
  2166. var  line_len : integer;
  2167.  
  2168. begin
  2169.   word := '';  wlen := 0;  linelen := length( line );
  2170.   if linelen > 0
  2171.     then begin
  2172.            delete( line, 1, scan( linelen, <> ' ', line[1] ) );
  2173.            linelen := length( line );
  2174.            if linelen > 0
  2175.              then begin
  2176.                     wlen := scan( linelen, = ' ', line[1] );
  2177.                     word := copy( line, 1, wlen );
  2178.                     delete( line, 1, wlen );
  2179.                   end;
  2180.          end;
  2181. end;  { isolate_word }
  2182.  
  2183.  
  2184.  
  2185. FUNCTION get_fn( var line, fn: string; namelen : integer ) : boolean;
  2186.  
  2187. { checks the length of the filename requested for 'send'.              }
  2188. { Or checks the prefix volume name for files to be received.           }
  2189.  
  2190. var i, l: integer;
  2191.  
  2192. begin
  2193.   get_fn := true;
  2194.   isolate_word( line, fn, l );
  2195.   if (l > namelen) or (l < 1) then get_fn := false
  2196.    { max filename length, incl. volumename = 23 }
  2197.    { max volumename length, incl. ':' = 8 }
  2198.   else begin
  2199.          if (fn[l] = ':') and (namelen=23)  then get_fn := false;
  2200.          if (fn[l] <> ':') and (namelen=8)  then get_fn := false;
  2201.          {  legality of volume and filename will be tested   }
  2202.          {  when the file is actually opened. ( see unit "sender" )   }
  2203.        end;
  2204. end; (* get_fn *)
  2205.  
  2206.  
  2207.  
  2208.  
  2209. FUNCTION get_num( var line: string; var n: integer ): boolean;
  2210.  
  2211. var
  2212.    numstr: string;
  2213.    i, numstr_len  : integer;
  2214. begin
  2215.    get_num := true; n := 0;
  2216.    isolate_word( line, numstr, numstr_len );
  2217.    if (numstr_len < 6) and (numstr_len > 0) then 
  2218.      begin
  2219.        i := 1;
  2220.        numstr := concat( numstr, ' ' );
  2221.        while (numstr[i] in ['0'..'9']) do begin
  2222.           if n<(maxint div 10) then
  2223.              n := n*10 + ord( numstr[i] ) - ord( '0' );
  2224.           i := i + 1
  2225.        end { while }
  2226.      end; { if }
  2227.    if n = 0 then get_num := false;
  2228. end; { get_num }
  2229.  
  2230.  
  2231.  
  2232.  
  2233. FUNCTION nextch(var ch: char): boolean;
  2234.  
  2235. var s: string;
  2236.     ch_len : integer;
  2237.  
  2238. begin
  2239.  isolate_word( line, s, ch_len );
  2240.  if ch_len <= 1 then begin
  2241.                        if ch_len = 1 then ch := s[1]
  2242.                                      else ch := cr;
  2243.                        nextch := true;
  2244.                      end
  2245.                 else nextch := false;
  2246. end; (* nextch *)
  2247.  
  2248.  
  2249.  
  2250. FUNCTION get_sym(var word: vocab): statustype;
  2251.  
  2252. var i: vocab;
  2253.     s: string;
  2254.     stat: statustype;
  2255.     done: boolean;
  2256.     matches, slen : integer;
  2257.  
  2258. begin
  2259.   isolate_word( line, s, slen );
  2260.   if slen = 0 then getsym := ateol
  2261.    else
  2262.      begin
  2263.        stat := null;
  2264.        done := false;
  2265.        i := first_sym;
  2266.        matches := 0;
  2267.        repeat
  2268.            if (pos(s,vocablist[i]) = 1) and (i in expected) then
  2269.              begin
  2270.                matches := matches + 1;
  2271.                word := i
  2272.              end
  2273.            else if (s[1] < vocablist[i,1]) then
  2274.                done := true;
  2275.            if (i = last_sym ) then
  2276.                done := true
  2277.            else
  2278.                i := succ(i)
  2279.        until (matches > 1) or done;
  2280.        if matches > 1 then
  2281.            stat := ambiguous
  2282.        else if (matches = 0) then
  2283.            stat := unrec;
  2284.        getsym := stat
  2285.      end (* else *)
  2286. end; (* getsym *)
  2287.  
  2288.  
  2289.  
  2290.  
  2291.  
  2292. FUNCTION parse(*: statustype*);
  2293.  
  2294. type states = (start, fin, get_filename, get_set_parm, get_parity, get_on_off,
  2295.                get_esc_char, get_show_parm, get_help_show, get_help_parm,
  2296.                exitstate, get_baud, get_wordlen, get_stopbit, get_xon_char,
  2297.                get_xoff_char, get_xoffwait, get_nofeed, get_timeout, get_maxpak,
  2298.                get_eoln_char, get_maxtry, get_prefix, get_dir);
  2299.  
  2300. var status: statustype;
  2301.     word: vocab;
  2302.     state: states;
  2303.     
  2304.            procedure case_start;
  2305.     
  2306.            begin
  2307.              expected := [consym, exitsym, helpsym, phelpsym, quitsym, recsym,
  2308.                           sendsym, setsym, showsym, pshowsym, dirsym, pdirsym];
  2309.              status := getsym(verb);
  2310.              if status = ateol then
  2311.                begin
  2312.                  parse := null;
  2313.                  exit(parse)
  2314.                end (* if *)
  2315.              else if (status <> unrec) and (status <>  ambiguous) then
  2316.                  case verb of
  2317.                    consym, recsym, exitsym, quitsym: state := fin;
  2318.                    helpsym         : begin
  2319.                                        state := get_help_parm;
  2320.                                        pr_out:= false
  2321.                                      end;
  2322.                    phelpsym        : begin
  2323.                                        state := get_help_parm;
  2324.                                        pr_out:= true
  2325.                                      end;
  2326.                    dirsym          : begin
  2327.                                        state := get_dir;
  2328.                                        pr_out := false;
  2329.                                      end;
  2330.                    pdirsym         : begin
  2331.                                        state := get_dir;
  2332.                                        pr_out := true;
  2333.                                      end;
  2334.                    sendsym         : state := getfilename;
  2335.                    setsym          : state := get_set_parm;
  2336.                    showsym         : begin
  2337.                                        state := get_show_parm;
  2338.                                        pr_out:= false
  2339.                                      end;
  2340.                    pshowsym        : begin
  2341.                                        state := get_show_parm;
  2342.                                        pr_out:= true
  2343.                                      end;
  2344.                  end (* case *)
  2345.            end; (* case_start *)
  2346.            
  2347.            
  2348.            procedure case_fin;
  2349.            
  2350.            begin
  2351.              expected := [];
  2352.              status := getsym(verb);
  2353.              if status = ateol then
  2354.                begin
  2355.                  parse := null;
  2356.                  exit(parse)
  2357.                end (* if status *)
  2358.              else
  2359.                  status := unconfirmed
  2360.            end; (* case_fin *)
  2361.            
  2362.            
  2363.            procedure case_getfilename;
  2364.            
  2365.            begin
  2366.              expected := [];
  2367.              if getfn(line,xfilename,23) then
  2368.                begin
  2369.                  status := null;
  2370.                  state := fin
  2371.                end (* if *)
  2372.              else
  2373.                  status := fnexpected
  2374.            end; (* case_getfilename *)
  2375.            
  2376.            
  2377.            procedure case_gtprefixname;
  2378.            
  2379.            begin
  2380.              expected := [];
  2381.              if getfn(line,newprefix_vol,8) then
  2382.                begin
  2383.                  status := null;
  2384.                  state := fin
  2385.                end
  2386.              else
  2387.                   status := pnexpected
  2388.            end;  (* case_gtprefixname *)
  2389.            
  2390.            
  2391.            procedure case_getsetparm;
  2392.            
  2393.            begin
  2394.              expected := [paritysym, localsym, ibmsym, escsym, prefixsym,
  2395.                           wordlensym, stopbsym, delsym, debugsym, filewarnsym,
  2396.                           baudsym, xonsym, xoffsym, xoffwaitsym, nofeedsym,
  2397.                           timeoutsym, eolnsym, maxtrysym, emulatesym, maxpsym,
  2398.                           textfsym, rejectsym];
  2399.              status := getsym(noun);
  2400.              if status = ateol then
  2401.                  status := parm_expected
  2402.              else if (status <> unrec) and (status <>  ambiguous) then
  2403.                  case noun of
  2404.                    paritysym:   state := get_parity;
  2405.                    prefixsym:   state := get_prefix;
  2406.                    escsym:      state := get_esc_char;
  2407.                    baudsym:     state := get_baud;
  2408.                    wordlensym:  state := get_wordlen;
  2409.                    stopbsym:    state := get_stopbit;
  2410.                    xonsym:      state := get_xon_char;
  2411.                    xoffsym:     state := get_xoff_char;
  2412.                    eolnsym:     state := get_eoln_char;
  2413.                    xoffwaitsym: state := get_xoffwait;
  2414.                    timeoutsym:  state := get_timeout;
  2415.                    maxtrysym:   state := get_maxtry;
  2416.                    maxpsym:     state := get_maxpak;
  2417.                    nofeedsym, filewarnsym, debugsym, delsym, textfsym, 
  2418.                    ibmsym, localsym, rejectsym, emulatesym:
  2419.                                 state := get_on_off;
  2420.                  end (* case *)
  2421.            end; (* case_getsetparm *)
  2422.            
  2423.            
  2424.            procedure case_getparity;
  2425.            
  2426.            begin
  2427.              expected := [marksym, spacesym, nonesym, evensym, oddsym];
  2428.              status := getsym(adj);
  2429.              if status = ateol then
  2430.                  status := parm_expected
  2431.              else if (status <> unrec) and (status <> ambiguous) then
  2432.                  state := fin
  2433.            end; (* case_getparity  *)
  2434.            
  2435.            
  2436.            procedure case_getnum( var newnum : integer );
  2437.            
  2438.            begin
  2439.              expected := [];
  2440.              if get_num( line, newnum ) then
  2441.                begin
  2442.                  status := null; state := fin
  2443.                end
  2444.              else status := num_expected
  2445.            end; (* case_getnum *)
  2446.            
  2447.            
  2448.            procedure case_getonoff;
  2449.            
  2450.            begin
  2451.              expected := [onsym, offsym];
  2452.              status := getsym(adj);
  2453.              if status = ateol then
  2454.                  status := parm_expected
  2455.              else if (status <> unrec) and (status <> ambiguous) then
  2456.                  state := fin
  2457.            end; (* case_ getonoff *)
  2458.            
  2459.            
  2460.            procedure case_getchar( var newchar : char );
  2461.            
  2462.            begin
  2463.              if nextch(newchar) then
  2464.                 state := fin
  2465.              else
  2466.                 status := ch_expected;
  2467.            end; (* case_getchar *)
  2468.            
  2469.            
  2470.            procedure case_gtshowparm;
  2471.            
  2472.            begin
  2473.              expected := [allsym, paritysym, localsym, ibmsym, prefixsym, 
  2474.                           wordlensym, stopbsym, escsym, delsym, debugsym,
  2475.                           filewarnsym, baudsym, xonsym, xoffsym, xoffwaitsym,
  2476.                           nofeedsym, timeoutsym, eolnsym, emulatesym, maxpsym,
  2477.                           maxtrysym, textfsym, rejectsym];
  2478.              status := getsym(noun);
  2479.              if status = ateol then
  2480.                  status := parm_expected
  2481.              else if (status <> unrec) and (status <>  ambiguous) then
  2482.                  state := fin
  2483.            end; (* case_gtshowparm *)
  2484.            
  2485.            
  2486.            procedure case_gethelpshow;
  2487.            
  2488.            begin
  2489.              expected := [paritysym, localsym, ibmsym, escsym, delsym,
  2490.                           wordlensym, stopbsym, debugsym, filewarnsym,
  2491.                           baudsym, xonsym, xoffsym, xoffwaitsym, emulatesym,
  2492.                           nofeedsym, timeoutsym, eolnsym, prefixsym, maxpsym,
  2493.                           maxtrysym, textfsym, rejectsym];
  2494.              status := getsym(adj);
  2495.              if (status = at_eol) then
  2496.                begin
  2497.                  status := null;
  2498.                  state := fin
  2499.                end
  2500.              else if (status <> unrec) and (status <>  ambiguous) then
  2501.                  state := fin
  2502.            end; (* case_gethelpshow *)
  2503.            
  2504.            
  2505.            procedure case_gthelpparm;
  2506.            
  2507.            begin
  2508.              expected := [consym, exitsym, helpsym, phelpsym, quitsym, recsym,
  2509.                           sendsym, setsym, showsym, pshowsym, dirsym, pdirsym];
  2510.              status := getsym(noun);
  2511.              if status = ateol then
  2512.                begin
  2513.                  parse := null;
  2514.                  exit(parse)
  2515.                end;
  2516.              if (status <> unrec) and (status <>  ambiguous) then
  2517.                  case noun of
  2518.                    consym, sendsym, recsym,
  2519.                    showsym, pshowsym, helpsym,
  2520.                    phelpsym, exitsym, quitsym,
  2521.                    dirsym, pdirsym            : state := fin;
  2522.                    setsym                     : state := get_help_show;
  2523.                  end (* case *)
  2524.            end; (* case_gthelpparm *)
  2525.            
  2526.            
  2527. begin  (*  parse  *)
  2528.   state   := start;
  2529.   parse   := null;
  2530.   noun    := nullsym;
  2531.   verb    := nullsym;
  2532.   adj     := nullsym;
  2533.   uppercase ( line );
  2534.   repeat
  2535.     case state of
  2536.       start         : case_start;
  2537.       fin           : case_fin;
  2538.       get_filename  : case_getfilename;
  2539.       get_prefix    : case_gtprefixname;
  2540.       get_set_parm  : case_getsetparm;
  2541.       get_parity    : case_getparity;
  2542.       get_baud      : case_getnum( newbaud );
  2543.       get_wordlen   : case_getnum( newdbit );
  2544.       get_stopbit   : case_getnum( newstopbit );
  2545.       get_xoffwait  : case_getnum( newxoffwait);
  2546.       get_timeout   : case_getnum( newtimeout );
  2547.       get_maxtry    : case_getnum( newmaxtry );
  2548.       get_maxpak    : case_getnum( newmaxpack );
  2549.       get_dir       : case_getnum( vol_num );
  2550.       get_on_off    : case_getonoff;
  2551.       get_esc_char  : case_getchar( newescchar );
  2552.       get_xon_char  : case_getchar( newxonchar );
  2553.       get_xoff_char : case_getchar( newxoffchar);
  2554.       get_eoln_char : case_getchar( newxeol_char );
  2555.       get_show_parm : case_gtshowparm;
  2556.       get_help_show : case_gethelpshow;
  2557.       get_help_parm : case_gthelpparm;
  2558.     end;  { case }
  2559.   until (status <> null);
  2560.   parse := status
  2561. end; (* parse *)
  2562.  
  2563.  
  2564. BEGIN  { initialization }
  2565.   vocablist[allsym]      := 'ALL';
  2566.   vocablist[baudsym]     := 'BAUD';
  2567.   vocablist[consym]      := 'CONNECT';
  2568.   vocablist[debugsym]    := 'DEBUG';
  2569.   vocablist[delsym]      := 'DELKEY';
  2570.   vocablist[dirsym]      := 'DIRECTORY';
  2571.   vocablist[emulatesym]  := 'EMULATE';
  2572.   vocablist[eolnsym]     := 'END-OF-LINE';
  2573.   vocablist[escsym]      := 'ESCAPE';
  2574.   vocablist[evensym]     := 'EVEN';
  2575.   vocablist[exitsym]     := 'EXIT';
  2576.   vocablist[filewarnsym] := 'FILE-WARNING';
  2577.   vocablist[helpsym]     := 'HELP';
  2578.   vocablist[ibmsym]      := 'IBM';
  2579.   vocablist[localsym]    := 'LOCAL-ECHO';
  2580.   vocablist[marksym]     := 'MARK';
  2581.   vocablist[maxpsym]     := 'MAXPACK';
  2582.   vocablist[maxtrysym]   := 'MAXTRY';
  2583.   vocablist[nofeedsym]   := 'NOFEED';
  2584.   vocablist[nonesym]     := 'NONE';
  2585.   vocablist[oddsym]      := 'ODD';
  2586.   vocablist[offsym]      := 'OFF';
  2587.   vocablist[onsym]       := 'ON';
  2588.   vocablist[paritysym]   := 'PARITY';
  2589.   vocablist[pdirsym]     := 'PDIRECTORY';
  2590.   vocablist[phelpsym]    := 'PHELP';
  2591.   vocablist[prefixsym]   := 'PREFIX';
  2592.   vocablist[pshowsym]    := 'PSHOW';
  2593.   vocablist[quitsym]     := 'QUIT';
  2594.   vocablist[recsym]      := 'RECEIVE';
  2595.   vocablist[rejectsym]   := 'REJECT';
  2596.   vocablist[sendsym]     := 'SEND';
  2597.   vocablist[setsym]      := 'SET';
  2598.   vocablist[showsym]     := 'SHOW';
  2599.   vocablist[spacesym]    := 'SPACE';
  2600.   vocablist[stopbsym]    := 'STOPBIT';
  2601.   vocablist[textfsym]    := 'TEXTFILE';
  2602.   vocablist[timeoutsym]  := 'TIMEOUT';
  2603.   vocablist[wordlensym]  := 'WORD-LENGTH';
  2604.   vocablist[xoffsym]     := 'XOFF-CHAR';
  2605.   vocablist[xoffwaitsym] := 'XOFF-WAIT-COUNT';
  2606.   vocablist[xonsym]      := 'XON-CHAR';
  2607.   first_sym := allsym;
  2608.   last_sym  := xonsym;
  2609. END. (* end of unit parser *)
  2610.  
  2611. (*=== KERMSETSHW.TEXT ===*)
  2612.  
  2613. (*$S+*)
  2614. (*$I-*)
  2615. (*$R-*)
  2616. (*$V-*)
  2617.  
  2618. UNIT parser;   INTRINSIC CODE 23  DATA 24;
  2619.  
  2620.  
  2621. INTERFACE
  2622.  
  2623. USES  kermglob,
  2624.       kermutil;
  2625.  
  2626. FUNCTION parse: statustype;
  2627.  
  2628.  
  2629. IMPLEMENTATION
  2630.  
  2631. VAR first_sym, last_sym : vocab;
  2632.  
  2633.  
  2634.   
  2635. PROCEDURE isolate_word ( var line, word : string; var wlen : integer );
  2636.  
  2637. var  line_len : integer;
  2638.  
  2639. begin
  2640.   word := '';  wlen := 0;  linelen := length( line );
  2641.   if linelen > 0
  2642.     then begin
  2643.            delete( line, 1, scan( linelen, <> ' ', line[1] ) );
  2644.            linelen := length( line );
  2645.            if linelen > 0
  2646.              then begin
  2647.                     wlen := scan( linelen, = ' ', line[1] );
  2648.                     word := copy( line, 1, wlen );
  2649.                     delete( line, 1, wlen );
  2650.                   end;
  2651.          end;
  2652. end;  { isolate_word }
  2653.  
  2654.  
  2655.  
  2656. FUNCTION get_fn( var line, fn: string; namelen : integer ) : boolean;
  2657.  
  2658. { checks the length of the filename requested for 'send'.              }
  2659. { Or checks the prefix volume name for files to be received.           }
  2660.  
  2661. var i, l: integer;
  2662.  
  2663. begin
  2664.   get_fn := true;
  2665.   isolate_word( line, fn, l );
  2666.   if (l > namelen) or (l < 1) then get_fn := false
  2667.    { max filename length, incl. volumename = 23 }
  2668.    { max volumename length, incl. ':' = 8 }
  2669.   else begin
  2670.          if (fn[l] = ':') and (namelen=23)  then get_fn := false;
  2671.          if (fn[l] <> ':') and (namelen=8)  then get_fn := false;
  2672.          {  legality of volume and filename will be tested   }
  2673.          {  when the file is actually opened. ( see unit "sender" )   }
  2674.        end;
  2675. end; (* get_fn *)
  2676.  
  2677.  
  2678.  
  2679.  
  2680. FUNCTION get_num( var line: string; var n: integer ): boolean;
  2681.  
  2682. var
  2683.    numstr: string;
  2684.    i, numstr_len  : integer;
  2685. begin
  2686.    get_num := true; n := 0;
  2687.    isolate_word( line, numstr, numstr_len );
  2688.    if (numstr_len < 6) and (numstr_len > 0) then 
  2689.      begin
  2690.        i := 1;
  2691.        numstr := concat( numstr, ' ' );
  2692.        while (numstr[i] in ['0'..'9']) do begin
  2693.           if n<(maxint div 10) then
  2694.              n := n*10 + ord( numstr[i] ) - ord( '0' );
  2695.           i := i + 1
  2696.        end { while }
  2697.      end; { if }
  2698.    if n = 0 then get_num := false;
  2699. end; { get_num }
  2700.  
  2701.  
  2702.  
  2703.  
  2704. FUNCTION nextch(var ch: char): boolean;
  2705.  
  2706. var s: string;
  2707.     ch_len : integer;
  2708.  
  2709. begin
  2710.  isolate_word( line, s, ch_len );
  2711.  if ch_len <= 1 then begin
  2712.                        if ch_len = 1 then ch := s[1]
  2713.                                      else ch := cr;
  2714.                        nextch := true;
  2715.                      end
  2716.                 else nextch := false;
  2717. end; (* nextch *)
  2718.  
  2719.  
  2720.  
  2721. FUNCTION get_sym(var word: vocab): statustype;
  2722.  
  2723. var i: vocab;
  2724.     s: string;
  2725.     stat: statustype;
  2726.     done: boolean;
  2727.     matches, slen : integer;
  2728.  
  2729. begin
  2730.   isolate_word( line, s, slen );
  2731.   if slen = 0 then getsym := ateol
  2732.    else
  2733.      begin
  2734.        stat := null;
  2735.        done := false;
  2736.        i := first_sym;
  2737.        matches := 0;
  2738.        repeat
  2739.            if (pos(s,vocablist[i]) = 1) and (i in expected) then
  2740.              begin
  2741.                matches := matches + 1;
  2742.                word := i
  2743.              end
  2744.            else if (s[1] < vocablist[i,1]) then
  2745.                done := true;
  2746.            if (i = last_sym ) then
  2747.                done := true
  2748.            else
  2749.                i := succ(i)
  2750.        until (matches > 1) or done;
  2751.        if matches > 1 then
  2752.            stat := ambiguous
  2753.        else if (matches = 0) then
  2754.            stat := unrec;
  2755.        getsym := stat
  2756.      end (* else *)
  2757. end; (* getsym *)
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763. FUNCTION parse(*: statustype*);
  2764.  
  2765. type states = (start, fin, get_filename, get_set_parm, get_parity, get_on_off,
  2766.                get_esc_char, get_show_parm, get_help_show, get_help_parm,
  2767.                exitstate, get_baud, get_wordlen, get_stopbit, get_xon_char,
  2768.                get_xoff_char, get_xoffwait, get_nofeed, get_timeout, get_maxpak,
  2769.                get_eoln_char, get_maxtry, get_prefix, get_dir);
  2770.  
  2771. var status: statustype;
  2772.     word: vocab;
  2773.     state: states;
  2774.     
  2775.            procedure case_start;
  2776.     
  2777.            begin
  2778.              expected := [consym, exitsym, helpsym, phelpsym, quitsym, recsym,
  2779.                           sendsym, setsym, showsym, pshowsym, dirsym, pdirsym];
  2780.              status := getsym(verb);
  2781.              if status = ateol then
  2782.                begin
  2783.                  parse := null;
  2784.                  exit(parse)
  2785.                end (* if *)
  2786.              else if (status <> unrec) and (status <>  ambiguous) then
  2787.                  case verb of
  2788.                    consym, recsym, exitsym, quitsym: state := fin;
  2789.                    helpsym         : begin
  2790.                                        state := get_help_parm;
  2791.                                        pr_out:= false
  2792.                                      end;
  2793.                    phelpsym        : begin
  2794.                                        state := get_help_parm;
  2795.                                        pr_out:= true
  2796.                                      end;
  2797.                    dirsym          : begin
  2798.                                        state := get_dir;
  2799.                                        pr_out := false;
  2800.                                      end;
  2801.                    pdirsym         : begin
  2802.                                        state := get_dir;
  2803.                                        pr_out := true;
  2804.                                      end;
  2805.                    sendsym         : state := getfilename;
  2806.                    setsym          : state := get_set_parm;
  2807.                    showsym         : begin
  2808.                                        state := get_show_parm;
  2809.                                        pr_out:= false
  2810.                                      end;
  2811.                    pshowsym        : begin
  2812.                                        state := get_show_parm;
  2813.                                        pr_out:= true
  2814.                                      end;
  2815.                  end (* case *)
  2816.            end; (* case_start *)
  2817.            
  2818.            
  2819.            procedure case_fin;
  2820.            
  2821.            begin
  2822.              expected := [];
  2823.              status := getsym(verb);
  2824.              if status = ateol then
  2825.                begin
  2826.                  parse := null;
  2827.                  exit(parse)
  2828.                end (* if status *)
  2829.              else
  2830.                  status := unconfirmed
  2831.            end; (* case_fin *)
  2832.            
  2833.            
  2834.            procedure case_getfilename;
  2835.            
  2836.            begin
  2837.              expected := [];
  2838.              if getfn(line,xfilename,23) then
  2839.                begin
  2840.                  status := null;
  2841.                  state := fin
  2842.                end (* if *)
  2843.              else
  2844.                  status := fnexpected
  2845.            end; (* case_getfilename *)
  2846.            
  2847.            
  2848.            procedure case_gtprefixname;
  2849.            
  2850.            begin
  2851.              expected := [];
  2852.              if getfn(line,newprefix_vol,8) then
  2853.                begin
  2854.                  status := null;
  2855.                  state := fin
  2856.                end
  2857.              else
  2858.                   status := pnexpected
  2859.            end;  (* case_gtprefixname *)
  2860.            
  2861.            
  2862.            procedure case_getsetparm;
  2863.            
  2864.            begin
  2865.              expected := [paritysym, localsym, ibmsym, escsym, prefixsym,
  2866.                           wordlensym, stopbsym, delsym, debugsym, filewarnsym,
  2867.                           baudsym, xonsym, xoffsym, xoffwaitsym, nofeedsym,
  2868.                           timeoutsym, eolnsym, maxtrysym, emulatesym, maxpsym,
  2869.                           textfsym, rejectsym];
  2870.              status := getsym(noun);
  2871.              if status = ateol then
  2872.                  status := parm_expected
  2873.              else if (status <> unrec) and (status <>  ambiguous) then
  2874.                  case noun of
  2875.                    paritysym:   state := get_parity;
  2876.                    prefixsym:   state := get_prefix;
  2877.                    escsym:      state := get_esc_char;
  2878.                    baudsym:     state := get_baud;
  2879.                    wordlensym:  state := get_wordlen;
  2880.                    stopbsym:    state := get_stopbit;
  2881.                    xonsym:      state := get_xon_char;
  2882.                    xoffsym:     state := get_xoff_char;
  2883.                    eolnsym:     state := get_eoln_char;
  2884.                    xoffwaitsym: state := get_xoffwait;
  2885.                    timeoutsym:  state := get_timeout;
  2886.                    maxtrysym:   state := get_maxtry;
  2887.                    maxpsym:     state := get_maxpak;
  2888.                    nofeedsym, filewarnsym, debugsym, delsym, textfsym, 
  2889.                    ibmsym, localsym, rejectsym, emulatesym:
  2890.                                 state := get_on_off;
  2891.                  end (* case *)
  2892.            end; (* case_getsetparm *)
  2893.            
  2894.            
  2895.            procedure case_getparity;
  2896.            
  2897.            begin
  2898.              expected := [marksym, spacesym, nonesym, evensym, oddsym];
  2899.              status := getsym(adj);
  2900.              if status = ateol then
  2901.                  status := parm_expected
  2902.              else if (status <> unrec) and (status <> ambiguous) then
  2903.                  state := fin
  2904.            end; (* case_getparity  *)
  2905.            
  2906.            
  2907.            procedure case_getnum( var newnum : integer );
  2908.            
  2909.            begin
  2910.              expected := [];
  2911.              if get_num( line, newnum ) then
  2912.                begin
  2913.                  status := null; state := fin
  2914.                end
  2915.              else status := num_expected
  2916.            end; (* case_getnum *)
  2917.            
  2918.            
  2919.            procedure case_getonoff;
  2920.            
  2921.            begin
  2922.              expected := [onsym, offsym];
  2923.              status := getsym(adj);
  2924.              if status = ateol then
  2925.                  status := parm_expected
  2926.              else if (status <> unrec) and (status <> ambiguous) then
  2927.                  state := fin
  2928.            end; (* case_ getonoff *)
  2929.            
  2930.            
  2931.            procedure case_getchar( var newchar : char );
  2932.            
  2933.            begin
  2934.              if nextch(newchar) then
  2935.                 state := fin
  2936.              else
  2937.                 status := ch_expected;
  2938.            end; (* case_getchar *)
  2939.            
  2940.            
  2941.            procedure case_gtshowparm;
  2942.            
  2943.            begin
  2944.              expected := [allsym, paritysym, localsym, ibmsym, prefixsym, 
  2945.                           wordlensym, stopbsym, escsym, delsym, debugsym,
  2946.                           filewarnsym, baudsym, xonsym, xoffsym, xoffwaitsym,
  2947.                           nofeedsym, timeoutsym, eolnsym, emulatesym, maxpsym,
  2948.                           maxtrysym, textfsym, rejectsym];
  2949.              status := getsym(noun);
  2950.              if status = ateol then
  2951.                  status := parm_expected
  2952.              else if (status <> unrec) and (status <>  ambiguous) then
  2953.                  state := fin
  2954.            end; (* case_gtshowparm *)
  2955.            
  2956.            
  2957.            procedure case_gethelpshow;
  2958.            
  2959.            begin
  2960.              expected := [paritysym, localsym, ibmsym, escsym, delsym,
  2961.                           wordlensym, stopbsym, debugsym, filewarnsym,
  2962.                           baudsym, xonsym, xoffsym, xoffwaitsym, emulatesym,
  2963.                           nofeedsym, timeoutsym, eolnsym, prefixsym, maxpsym,
  2964.                           maxtrysym, textfsym, rejectsym];
  2965.              status := getsym(adj);
  2966.              if (status = at_eol) then
  2967.                begin
  2968.                  status := null;
  2969.                  state := fin
  2970.                end
  2971.              else if (status <> unrec) and (status <>  ambiguous) then
  2972.                  state := fin
  2973.            end; (* case_gethelpshow *)
  2974.            
  2975.            
  2976.            procedure case_gthelpparm;
  2977.            
  2978.            begin
  2979.              expected := [consym, exitsym, helpsym, phelpsym, quitsym, recsym,
  2980.                           sendsym, setsym, showsym, pshowsym, dirsym, pdirsym];
  2981.              status := getsym(noun);
  2982.              if status = ateol then
  2983.                begin
  2984.                  parse := null;
  2985.                  exit(parse)
  2986.                end;
  2987.              if (status <> unrec) and (status <>  ambiguous) then
  2988.                  case noun of
  2989.                    consym, sendsym, recsym,
  2990.                    showsym, pshowsym, helpsym,
  2991.                    phelpsym, exitsym, quitsym,
  2992.                    dirsym, pdirsym            : state := fin;
  2993.                    setsym                     : state := get_help_show;
  2994.                  end (* case *)
  2995.            end; (* case_gthelpparm *)
  2996.            
  2997.            
  2998. begin  (*  parse  *)
  2999.   state   := start;
  3000.   parse   := null;
  3001.   noun    := nullsym;
  3002.   verb    := nullsym;
  3003.   adj     := nullsym;
  3004.   uppercase ( line );
  3005.   repeat
  3006.     case state of
  3007.       start         : case_start;
  3008.       fin           : case_fin;
  3009.       get_filename  : case_getfilename;
  3010.       get_prefix    : case_gtprefixname;
  3011.       get_set_parm  : case_getsetparm;
  3012.       get_parity    : case_getparity;
  3013.       get_baud      : case_getnum( newbaud );
  3014.       get_wordlen   : case_getnum( newdbit );
  3015.       get_stopbit   : case_getnum( newstopbit );
  3016.       get_xoffwait  : case_getnum( newxoffwait);
  3017.       get_timeout   : case_getnum( newtimeout );
  3018.       get_maxtry    : case_getnum( newmaxtry );
  3019.       get_maxpak    : case_getnum( newmaxpack );
  3020.       get_dir       : case_getnum( vol_num );
  3021.       get_on_off    : case_getonoff;
  3022.       get_esc_char  : case_getchar( newescchar );
  3023.       get_xon_char  : case_getchar( newxonchar );
  3024.       get_xoff_char : case_getchar( newxoffchar);
  3025.       get_eoln_char : case_getchar( newxeol_char );
  3026.       get_show_parm : case_gtshowparm;
  3027.       get_help_show : case_gethelpshow;
  3028.       get_help_parm : case_gthelpparm;
  3029.     end;  { case }
  3030.   until (status <> null);
  3031.   parse := status
  3032. end; (* parse *)
  3033.  
  3034.  
  3035. BEGIN  { initialization }
  3036.   vocablist[allsym]      := 'ALL';
  3037.   vocablist[baudsym]     := 'BAUD';
  3038.   vocablist[consym]      := 'CONNECT';
  3039.   vocablist[debugsym]    := 'DEBUG';
  3040.   vocablist[delsym]      := 'DELKEY';
  3041.   vocablist[dirsym]      := 'DIRECTORY';
  3042.   vocablist[emulatesym]  := 'EMULATE';
  3043.   vocablist[eolnsym]     := 'END-OF-LINE';
  3044.   vocablist[escsym]      := 'ESCAPE';
  3045.   vocablist[evensym]     := 'EVEN';
  3046.   vocablist[exitsym]     := 'EXIT';
  3047.   vocablist[filewarnsym] := 'FILE-WARNING';
  3048.   vocablist[helpsym]     := 'HELP';
  3049.   vocablist[ibmsym]      := 'IBM';
  3050.   vocablist[localsym]    := 'LOCAL-ECHO';
  3051.   vocablist[marksym]     := 'MARK';
  3052.   vocablist[maxpsym]     := 'MAXPACK';
  3053.   vocablist[maxtrysym]   := 'MAXTRY';
  3054.   vocablist[nofeedsym]   := 'NOFEED';
  3055.   vocablist[nonesym]     := 'NONE';
  3056.   vocablist[oddsym]      := 'ODD';
  3057.   vocablist[offsym]      := 'OFF';
  3058.   vocablist[onsym]       := 'ON';
  3059.   vocablist[paritysym]   := 'PARITY';
  3060.   vocablist[pdirsym]     := 'PDIRECTORY';
  3061.   vocablist[phelpsym]    := 'PHELP';
  3062.   vocablist[prefixsym]   := 'PREFIX';
  3063.   vocablist[pshowsym]    := 'PSHOW';
  3064.   vocablist[quitsym]     := 'QUIT';
  3065.   vocablist[recsym]      := 'RECEIVE';
  3066.   vocablist[rejectsym]   := 'REJECT';
  3067.   vocablist[sendsym]     := 'SEND';
  3068.   vocablist[setsym]      := 'SET';
  3069.   vocablist[showsym]     := 'SHOW';
  3070.   vocablist[spacesym]    := 'SPACE';
  3071.   vocablist[stopbsym]    := 'STOPBIT';
  3072.   vocablist[textfsym]    := 'TEXTFILE';
  3073.   vocablist[timeoutsym]  := 'TIMEOUT';
  3074.   vocablist[wordlensym]  := 'WORD-LENGTH';
  3075.   vocablist[xoffsym]     := 'XOFF-CHAR';
  3076.   vocablist[xoffwaitsym] := 'XOFF-WAIT-COUNT';
  3077.   vocablist[xonsym]      := 'XON-CHAR';
  3078.   first_sym := allsym;
  3079.   last_sym  := xonsym;
  3080. END. (* end of unit parser *)
  3081. (*=== KERMSETSHW.TEXT ===*)
  3082. (* >>>> KERMSETSHW.TEXT ************************************************)
  3083.  
  3084. (*$I-*)
  3085. (*$R-*)
  3086. (*$S+*)
  3087. (*$V-*)
  3088.  
  3089. UNIT KERMSETSHW;         INTRINSIC CODE   27;
  3090.  
  3091. INTERFACE
  3092.  
  3093. USES kermglob, kermacia, kermutil;
  3094.  
  3095.  
  3096. PROCEDURE  show_parms;
  3097.  
  3098. PROCEDURE  set_parms;
  3099.  
  3100.  
  3101. IMPLEMENTATION
  3102.  
  3103.  
  3104. PROCEDURE show_dir( list_device : integer );
  3105.  
  3106. { lists all the files in the directory from the requested diskunit number  }
  3107.  
  3108. var space   : packed array[1..15] of char;
  3109.     fil_type ,file_count, file_num : integer;
  3110.  
  3111.  
  3112. PROCEDURE list_names ( start, quit : integer );
  3113.  
  3114. var   len : integer;
  3115.  
  3116. begin
  3117.   while (filecount < filenum) and (start < quit) do
  3118.     begin
  3119.       len := ord( filebuf[start-1] );
  3120.       fil_type := ord( filebuf[start-3] );
  3121.       if (len > 0) and (len < 16) and (fil_type < 6) then
  3122.         begin
  3123.           unitwrite( list_device, filebuf[start], len );
  3124.           unitwrite( list_device, space[1], 16-len );
  3125.           file_count := file_count + 1;
  3126.         end;
  3127.       start := start + 26;
  3128.     end;
  3129. end;  { list_names}
  3130.  
  3131. begin  { show_dir }
  3132.   space := '               '; 
  3133.   if (volnum=4) or (volnum=5) or ((volnum>8) and (volnum<13))
  3134.     then begin
  3135.            unitread( vol_num, filebuf[1], page_size, 2 );
  3136.            if ioresult <> 0 then begin
  3137.                                    writeln('not on line');
  3138.                                    writeln;
  3139.                                    exit( show_dir );
  3140.                                  end;
  3141.            writeln(p); write(p,'Volume name is : ');
  3142.            unitwrite( list_device, filebuf[8], ord( filebuf[7] ) );
  3143.            file_num := ord( filebuf[17] );
  3144.            file_count := 0;
  3145.            writeln(p); writeln(p);
  3146.            list_names(34, pagesize-27);
  3147.            if (filecount < filenum) then
  3148.              begin
  3149.                moveleft( filebuf[pagesize-9], filebuf[1], 10 );
  3150.                unitread( vol_num, filebuf[11], page_size - 10, 4 );
  3151.                list_names( 8, pagesize-27);
  3152.              end;
  3153.            writeln(p);
  3154.            writeln(p);
  3155.          end
  3156.     else begin
  3157.            writeln('not a disk volume');
  3158.            writeln;
  3159.          end;
  3160.  end;    { show_dir }
  3161.  
  3162.  
  3163. PROCEDURE show_p1;
  3164.  
  3165. (* shows the various settable parameters *)
  3166.  
  3167. var list_device : integer;
  3168.  
  3169. begin
  3170.   close( p );
  3171.   if pr_out and print_enable
  3172.     then begin
  3173.            reset(p, pr_file);
  3174.            list_device := line_printer;
  3175.          end
  3176.     else begin
  3177.            reset(p, cs_file);
  3178.            list_device := consol;
  3179.          end;
  3180.   writeln;
  3181.   if (verb = dirsym) or (verb = pdirsym)
  3182.     then begin
  3183.            show_dir( list_device );
  3184.            pr_out := false;
  3185.            exit( show_parms )
  3186.          end;
  3187.   if noun = allsym then
  3188.     begin
  3189.       page(output);
  3190.       writeln(p,'SERIAL PORT SETTINGS');
  3191.       writeln(p);
  3192.     end;
  3193.   if (noun=allsym) or (noun=baudsym) then
  3194.     writeln(p,'   BAUD rate is ', baud );
  3195.   if (noun=allsym) or (noun=paritysym) then
  3196.     begin
  3197.       case parity of
  3198.         evenpar  : write(p,'   EVEN');
  3199.         markpar  : write(p,'   MARK');
  3200.         nopar    : write(p,'   NONE');
  3201.         oddpar   : write(p,'   ODD');
  3202.         spacepar : write(p,'   SPACE');
  3203.       end; { case }
  3204.       writeln(p,' PARITY');
  3205.     end; { if }
  3206.   if (noun=allsym) or (noun=wordlensym) then
  3207.     writeln(p,'   WORD-LENGTH is ', data_bit ,' bits');
  3208.   if (noun=allsym) or (noun=stopbsym) then
  3209.     begin
  3210.       write(p,'   Number of STOPBITs is ');
  3211.       if stopbit = 15 then writeln(p,'1.5') else writeln(p, stopbit );
  3212.     end; { if }
  3213.   if (noun=allsym) or (noun=localsym) then
  3214.     write_bool('   LOCAL-ECHO is ', halfduplex );
  3215. end; { show_p1 }
  3216.  
  3217.  
  3218. PROCEDURE show_p2;
  3219.  
  3220. begin
  3221.   if (noun=allsym) then
  3222.     begin
  3223.       writeln(p);
  3224.       writeln(p,'TERMINAL MODE RELATED SETTINGS');
  3225.       writeln(p);
  3226.     end;
  3227.   if (noun=allsym) or (noun=emulatesym) then
  3228.     writeln(p,'   EMULATE  is not implemented.' );
  3229.   if (noun=allsym) or (noun=escsym) then
  3230.     begin
  3231.       write(p,'   Terminal ESCAPE key is ');
  3232.       write_ctl( esc_char );
  3233.       writeln(p);
  3234.     end;
  3235.   if (noun=allsym) or (noun=rejectsym) then
  3236.     write_bool('   REJECT incoming control characters is ', reject_cntrl_char);
  3237.   if (noun=allsym) or (noun=delsym) then
  3238.     begin
  3239.       write(p,'   DELKEY (backspace key code send to host = ');
  3240.       write_ctl( bs_to_del ); write(p,' ) is ');
  3241.       if bs_to_del = chr(del) then writeln(p,'ON') else writeln(p,'OFF');
  3242.     end;
  3243.   if (noun=allsym) or (noun=xonsym) then
  3244.     begin
  3245.       write(p,'   XON-CHAR is ');
  3246.       write_ctl( xon_char );
  3247.       writeln(p,' ( screendump and ibm = on only )');
  3248.     end;
  3249.   if (noun=allsym) or (noun=xoffsym) then
  3250.     begin
  3251.       write(p,'   XOFF-CHAR is ');
  3252.       write_ctl( xoff_char );
  3253.       writeln(p,' ( screendump only )');
  3254.     end;
  3255.   if (noun=allsym) or (noun=xoffwaitsym) then
  3256.     writeln(p,'   XOFF-WAIT-COUNT is ', xoffwtime ,'   ( screendump only )');
  3257.   if (noun=allsym) or (noun=nofeedsym) then
  3258.     write_bool('   NOFEED (form-feed during screendump) is ', no_ffeed );
  3259.   if (noun=allsym) or (noun=ibmsym) then
  3260.     write_bool('   IBM vm/cms settings are ', ibm );
  3261.   if (noun=allsym) then
  3262.     begin
  3263.       if not ( pr_out and print_enable ) then
  3264.         begin
  3265.           writeln;
  3266.           write('>>> PRESS <RETURN> FOR MORE <<<');
  3267.           readln;
  3268.         end;
  3269.       writeln(p);
  3270.       writeln(p,'FILE TRANSFER RELATED SETTINGS');
  3271.       writeln(p);
  3272.     end;
  3273. end;  { show_p2 }
  3274.  
  3275.  
  3276. PROCEDURE  show_p3;
  3277.  
  3278. begin
  3279.   if (noun=allsym) or (noun=debugsym) then
  3280.     write_bool('   DEBUGging is ', debug );
  3281.   if (noun=allsym) or (noun=filewarnsym) then
  3282.     write_bool('   FILE-WARNING is ', fwarn );
  3283.   if (noun=allsym) or (noun=textfsym) then
  3284.     write_bool('   TEXTFILE send & receive is ', text_file );
  3285.   if (noun=allsym) or (noun=prefixsym) then
  3286.     writeln(p, '   PREFIX volume for received files is ', prefix_vol );
  3287.   if (noun=allsym) or (noun=timeoutsym) then
  3288.     writeln(p, '   TIMEOUT period specified to host is about ',mytime,' sec');
  3289.   if (noun=allsym) or (noun=maxtrysym) then
  3290.     begin
  3291.     writeln(p,'   MAXTRY ( number of retries before breaking off ) is ',maxtry);
  3292.     writeln(p,'          ( Initial retries =  5 * maxtry )');
  3293.     end;
  3294.   if (noun=allsym) or (noun=eolnsym) then
  3295.     begin
  3296.       write(p,'   END-OF-LINE character send after each package is ');
  3297.       write_ctl( xeol_char );
  3298.       writeln(p);
  3299.     end;
  3300.   if (noun=allsym) or (noun=maxpsym) then
  3301.       writeln(p,'   MAXPACK: packetsize (20..', def_maxpack,
  3302.                                                ') I can receive is ', maxpack );
  3303.   if (noun=allsym) then
  3304.     begin
  3305.       write(p,'   Kermit packet starts with '); write_ctl( soh_char );
  3306.       writeln(p);
  3307.       write(p,'   My padding character is '); write_ctl( my_pchar );
  3308.       writeln(p);
  3309.       writeln(p,'   Number of padding char''s  I need is ', my_pad );
  3310.       writeln(p,'   My quote char for control char''s is ', my_quote );
  3311.     end;
  3312.   writeln(p);
  3313.    close( p ); reset( p, cs_file ); 
  3314. end; { show_p3 }
  3315.     
  3316.     
  3317. PROCEDURE  show_parms;
  3318.  
  3319. begin
  3320.   show_p1;
  3321.   show_p2;
  3322.   show_p3;
  3323.   pr_out := false;
  3324. end;  { show_parms }
  3325.  
  3326.  
  3327.  
  3328. PROCEDURE set_parms;
  3329.  
  3330. (* sets the parameters *)
  3331.  
  3332. begin
  3333.   case noun of
  3334.     debugsym   : debug := ( adj = onsym );
  3335.     emulatesym : ;
  3336.     textfsym   : textfile := ( adj = onsym );
  3337.     prefixsym  : prefix_vol := newprefix_vol;
  3338.     rejectsym  : reject_cntrl_char := ( adj = onsym );
  3339.     nofeedsym  : no_ffeed := ( adj = onsym );
  3340.     xonsym     : xonchar := newxonchar;
  3341.     xoffsym    : xoffchar := newxoffchar;
  3342.     eolnsym    : xeol_char := new_xeol_char;
  3343.     escsym     : esc_char := new_esc_char;
  3344.     delsym     : case adj of
  3345.                    onsym  : bs_to_del := chr(del);
  3346.                    offsym : bs_to_del := backsp;
  3347.                  end;
  3348.     filewarnsym: fwarn := (adj = onsym);
  3349.     xoffwaitsym: if newxoffwait < 256 then xoffwtime := newxoffwait;
  3350.     maxtrysym  : begin
  3351.                    maxtry := newmaxtry;
  3352.                    inittry := 5 * maxtry;
  3353.                  end;
  3354.     maxpsym    : if (new_maxpack <= def_maxpack ) and (new_maxpack >= 20)
  3355.                    then maxpack := new_maxpack;
  3356.     timeoutsym : if newtimeout < 32  then begin
  3357.                                             my_time := newtimeout; 
  3358.                                             xtime := my_time;
  3359.                                           end;
  3360.     ibmsym     : case adj of
  3361.                    onsym : begin
  3362.                              set_acia_parms(markpar,databit,stopbit,baud);
  3363.                              get_acia_parms(parity,databit,stopbit,baud);
  3364.                              if parity = mark_par
  3365.                                then begin
  3366.                                       ibm := true;
  3367.                                       half_duplex := true;
  3368.                                     end;
  3369.                            end; (* onsym *)
  3370.                    offsym: begin
  3371.                              ibm := false;
  3372.                              half_duplex := false;
  3373.                            end; (* offsym *)
  3374.                  end; (* case adj *)
  3375.     localsym   : if not ibm then halfduplex := (adj = onsym);
  3376.     paritysym  : if not ibm then
  3377.                  case adj of
  3378.                    evensym: new_par:= evenpar;
  3379.                    marksym: new_par:= markpar;
  3380.                    nonesym: new_par:= nopar;
  3381.                    oddsym:  new_par:= oddpar;
  3382.                    spacesym:new_par:= spacepar;
  3383.                  end; (* case *)
  3384.   end; (* case noun *)
  3385.   case noun of
  3386.     paritysym  : set_acia_parms( new_par,data_bit, stop_bit, baud );
  3387.     baudsym    : set_acia_parms( parity, data_bit, stop_bit, new_baud );
  3388.     wordlensym : set_acia_parms( parity, new_dbit, stop_bit, baud );
  3389.     stopbsym   : set_acia_parms( parity, data_bit, new_stopbit, baud );
  3390.   end; { case }
  3391.     get_acia_parms( parity,  data_bit, stop_bit,    baud     );
  3392. end; (* set_parms *)
  3393.  
  3394. begin
  3395. end.     {  kermsetshw }
  3396. (*=== KERMINIT.TEXT ===*)
  3397. (*>>>>>>>>>>>>KERMINIT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*)
  3398.  
  3399. (*$I-*)
  3400. (*$R-*)
  3401. (*$S+*)
  3402. (*$V-*)
  3403.  
  3404. UNIT KERMINIT;      INTRINSIC  CODE  29;
  3405.  
  3406. INTERFACE
  3407.  
  3408. USES  kermglob,
  3409.       kermacia,
  3410.       kermutil;
  3411.  
  3412. PROCEDURE initialize;
  3413.  
  3414.  
  3415. IMPLEMENTATION
  3416.  
  3417. PROCEDURE initialize;
  3418.  
  3419. { reads system.miscinfo and the default parameter file kermit.data and }
  3420. { does other necessary initializations }
  3421.  
  3422.  
  3423. PROCEDURE  logo;
  3424.  
  3425. begin
  3426.   page( output );
  3427.   gotoxy(17,2);  write('K    E    R    M    I    T');
  3428.   gotoxy(21,4);  write('VERSION ', version );
  3429.   gotoxy(28,5);  write('for');
  3430.   gotoxy(17,6);  write('Apple ][(e) UCSD p-system');
  3431.   gotoxy(10,17); write('Adapted from the IBM PC UCSD version by :');
  3432.   gotoxy(24,19); write('P. Terpstra');
  3433.   gotoxy(20,20); write('University Groningen');
  3434.   gotoxy(23,21); write('Nijenborgh 16');
  3435.   gotoxy(25,22); write('Groningen');
  3436.   gotoxy(22,23); write('The Netherlands');
  3437. end;  { logo }
  3438.  
  3439.  
  3440. PROCEDURE  check_io ( io_status : integer;  filename : string );
  3441.  
  3442. begin
  3443.   if io_status <> 0 then
  3444.     begin
  3445.       io_error( io_status );
  3446.       gotoxy( 50, error_line );
  3447.       write( filename );
  3448.       exit( program );
  3449.     end;
  3450. end;   {  check_io  }
  3451.  
  3452.   
  3453.   
  3454. PROCEDURE get_crt_info;
  3455.  
  3456. { read system.miscinfo to get terminal independent screen operations }
  3457.  
  3458. var      byte : 0..255;
  3459.          i : integer;
  3460.          
  3461. begin
  3462.   reset( untyped_f, sys_misc_file );
  3463.   check_io( ioresult, sys_misc_file );
  3464.   i := blockread( untyped_f, file_buf[1], 1 );
  3465.   if i <> 1 then check_io( 64, sys_misc_file );
  3466.   close( untyped_f );
  3467.   prefix := file_buf[63];        byte := ord( file_buf[73] );
  3468.   prefixed[ sc_up      ] := odd( byte );         {cursor up}
  3469.   prefixed[ sc_right   ] := odd( byte div   2 ); {cursor right}
  3470.   prefixed[ sc_clreol  ] := odd( byte div   4 ); {clear to end of line}
  3471.   prefixed[ sc_clreos  ] := odd( byte div   8 ); {clear to end of screen}
  3472.   prefixed[ sc_home    ] := odd( byte div  16 ); {cursor home}
  3473.   prefixed[ sc_delchar ] := odd( byte div  32 ); {often not implemented}
  3474.   prefixed[ sc_clrall  ] := odd( byte div  64 ); {clear whole screen}
  3475.   prefixed[ sc_clrline ] := odd( byte div 128 ); {often not implemented}
  3476.   prefixed[ sc_left    ] := false; {cursor left:no prefix in sys.miscinfo}
  3477.   prefixed[ sc_down    ] := false; {cursor down:no prefix in sys.miscinfo}
  3478.   rlf       := file_buf[68]; {reverse line feed: cursor up}
  3479.   ndfs      := file_buf[67]; {non destructive space forward: cursor right}
  3480.   eraseol   := file_buf[66]; {from cursor: clear to end of line}
  3481.   eraseos   := file_buf[65]; {from cursor: clear to end of screen}
  3482.   home      := file_buf[64]; {cursor to x=0, y=0}
  3483.   delchar   := file_buf[69]; {backspace with deleting: often same as backsp}
  3484.   clrscreen := file_buf[72]; {clear whole screen}
  3485.   clrline   := file_buf[71]; {clear one whole line: often not possible}
  3486.   backsp    := chr( backspace ); {see kermglob: mostly chr(8) }
  3487.   lf        := chr( linefeed  ); {see kermglob: mostly chr(10) }
  3488.   cr        := chr( eoline );    {see kermglob: mostly chr(13) }
  3489.   ff        := chr( formfeed );  {see kermglob: mostly chr(12) }
  3490. end;  { procedure get_crt_info }
  3491.   
  3492.  
  3493. PROCEDURE read_defaults;
  3494.  
  3495. var temp : integer;
  3496.     temp_bool : boolean;
  3497.  
  3498. begin
  3499.   reset( def, setup_file );
  3500.   check_io( ioresult, setup_file );
  3501.   esc_char        := chr( def^ ); get( def );
  3502.   eoln_char       := chr( def^ ); get( def );
  3503.   my_quote        := chr( def^ ); get( def );
  3504.   my_pchar        := chr( def^ ); get( def );
  3505.   my_pad          :=      def^  ; get( def );
  3506.   soh_char        := chr( def^ ); get( def );
  3507.   int_key         := chr( def^ ); get( def );
  3508.   xon_char        := chr( def^ ); get( def );
  3509.   xoff_char       := chr( def^ ); get( def );
  3510.   xoff_w_time     :=      def^  ; get( def );
  3511.   max_pack        :=      def^  ; get( def );
  3512.   if (maxpack < 20) or (maxpack > def_maxpack) then  maxpack := def_maxpack;
  3513.   max_try         :=      def^  ; get( def );
  3514.   my_time         :=      def^  ; get( def );
  3515.   if my_time < 1 then my_time := 1 else if my_time > 31 then my_time := 31;
  3516.   half_duplex     := odd( def^ ); get( def );
  3517.   debug           := odd( def^ ); get( def );
  3518.   fwarn           := odd( def^ ); get( def );
  3519.   text_file       := odd( def^ ); get( def );
  3520.   no_ffeed        := odd( def^ ); get( def );
  3521.   rejectcntrlchar := odd( def^ ); get( def );
  3522.   temp_bool       := odd( def^ ); get( def );
  3523.   if temp_bool then bs_to_del := chr(del) else bs_to_del := backsp;
  3524.   temp            :=      def^  ; get( def );
  3525.   acia_implem     := unknown;
  3526.   if temp = 1 then acia_implem := A6551;
  3527.   if temp = 2 then acia_implem := A6850;
  3528.   acia_comm_reg   :=      def^  ; get( def );
  3529.   acia_cntrl_reg  :=      def^  ; get( def );
  3530.   new_baud        :=      def^  ; get( def );
  3531.   new_dbit        :=      def^  ; get( def );
  3532.   new_stopbit     :=      def^  ; get( def );
  3533.   temp            :=      def^  ; get( def );
  3534.   new_par := no_par;
  3535.   case temp of
  3536.     0 : new_par := no_par;
  3537.     1 : new_par := odd_par;
  3538.     2 : new_par := even_par;
  3539.     3 : new_par := mark_par;
  3540.     4 : new_par := space_par;
  3541.   end;
  3542.   temp           :=      def^   ;
  3543.   if temp = 80 then begin 
  3544.                       no_sfb_char := no_sp_char;
  3545.                       sfb_char    := stop_flush_break_sp_char;
  3546.                     end
  3547.                else begin
  3548.                       no_sfb_char := scr_40_sp_char;
  3549.                       sfb_char    := all_sp_char;
  3550.                     end;
  3551.   close( def );
  3552. end;    {  read_defaults  }
  3553.  
  3554.  
  3555. PROCEDURE  other_defaults;
  3556.  
  3557. begin
  3558.   ibm       :=   false;
  3559.   emulate   :=   false;
  3560.   pr_out    :=   false;
  3561.   xdle_char :=   chr( xdle );
  3562.   xeol_char :=   eoln_char;
  3563.   quote     :=   my_quote;
  3564.   pad       :=   my_pad;
  3565.   pad_char  :=   my_pchar;
  3566.   xtime     :=   my_time;
  3567.   prefix_vol:=   ':';
  3568.   init_try  :=   5 * max_try;
  3569.   print_enable := test_printer;
  3570.   err_string   := 'Error at host';
  3571.   reset( p, cs_file ); 
  3572.   ctl_set := [ chr(0)..chr(31), chr(del) ];
  3573.   check_apple_char( no_sfb_char );
  3574.   check_apple_char( mask_msbit_remin );
  3575.   with controlword do
  3576.     begin
  3577.       channel := inp;
  3578.       purpose := status;
  3579.       reserved:= 0;
  3580.       special_req := none;
  3581.       filler  := 0
  3582.     end;
  3583.   baud := new_baud;
  3584.   if (acia_implem=A6551) or (acia_implem=A6850)
  3585.     then begin
  3586.            set_acia_parms( new_par, new_dbit, new_stopbit, new_baud );
  3587.            get_acia_parms( parity, databit, stopbit, baud );
  3588.          end
  3589.     else begin
  3590.            parity  := new_par;
  3591.            stopbit := new_stopbit;
  3592.            databit := new_dbit;
  3593.          end;
  3594. end;   {  other_defaults }
  3595.  
  3596.  
  3597. begin   {  initialize  }
  3598.   logo;
  3599.   get_crt_info;
  3600.   read_defaults;
  3601.   other_defaults;
  3602.   writeln;
  3603.   writeln;
  3604. end;   {  initialize  }
  3605.  
  3606.  
  3607. begin
  3608. end.   {  kerminit  }
  3609. (*=== HELPER.TEXT ===*)
  3610. (* >>>> HELPER.TEXT  **************************************************)
  3611.  
  3612. (*$I-*)
  3613. (*$R-*)
  3614. (*$S+*)
  3615. (*$V-*)
  3616.  
  3617. UNIT helper;      INTRINSIC  CODE 22;
  3618.  
  3619.  
  3620. INTERFACE
  3621.  
  3622. USES  kermglob,
  3623.       kermutil;
  3624.  
  3625. PROCEDURE help;
  3626.  
  3627. IMPLEMENTATION
  3628.  
  3629. PROCEDURE help;
  3630.  
  3631.  
  3632. const  scrpr   = 'resp. on screen or on the printer.';
  3633.        numpar  = 'Takes a number as parameter.';
  3634.        charpar = 'Takes a character as parameter.';
  3635.        onoffp  = 'Takes ON / OFF as parameter.';
  3636.        conval  = 'Valid only during CONNECT.';
  3637.        ftval   = 'Valid only during file transfer.';
  3638.        dumpval = 'Valid only in screendump mode.';
  3639.  
  3640. Var  i : integer;
  3641.      ch : char;
  3642.  
  3643.  
  3644. (************  Auxiliary procedures ***********************************)
  3645.  
  3646.  
  3647.  
  3648. PROCEDURE wait;
  3649.  
  3650. begin
  3651.   if not pr_out then
  3652.     begin
  3653.       ch := ' ';
  3654.       gotoxy( 0, 23 );
  3655.       write('----------- ');
  3656.       write('( Type <spacebar> to continue or '); write_ctl( esc_char );
  3657.       write(' to quit help ) ------------');
  3658.       read( keyboard, ch );
  3659.       if ch = esc_char then begin
  3660.                               writeln;
  3661.                               writeln;
  3662.                               exit( help );
  3663.                             end;
  3664.       page( output );
  3665.     end;
  3666. end;
  3667.  
  3668.  
  3669. PROCEDURE line;
  3670.  
  3671. begin
  3672.   for i := 1 to 24 do write(p,'-');
  3673. end;
  3674.  
  3675.  
  3676. PROCEDURE word1( sym : vocab );
  3677.  
  3678. begin
  3679.   writeln(p);
  3680.   line;
  3681.   writeln(p);
  3682.   writeln(p, vocablist[sym] );
  3683.   line;
  3684.   writeln(p);
  3685.   writeln(p);
  3686. end;
  3687.  
  3688.  
  3689. PROCEDURE word2( sym1, sym2 : vocab );
  3690.  
  3691. begin
  3692.   writeln(p);
  3693.   line;
  3694.   writeln(p);
  3695.   writeln(p, vocablist[sym1], '   ', vocablist[sym2] );
  3696.   line;
  3697.   writeln(p);
  3698.   writeln(p);
  3699. end;
  3700.  
  3701.  
  3702. PROCEDURE aciaset( sym : vocab );
  3703.  
  3704. begin
  3705.   write(p,'According to the file ', setup_file, ' this command should ');
  3706.   if ( ( aciaimplem=A6850 ) and ( sym=baudsym ) ) or
  3707.        ( aciaimplem=unknown ) or ( aciaimplem>A6551 )
  3708.    then writeln(p,'not work.')
  3709.    else begin
  3710.           writeln(p,'work.');
  3711.           writeln(p,'Consult your serial card manual for valid settings.');
  3712.         end;
  3713. end;
  3714.  
  3715.  
  3716. (*********** Introduction procedure  ***********************************)
  3717.  
  3718.  
  3719. PROCEDURE introkermit;
  3720. begin
  3721.   writeln(p,'KERMIT is a family of programs that do reliable file transfer');
  3722.   writeln(p,'between computers over TTY lines. ( BYTE june & july 1984 )');
  3723.   writeln(p,'KERMIT can also be used to make the micro computer behave as a');
  3724.   writeln(p,'terminal for a mainframe.');
  3725.   writeln(p);
  3726.   writeln(p,'These are the commands for the Apple ][(e) UCSD KERMIT ',version);
  3727.   writeln(p);
  3728.   writeln(p);
  3729. end;
  3730.  
  3731.  
  3732. (********* These procedures explain the commands except SET ************)
  3733.  
  3734.  
  3735. PROCEDURE helpsend;
  3736. begin
  3737.   word1( sendsym );
  3738.   writeln(p,'To send a file to the remote system.');
  3739.   writeln(p,'Takes a filename as parameter.');
  3740. end;
  3741.  
  3742. PROCEDURE helpdir;
  3743. begin
  3744.   word2( dirsym, pdirsym );
  3745.   writeln(p,'Lists the directory of a disk ', scrpr );
  3746.   writeln(p, numpar, ' ( 4,5,9..12 )');
  3747. end;
  3748.  
  3749. PROCEDURE helphelp;
  3750. begin
  3751.   word2( helpsym, phelpsym );
  3752.   writeln(p,'To get an explanation of KERMIT commands ', scrpr );
  3753. end;
  3754.  
  3755. PROCEDURE helpshow;
  3756. begin
  3757.   word2( showsym, pshowsym );
  3758.   writeln(p,'Shows the values of the parameters that can be modified via');
  3759.   writeln(p,'the SET command ', scrpr );
  3760. end;
  3761.  
  3762. PROCEDURE helpconn;
  3763. begin
  3764.   word1( consym );
  3765.   writeln(p,'To make a virtual terminal connection to a remote system.');
  3766.   writeln(p,'To break the connection and escape back to the micro KERMIT');
  3767.   write(p,'command level type '); write_ctl( esc_char );
  3768.   writeln(p,' immediately followed by <C>.');
  3769.   writeln(p,'When the Apple screen starts scrolling host characters may');
  3770.   writeln(p,'be lost at > 1200 baud. To prevent this set the host''s');
  3771.   writeln(p,'linefeed fill to a count of about 5.');
  3772. end;
  3773.  
  3774. PROCEDURE helpexit;
  3775. begin
  3776.   word2( exitsym, quitsym );
  3777.   writeln(p,'To return back to the Apple UCSD p-system command level.');
  3778. end;
  3779.  
  3780. PROCEDURE helprec;
  3781. begin
  3782.   word1( recsym );
  3783.   writeln(p,'To accept a file or group of files from the remote system.');
  3784. end;
  3785.  
  3786.  
  3787. (***********  The following procedures explain the SET subcommands  ********)
  3788.  
  3789.  
  3790. PROCEDURE baudset;
  3791. begin
  3792.   word2( setsym, baudsym );
  3793.   writeln(p,'To set the serial baud rate.');
  3794.   writeln(p, numpar );
  3795.   aciaset( baudsym );
  3796. end;
  3797.  
  3798. PROCEDURE parset;
  3799. begin
  3800.   word2( setsym, paritysym );
  3801.   writeln(p,'This selects the parity for outgoing characters to match the');
  3802.   writeln(p,'requirements of the host.');
  3803.   writeln(p,'Takes as parameters : ', vocablist[nonesym], vocablist[oddsym]:4,
  3804.             vocablist[evensym]:5, vocablist[marksym]:5, vocablist[spacesym]:6 );
  3805.   writeln(p,'When the IBM flag is set, parity is set to ', vocablist[marksym],
  3806.             ' ( if possible ).');
  3807.   aciaset( paritysym );
  3808. end;
  3809.  
  3810. PROCEDURE wordlset;
  3811. begin
  3812.   word2( setsym, wordlensym );
  3813.   writeln(p,'Sets the number of databits for outgoing & incoming characters.');
  3814.   writeln(p, numpar );
  3815.   aciaset ( wordlensym );
  3816. end;
  3817.  
  3818. PROCEDURE stopbset;
  3819. begin
  3820.   word2( setsym, stopbsym );
  3821.   writeln(p,'Sets the number of stopbits for outgoing & incoming characters.');
  3822.   writeln(p, numpar );
  3823.   aciaset( stopbsym );
  3824. end;
  3825.  
  3826. PROCEDURE debugset;
  3827. begin
  3828.   word2( setsym, debugsym );
  3829.   writeln(p,'Shows packets sent & received during filetransfer when ON.');
  3830.   writeln(p, onoffp );
  3831.   writeln(p, ftval );
  3832. end;
  3833.  
  3834. PROCEDURE delset;
  3835. begin
  3836.   word2( setsym, delsym );
  3837.   writeln(p,'Changes the Apple <backspace> key to a <del> key for the host');
  3838.   writeln(p,'when set to ON.');
  3839.   writeln(p, onoffp );
  3840.   writeln(p, conval );
  3841. end;
  3842.  
  3843. PROCEDURE emulset;
  3844. begin
  3845.   word2( setsym, emulatesym );
  3846.   writeln(p,'Not implemented.');
  3847. end;
  3848.    
  3849. PROCEDURE eolnset;
  3850. begin
  3851.   word2( setsym, eolnsym );
  3852.   writeln(p,'Sets the "end-of-line" character sent after a KERMIT package.');
  3853.   writeln(p, charpar );
  3854.   writeln(p, ftval );
  3855. end;
  3856.  
  3857. PROCEDURE escset;
  3858. begin
  3859.   word2( setsym, escsym );
  3860.   writeln(p,'Sets the escape character preceding the <C>.');
  3861.   write(p,'The sequence '); write_ctl( esc_char );
  3862.   writeln(p,' <C> returns you to the KERMIT command level.');
  3863.   writeln(p, charpar );
  3864.   writeln(p, conval );
  3865. end;
  3866.  
  3867. PROCEDURE filewset;
  3868. begin
  3869.   word2( setsym, filewarnsym );
  3870.   writeln(p,'Changes names of received files to protect already existing');
  3871.   writeln(p,'files with similar names.');
  3872.   writeln(p, onoffp );
  3873.   writeln(p, ftval );
  3874. end;
  3875.  
  3876. PROCEDURE ibmset;
  3877. begin
  3878.   word2( setsym, ibmsym );
  3879.   writeln(p,'When communicating with an IBM VM/CMS mainframe this flag');
  3880.   writeln(p,'should be on.');
  3881.   writeln(p,'It also sets ', vocablist[paritysym], ' to ',
  3882.              vocablist[marksym], ' and activates ', vocablist[localsym],
  3883.              '.');
  3884.   writeln(p, onoffp );
  3885. end;
  3886.  
  3887. PROCEDURE localset;
  3888. begin
  3889.   word2( setsym, localsym );
  3890.   writeln(p,'This sets the duplex : it should be ON for th IBM VM/CMS');
  3891.   writeln(p,'and OFF for the CYBER, VAX, DEC-20.');
  3892.   writeln(p, onoffp );
  3893. end;
  3894.  
  3895. PROCEDURE maxtryset;
  3896. begin
  3897.   word2( setsym, maxtrysym );
  3898.   writeln(p,'Maximum number of times KERMIT tries to receive a correct');
  3899.   writeln(p,'package before breaking off the file transfer. At the start');
  3900.   writeln(p,'of file transfer this number is five times higher to allow');
  3901.   writeln(p,'the other side extra time to start file transfer.');
  3902.   writeln(p, numpar );
  3903. end;
  3904.  
  3905. PROCEDURE nofeedset;
  3906. begin
  3907.   word2( setsym, nofeedsym );
  3908.   writeln(p,'Replaces an incoming formfeed character with carriage return.');
  3909.   writeln(p, onoffp );
  3910. end;
  3911.  
  3912. PROCEDURE prefixset;
  3913. begin
  3914.   word2( setsym, prefixsym );
  3915.   writeln(p,'Sets the prefix name of the (disk)volume for incoming files.');
  3916.   writeln(p,'Takes a volume name as parameter.');
  3917.   writeln(p, ftval );
  3918. end;
  3919.  
  3920. PROCEDURE rejset;
  3921. begin
  3922.   word2( setsym, rejectsym );
  3923.   writeln(p,'When set control characters coming from the host are not');
  3924.   writeln(p,'echoed to the Apple screen or printer except :');
  3925.   writeln(p,'backspace, carr. return, formfeed, linefeed, bell.');
  3926.   writeln(p, onoffp );
  3927.   writeln(p, conval );
  3928. end;
  3929.  
  3930. PROCEDURE textfset;
  3931. begin
  3932.   word2( setsym, textfsym );
  3933.   writeln(p,' ON : incoming and outgoing files will be treated as UCSD');
  3934.   writeln(p,'      textfiles and the 8th bit of each character is masked.');
  3935.   writeln(p,'OFF : incoming and outgoing files will be treated as UCSD');
  3936.   writeln(p,'      datafiles and the 8th bit of each char. is not masked.');
  3937.   writeln(p,'UCSD data & code files can thus be transfered only if both');
  3938.   writeln(p,'sides are set to 8-bit word length, no parity and if the 8th');
  3939.   writeln(p,'bit is not altered during transmission.');
  3940.   writeln(p, ftval );
  3941. end;
  3942.  
  3943. PROCEDURE timoutset;
  3944. begin
  3945.   word2( setsym, timeoutsym );
  3946.   writeln(p,'Time-out period specified to host in approx. seconds (1..31).');
  3947.   writeln(p,'( Note : some host KERMITs do not take this parameter and');
  3948.   writeln(p,'         just keep waiting.)');
  3949.   writeln(p, numpar );
  3950.   writeln(p, ftval );
  3951. end;
  3952.  
  3953. PROCEDURE maxpackset;
  3954. begin
  3955.   word2( setsym, maxpsym );
  3956.   writeln(p,'Sets this side''s maximum KERMIT package length ( 20..94 ).');
  3957.   writeln(p,'Reduce package length on noisy lines.');
  3958.   writeln(p, numpar );
  3959.   writeln(p, ftval );
  3960. end;
  3961.  
  3962. PROCEDURE xoffset;
  3963. begin
  3964.   word2( setsym, xoffsym );
  3965.   writeln(p,'A Xoff/Xon protocol is used during ',vocablist[consym],
  3966.              ' when a screendump to the printer');
  3967.   writeln(p,'is requested.');
  3968.   writeln(p,'Set Xoff & Xon  according to the requirements of the host.');
  3969.   writeln(p,'( Note : at some hosts the Xon/Xoff char''s should first be');
  3970.   writeln(p,'         defined by a terminal definition command. )');
  3971.   writeln(p, charpar );
  3972.   writeln(p, dumpval );
  3973. end;
  3974.  
  3975. PROCEDURE xonset;
  3976. begin
  3977.   word2( setsym, xonsym );
  3978.   writeln(p,'See ', vocablist[setsym],vocablist[xoffsym] : 11, '.');
  3979.   writeln(p,'( Note : if IBM flag is on this character is also used in the');
  3980.   write(  p,'         file-transfer protocol. It should then be set to ');
  3981.   write_ctl( chr(17) ); writeln(p,' )');
  3982. end;
  3983.  
  3984. PROCEDURE xoffwset;
  3985. begin
  3986.   word2( setsym, xoffwaitsym );
  3987.   writeln(p,'If characters are lost during a screendump to the printer then');
  3988.   writeln(p,'increase this parameter.');
  3989.   writeln(p, numpar, ' (1..255 )');
  3990.   writeln(p, conval );
  3991.   writeln(p, dumpval );
  3992. end;
  3993.  
  3994.  
  3995.  
  3996. (*************** This procedure list all SET subcommands  ****************)
  3997.  
  3998.  
  3999. PROCEDURE allset;
  4000. begin
  4001.   page( output );
  4002.   word1( setsym );
  4003.   writeln(p,'To establish system dependent parameters.');
  4004.   writeln(p,'The ', vocablist[ setsym ], ' options are as follows :');
  4005.   writeln(p);
  4006.   baudset;
  4007.   wait;
  4008.   debugset;
  4009.   delset;
  4010.   wait;
  4011.   emulset;
  4012.   eolnset;
  4013.   escset;
  4014.   wait;
  4015.   filewset;
  4016.   ibmset;
  4017.   wait;
  4018.   localset;
  4019.   maxpackset;
  4020.   wait;
  4021.   maxtryset;
  4022.   nofeedset;
  4023.   wait;
  4024.   parset;
  4025.   prefixset;
  4026.   wait;
  4027.   rejset;
  4028.   stopbset;
  4029.   wait;
  4030.   textfset;
  4031.   wait;
  4032.   timoutset;
  4033.   wordlset;
  4034.   wait;
  4035.   xoffset;
  4036.   xonset;
  4037.   wait;
  4038.   xoffwset;
  4039. end;
  4040.  
  4041.  
  4042. (*********** This procedure explains the SET command ********************)
  4043.  
  4044.  
  4045. PROCEDURE helpset;
  4046.  
  4047. begin
  4048.   case adj of
  4049.     nullsym       : allset;
  4050.     baudsym       : baudset;
  4051.     debugsym      : debugset;
  4052.     delsym        : delset;
  4053.     emulatesym    : emulset;
  4054.     eolnsym       : eolnset;
  4055.     escsym        : escset;
  4056.     filewarnsym   : filewset;
  4057.     ibmsym        : ibmset;
  4058.     localsym      : localset;
  4059.     maxpsym       : maxpackset;
  4060.     maxtrysym     : maxtryset;
  4061.     nofeedsym     : nofeedset;
  4062.     paritysym     : parset;
  4063.     prefixsym     : prefixset;
  4064.     rejectsym     : rejset;
  4065.     stopbsym      : stopbset;
  4066.     textfsym      : textfset;
  4067.     timeoutsym    : timoutset;
  4068.     wordlensym    : wordlset;
  4069.     xoffsym       : xoffset;
  4070.     xonsym        : xonset;
  4071.     xoffwaitsym   : xoffwset;
  4072.   end;  { case }
  4073. end;   {  helpset }
  4074.  
  4075.  
  4076.  
  4077. (**************** This procedure shows all valid HELP commands ************)
  4078.  
  4079.  
  4080. PROCEDURE helpall;
  4081.  
  4082. begin
  4083.   page( output );
  4084.   introkermit;
  4085.   helpconn;
  4086.   wait;
  4087.   helpdir;
  4088.   helpexit;
  4089.   helphelp;
  4090.   wait;
  4091.   helprec;
  4092.   helpsend;
  4093.   helpshow;
  4094.   wait;
  4095.   helpset;
  4096. end;
  4097.  
  4098.  
  4099. (********************* Finally here starts procedure HELP  ****************)
  4100.  
  4101.  
  4102. begin   {  help  }
  4103.   close(p);
  4104.   if pr_out and print_enable then reset(p, pr_file )
  4105.                              else reset(p, cs_file );
  4106.   writeln(p);
  4107.   case noun of
  4108.     nullsym              :  helpall;
  4109.     setsym               :  helpset;
  4110.     showsym, pshowsym    :  helpshow;
  4111.     dirsym , pdirsym     :  helpdir;
  4112.     helpsym, phelpsym    :  helphelp;
  4113.     exitsym, quitsym     :  helpexit;
  4114.     recsym               :  helprec;
  4115.     sendsym              :  helpsend;
  4116.     consym               :  helpconn;
  4117.   end;  {  case  }
  4118.   writeln(p);
  4119.   pr_out := false;
  4120. end;   {  help  }
  4121.   
  4122.   
  4123.  
  4124. begin   {  unit  helper  }
  4125. end.
  4126.  
  4127. (*=== ASM.KERMIT.TEXT ===*)
  4128. ;-----------------------------------------------------------------------
  4129. ;-----------------------------------------------------------------------
  4130. ;
  4131. ;   This procedure is external to the unit kermpack.
  4132. ;
  4133. ;-----------------------------------------------------------------------
  4134. ;-----------------------------------------------------------------------
  4135. ;
  4136. ;FUNCTION rpack(           n  : INTEGER;
  4137. ;                VAR len, num : INTEGER;
  4138. ;                VAR    data  : packet_type;
  4139. ;                    time_out : INTEGER;
  4140. ;                         soh : CHAR        ) : CHAR;
  4141. ;------------------------------------------------------------------------
  4142. ; This function listens to the serial input port, detects a kermit
  4143. ; package, decodes it, returns the data part of the package, the
  4144. ; length of the data part and the number of the package. Its function
  4145. ; value is the packet-type.
  4146. ; n = the number of the last packet send. It is only used to initialize
  4147. ; num, otherwise num would be undefined in case of receive failure.
  4148. ; The function takes the value '@' in case a transmission error is
  4149. ; detected when decoding the packet or when no valid packet has been
  4150. ; received during the time_out period.
  4151. ; time_out can be specified in seconds : this value will be multiplied
  4152. ; within rpack by 8 to approximate real time. Because only the least
  4153. ; significant byte of time_out is passed to rpack, the valid range for
  4154. ; time_out will be 1..31 seconds.
  4155. ; This function will not work without the system.attach and attach.drivers
  4156. ; that implement a remin buffer and the remin unitstatus statement.
  4157. ;--------------------------------------------------------------------------
  4158. ;
  4159.            .FUNC RPACK, 6.
  4160. ;
  4161. BIOSAF     .EQU 0FF5C          ; base of bios jump table. Same in V1.1 & V1.2
  4162. BIOSRAM    .EQU 0C083          ; switch for extra bios ram.
  4163. INTPRAM    .EQU 0C08B          ; switch back to main ram.
  4164. RREAD      .EQU BIOSAF+24.     ; bios remote read routine adress.
  4165. RSTAT      .EQU BIOSAF+51.     ; bios remote status routine adress.
  4166. DUMMY      .EQU 0FFFF          ; dummy adress : will be filled in at runtime
  4167. TEMP1      .EQU 00             ; temp zero page adresses.
  4168. TEMP2      .EQU 02
  4169. ;
  4170. ; get parameters from stack:
  4171. ;
  4172.            PLA                 ; pop return adress.
  4173.            STA RETURN
  4174.            PLA
  4175.            STA RETURN+1
  4176.            ;-------------------
  4177.            PLA                 ; remove function bias.
  4178.            PLA
  4179.            PLA
  4180.            PLA
  4181.            ;-------------------
  4182.            PLA                 ; pop soh ( nearly always ^A )
  4183.            STA SOH
  4184.            PLA                 ; discard msb.
  4185.            ;-------------------
  4186.            PLA                 ; pop timeout.
  4187.            ASL A               ; timeout = timeout * 8
  4188.            ASL A               ; to approximate real time.
  4189.            ASL A
  4190.            STA TIMEOUT
  4191.            PLA                 ; discard msb.
  4192.            ;-------------------
  4193.            PLA                 ; move adress of recpkt to the the right place.
  4194.            STA RPADR+1
  4195.            PLA
  4196.            STA RPADR+2
  4197.            ;-------------------
  4198.            PLA                 ; move adress of num .
  4199.            STA TEMP1
  4200.            STA NUMADR+1
  4201.            PLA
  4202.            STA TEMP1+1
  4203.            STA NUMADR+2
  4204.            ;-------------------
  4205.            PLA                 ; move adress of len .
  4206.            STA TEMP2
  4207.            STA LENADR+1
  4208.            PLA
  4209.            STA TEMP2+1
  4210.            STA LENADR+2
  4211.            ;-------------------
  4212.            PLA                 ; pop n
  4213.            AND #3F             ; take mod 64
  4214.            LDY #00             ; init num to n in case of receive failure.
  4215.            STA @TEMP1,Y
  4216.            PLA                 ; discard msb of n.
  4217.            TYA
  4218.            INY
  4219.            STA @TEMP1,Y
  4220.            ;-------------------
  4221. ;
  4222. ; initialization code
  4223. ;
  4224.            LDA #00             ; init len to zero.
  4225.            TAY
  4226.            STA @TEMP2,Y
  4227.            INY
  4228.            STA @TEMP2,Y
  4229.            STA RESYNCNT        ; set resynchronization count to 0
  4230.            STA C1              ; set all timeout counters to 0
  4231.            STA C2
  4232.            LDA BIOSRAM         ; switch in bios ram
  4233. ;
  4234. ; start rpack
  4235. ;
  4236. WAITSOH    JSR GETCHAR2        ; wait for a soh (^A)
  4237.            BNE WAITSOH
  4238. RESYN      INC RESYNCNT        ; if more than 256 resync's : give up
  4239.            BEQ RECFAIL
  4240.            ;-------------------
  4241.            JSR GETCHAR1        ; get packet length ( len ).
  4242.            BEQ RESYN           ; if it was a soh then resync.
  4243.            STA CHKSUM          ; init checksum .
  4244.            SEC
  4245.            SBC #35.            ; len := len - 32 - 3.
  4246.            BMI RECFAIL         ; if len < 0 then something is wrong.
  4247.            STA LEN             ; save len temporarily.
  4248. LENADR     STA DUMMY           ; save len for pascal.
  4249.            ;-------------------
  4250.            JSR GETCHAR1        ; get packet number ( num ).
  4251.            BEQ RESYN           ; if it was a soh then resync.
  4252.            PHA                 ; save num 
  4253.            CLC
  4254.            ADC CHKSUM          ; increase chksum
  4255.            STA CHKSUM
  4256.            PLA                 ; get original num back.
  4257.            SEC
  4258.            SBC #32.            ; subtract 32.
  4259. NUMADR     STA DUMMY           ; save num for pascal.
  4260.            ;-------------------
  4261.            JSR GETCHAR1        ; get packet type ( function value of rpack )
  4262.            BEQ RESYN
  4263.            STA PTYPE
  4264.            CLC
  4265.            ADC CHKSUM          ; increase checksum
  4266.            STA CHKSUM
  4267.            ;-------------------
  4268.            LDY #00             ; get data char's ( recpkt )
  4269. FILLPACK   STY LENCNT          ; save y reg.
  4270.            CPY LEN             ; if no (more) data expected : skip this loop.
  4271.            BEQ GETCHKSUM
  4272.            JSR GETCHAR1        ; get data char.
  4273.            BEQ RESYN
  4274.            LDY LENCNT          ; restore y reg.
  4275. RPADR      STA DUMMY,Y         ; fill in recpkt for pascal
  4276.            CLC
  4277.            ADC CHKSUM          ; increase checksum
  4278.            STA CHKSUM
  4279.            INY                 ; increase length counter
  4280.            BNE FILLPACK        ; branch always to get next data char.
  4281.            ;-------------------
  4282. GETCHKSUM  JSR GETCHAR1        ; get packet checksum.
  4283.            BEQ RESYN
  4284.            SEC
  4285.            SBC #32.            ; subtract 32.
  4286.            STA PCHKSUM
  4287.            ;-------------------
  4288.            LDA CHKSUM          ; calculate final checksum.
  4289.            ROL A
  4290.            ROL A
  4291.            ROL A
  4292.            AND #03
  4293.            CLC
  4294.            ADC CHKSUM
  4295.            AND #3F
  4296.            ; equivalent to s = ( s + ( ( s and 192 ) div 64 ) ) and 63
  4297.            CMP PCHKSUM         ; compare to received checksum.
  4298.            BEQ EXIT            ; if ok then back to pascal.
  4299.            ;-------------------
  4300. RECFAIL    LDA #40             ; rpack = '@' if a receive failure was
  4301.            STA PTYPE           ; detected.
  4302.            ;-------------------
  4303. EXIT       LDA #00             ; push msb of function value.
  4304.            PHA
  4305.            LDA PTYPE           ; push lsb of function value.
  4306.            PHA
  4307.            ;-------------------
  4308.            LDA INTPRAM         ; switch back to main ram.
  4309.            ;-------------------
  4310.            LDA RETURN+1        ; push return adress
  4311.            PHA
  4312.            LDA RETURN
  4313.            PHA
  4314.            ;-------------------
  4315.            RTS                 ; back to pascal.
  4316. ;---------------------------------------------------------------------
  4317. ;
  4318. ;  subroutines  GETCHAR1 & GETCHAR2
  4319. ;
  4320. GETCHAR1   LDA #00             ; zero timeout counters
  4321.            STA C1
  4322.            STA C2
  4323.            ;-------------------
  4324. GETCHAR2   JSR RSTATUS         ; entry point without timeout reset.
  4325.            LDA BUFLEN          ; something in remin buffer?
  4326.            BNE GET             ; then get it.
  4327.            INC C1              ; if not then increase timeout counter
  4328.            BNE GETCHAR2        ; and keep testing remin buffer.
  4329.            INC C2
  4330.            LDA C2
  4331.            CMP TIMEOUT         ; if timeout period has expired then
  4332.            BNE GETCHAR2        ; indicate a receive failure.
  4333.            PLA                 ; remove this routine's return adress
  4334.            PLA                 ; from stack and go
  4335.            JMP RECFAIL         ; back to pascal.
  4336.            ;-------------------
  4337. GET        LDX #00             ; x = 0 : read request.
  4338.            JSR RREAD           ; read remin buffer. Char in accu.
  4339.            CMP SOH             ; main rpack will take action if a ^A is
  4340.            RTS                 ; detected.
  4341. ;---------------------------------------------------------------------
  4342. ;
  4343. ;  subroutine  RSTATUS
  4344. ;
  4345. RSTATUS    LDA #00             ; push controlword on stack
  4346.            PHA
  4347.            LDA #01
  4348.            PHA
  4349.            ;-------------------
  4350.            LDA BUFLENPTR+1     ; push adress of buflen on stack
  4351.            PHA
  4352.            LDA BUFLENPTR
  4353.            PHA
  4354.            ;-------------------
  4355.            LDX #04             ; x = 4 : status request.
  4356.            JSR RSTAT           ; number of char's in reminbuffer 
  4357.            RTS                 ; can now be found in buflen.
  4358. ;---------------------------------------------------------------------
  4359. ;
  4360. ;  variable space:
  4361. ;
  4362. RETURN     .WORD 00
  4363. SOH        .BYTE 00
  4364. TIMEOUT    .BYTE 00
  4365. RESYNCNT   .BYTE 00
  4366. C1         .BYTE 00
  4367. C2         .BYTE 00
  4368. LEN        .BYTE 00
  4369. LENCNT     .BYTE 00
  4370. PTYPE      .BYTE 00
  4371. CHKSUM     .BYTE 00
  4372. PCHKSUM    .BYTE 00
  4373. BUFLEN     .WORD 00
  4374. BUFLENPTR  .WORD BUFLEN
  4375. ;--------------------------------------------------------------------------
  4376. ;--------------------------------------------------------------------------
  4377. ;
  4378. ;  These procedures are external to unit kermutil.
  4379. ;
  4380. ;--------------------------------------------------------------------------
  4381. ;--------------------------------------------------------------------------
  4382. ;
  4383. ;  FUNCTION calc_checksum( var packet : packettype; len : integer ) : CHAR;
  4384. ;
  4385. ;  calculates one character checksum of a packet.
  4386. ;
  4387. ;  FUNCTION ctl( ch : char ) : CHAR;
  4388. ;
  4389. ;  transforms a control char to a printable char and vice versa.
  4390. ;
  4391. ;-----------------------------------------------------------------------
  4392. ;
  4393.           .FUNC CALCCHECKSUM, 2 ; two parameters
  4394. RETURN    .EQU 00
  4395. PACKETPTR .EQU 02
  4396. CHKSUM    .EQU 04
  4397.           ;---------------------
  4398.           PLA                   ; pop return address
  4399.           STA RETURN
  4400.           PLA
  4401.           STA RETURN+1
  4402.           ;---------------------
  4403.           PLA                   ; pop .func bias
  4404.           PLA
  4405.           PLA
  4406.           PLA
  4407.           ;---------------------
  4408.           PLA                   ; save len in y reg.
  4409.           TAY
  4410.           DEY                   ; len = len - 1
  4411.           PLA                   ; discard msb.
  4412.           ;---------------------
  4413.           PLA                   ; pop address of var packet
  4414.           STA PACKETPTR
  4415.           PLA
  4416.           STA PACKETPTR+1
  4417.           ;---------------------
  4418.           LDA #00               ; push msb of function result
  4419.           PHA
  4420.           ;---------------------
  4421. SUM       CLC                   ; sum characters except packet[0]
  4422.           ADC @PACKETPTR,Y
  4423.           DEY
  4424.           BNE SUM
  4425.           ;--------------------
  4426.           STA CHKSUM            ; save this sum temporarily
  4427.           ROL A
  4428.           ROL A
  4429.           ROL A
  4430.           AND #03
  4431.           CLC
  4432.           ADC CHKSUM
  4433.           AND #3F
  4434.           ;---------------------
  4435.           ; equivalent to  s = ( s + ( ( s and 192 ) div 64 ) ) and 63
  4436.           PHA                  ; push lsb of function result
  4437.           LDA RETURN+1         ; push return and back to pascal
  4438.           PHA
  4439.           LDA RETURN
  4440.           PHA
  4441.           RTS
  4442. ;----------------------------------------------------------------------
  4443. ;
  4444.           .FUNC CTL, 1         ; one parameter
  4445.           PLA                  ; save return address in x and y
  4446.           TAX
  4447.           PLA
  4448.           TAY
  4449.           ;--------------------
  4450.           PLA                  ; pop .func bias
  4451.           PLA
  4452.           PLA
  4453.           PLA
  4454.           ;--------------------
  4455.           PLA                  ; leave msb function result on stack (=0)
  4456.           EOR #40              ; toggle bit 7 of character
  4457.           PHA                  ; push lsb funtion result
  4458.           ;--------------------
  4459.           TYA                  ; push return address
  4460.           PHA
  4461.           TXA
  4462.           PHA
  4463.           RTS
  4464. ;-------------------------------------------------------------------------
  4465. ;-------------------------------------------------------------------------
  4466. ;
  4467. ;  These procedures are external to the unit kermacia.
  4468. ;
  4469. ;-------------------------------------------------------------------------
  4470. ;-------------------------------------------------------------------------
  4471. ;
  4472. ;            PROCEDURE   Send_6551_Break ( adr_comm_reg : INTEGER )
  4473. ;
  4474. ;  This procedure is external to the unit "kermacia" and is specific for a
  4475. ;  6551 acia in slot 2.
  4476. ;  It sends a "break" signal to the the remote host.
  4477. ;  The signal is switched off by pressing any key.
  4478. ;  The previous state of the command register is restored.
  4479. ;-------------------------------------------------------------------------
  4480. ;
  4481. ;
  4482.           .PROC SEND6551BREAK, 1  ; one parameter : the address of the 6551
  4483.                                   ; command register.
  4484. COMREG    .EQU 00                 ; zero page pointer.
  4485. ;---------------------------------
  4486.           PLA                 ; pop return adress.
  4487.           STA RETURN
  4488.           PLA
  4489.           STA RETURN+1
  4490.           ;-------------------
  4491.           PLA                 ; pop 6511 command reg. address.
  4492.           STA COMREG
  4493.           PLA
  4494.           STA COMREG+1
  4495.           ;-------------------
  4496.           LDY #00
  4497.           LDA @COMREG,Y
  4498.           PHA                 ; save content of command register.
  4499.           ORA #0C             ; turn on break bits 00001100
  4500.           STA @COMREG,Y       ; give break signal.
  4501.           ;-------------------
  4502. KEYBOARD  LDA 0C000           ; test apple keyboard
  4503.           BPL KEYBOARD
  4504.           STA 0C010           ; clear keyboard strobe
  4505.           ;-------------------
  4506.           PLA                 ; retrieve content of command register.
  4507.           STA @COMREG,Y       ; and restore old situation
  4508.           ;-------------------
  4509.           LDA RETURN+1        ; push return adress
  4510.           PHA
  4511.           LDA RETURN
  4512.           PHA
  4513.           RTS                 ; and back to pascal.
  4514.           ;-------------------
  4515. RETURN    .WORD 00
  4516. ;----------------------------------------------------------------------
  4517. ;
  4518. ;            PROCEDURE   Send_6850_Break ( adr_comm_reg : INTEGER )
  4519. ;
  4520. ;  This procedure is external to the unit "kermacia" and is specific for a
  4521. ;  6850 acia in slot 2.
  4522. ;  It sends a "break" signal to the the remote host.
  4523. ;  The signal is switched off by pressing any key.
  4524. ;  The previous state of the command register is restored by the procedure
  4525. ;  set_acia_parms in unit kermacia.
  4526. ;-------------------------------------------------------------------------
  4527. ;
  4528. ;
  4529.           .PROC SEND6850BREAK, 1  ; one parameter : the address of the 6850
  4530.                                   ; command register.
  4531. COMREG    .EQU 00                 ; zero page pointer.
  4532. ;---------------------------------
  4533.           PLA                 ; pop return adress.
  4534.           STA RETURN
  4535.           PLA
  4536.           STA RETURN+1
  4537.           ;-------------------
  4538.           PLA                 ; pop 6511 command reg. address.
  4539.           STA COMREG
  4540.           PLA
  4541.           STA COMREG+1
  4542.           ;-------------------
  4543.           LDY #00
  4544.           LDA #70             ; set break signal on .
  4545.           STA @COMREG,Y
  4546.           ;-------------------
  4547. KEYBOARD  LDA 0C000           ; test apple keyboard
  4548.           BPL KEYBOARD
  4549.           STA 0C010           ; clear keyboard strobe
  4550.           ;-------------------
  4551.           LDA #13             ; give an acia master reset.
  4552.           STA @COMREG,Y       ; 
  4553.           ;-------------------
  4554.           LDA RETURN+1        ; push return adress
  4555.           PHA
  4556.           LDA RETURN
  4557.           PHA
  4558.           RTS                 ; and back to pascal.
  4559.           ;-------------------
  4560. RETURN    .WORD 0
  4561. ;-----------------------------------------------------------------------
  4562.           .END
  4563. (*=== KERMTERM.TEXT ===*)
  4564. ;>>>>>>>>>>>>>>>>>>>>>>> KERMTERM.TEXT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  4565.  
  4566.  
  4567. ;----------------------------------------------------------------------
  4568. ;----------------------------------------------------------------------
  4569. ;
  4570. ;  This procedure is external to the main kermit program.
  4571. ;
  4572. ;----------------------------------------------------------------------
  4573. ;----------------------------------------------------------------------
  4574. ; PROCEDURE Kerm_Term( BS_to_DEL, Esc_Char, Xon_Char, Xoff_Char : CHAR;
  4575. ;                      Xoff_Wait : INTEGER;
  4576. ;                      No_Ffeed, Print, Half_Duplex, Reject_Cntrl_Char,
  4577. ;                      Emulate : BOOLEAN );
  4578. ;----------------------------------------------------------------------
  4579. ;
  4580. ; This procedure works only in cooperation with my serial card driver
  4581. ; BIOS routine, that implements the UCSD  UNITSTATUS procedure and buffers 
  4582. ; serial input for various serial cards. ( see REMDRIVER.TEXT )
  4583. ; It is written in 6502 code in order to be able to work at high baudrates.
  4584. ; The baudrate limiting factor on the Apple is the screen scrolling routine.
  4585. ; If one can set the linefeed fill count in the remote host terminal
  4586. ; definition to an appropiate value, then this procedure works at 4800 baud.
  4587. ; With the right Xon and Xoff characters ( most often ^Q and ^S ) and Xoff-
  4588. ; wait count this procedure will echo on request also to a printer, without
  4589. ; losing characters. Increase Xoff_wait if characters seem to be lost when
  4590. ; printing.
  4591. ; If your keyboard doesn`t have a DEL key and your host requires one for
  4592. ; delete & backspace, then set BS_to_DEL to CHR(127). During the connection
  4593. ; your BS key (Asci 8) will be translated to DEL (Asci 127).
  4594. ; If you do not want incoming control characters other than 'bell', 'bs',
  4595. ; 'lf', 'ff', 'cr' echoed to to your screen : set 'reject_cntrl_char' to
  4596. ; true.
  4597. ;----------------------------------------------------------------------
  4598. ;
  4599. ; N.B.  EMULATE is not implemented.
  4600. ;
  4601. ;----------------------------------------------------------------------
  4602. ;
  4603.           .PROC KERMTERM,10.  ; 10 parameters, see above.
  4604. ;
  4605. BIOSAF    .EQU 0FF5C        ;base of bios jump table. Same in V1.1 &1.2
  4606. CREAD     .EQU BIOSAF+0     ;bios console read routine adres
  4607. CWRITE    .EQU BIOSAF+3.    ;bios console write routine adres
  4608. PWRITE    .EQU BIOSAF+9.    ;bios printer write routine adres
  4609. RREAD     .EQU BIOSAF+24.   ;bios remote read routine adres
  4610. RWRITE    .EQU BIOSAF+27.   ;bios remote write routine adres
  4611. CSTAT     .EQU BIOSAF+42.   ;bios keyboard status routine adres
  4612. RSTAT     .EQU BIOSAF+51.   ;bios remote status routine adres
  4613. ;
  4614. ;  The BIOS After Fold jump vector will be patched by SYSTEM.ATTACH .
  4615. ;  From the above routines only RREAD & RSTAT are actually changed.
  4616. ;
  4617. BIOSRAM   .EQU 0C083        ;switch adress for extra 4k language card part.
  4618.                             ;contains UCSD BIOS routines.
  4619. INTPRAM   .EQU 0C08B        ;switch adress to get back to normal language
  4620.                             ;card part. contains UCSD interpreter.
  4621. RPTR      .EQU 0BF18        ;read pointer for circular keyboard buffer.
  4622. WPTR      .EQU 0BF19        ;write   "     "     "        "      "
  4623. BS        .EQU 08           ;backspace character.
  4624. LINEFD    .EQU 0A           ;linefeed     "
  4625. FF        .EQU 0C           ;formfeed     "
  4626. CR        .EQU 0D           ;return       "
  4627. BELL      .EQU 07           ;bell         "
  4628. TRUE      .EQU 80           ;used as boolean.
  4629. ;---------------------------
  4630. ; GET PARAMETERS FROM STACK
  4631. ;
  4632.           PLA               ; pop return adress.
  4633.           STA RETURN
  4634.           PLA
  4635.           STA RETURN+1
  4636.           ;-----------------
  4637.           PLA               ; pop emulate boolean.
  4638.           BEQ $05
  4639.           LDA #TRUE
  4640. $05       STA EMULATE
  4641.           PLA
  4642.           ;----------------
  4643.           PLA               ; pop Reject_Cntrl_Char Boolean.
  4644.           BEQ $01
  4645.           LDA #TRUE
  4646. $01       STA REJECT
  4647.           PLA
  4648.           ;-----------------
  4649.           PLA               ; pop Half_Duplex Boolean.
  4650.           BEQ $02
  4651.           LDA #TRUE
  4652. $02       STA HALFDUP
  4653.           PLA
  4654.           ;-----------------
  4655.           PLA               ; pop Printer Boolean.
  4656.           BEQ $03
  4657.           LDA #TRUE
  4658. $03       STA PRINTER
  4659.           PLA
  4660.           ;-----------------
  4661.           PLA               ; pop No_Ffeed Boolean.
  4662.           BEQ $04
  4663.           LDA #TRUE
  4664. $04       STA NOFEED
  4665.           PLA
  4666.           ;-----------------
  4667.           PLA               ; pop Xoff_Wait Integer (1..255).
  4668.           STA XOFFWAIT
  4669.           PLA
  4670.           ;-----------------
  4671.           PLA               ; pop Xoff_Char Char.
  4672.           STA XOFFCHAR
  4673.           PLA
  4674.           ;-----------------
  4675.           PLA               ; pop Xon_Char Char.
  4676.           STA XONCHAR
  4677.           PLA
  4678.           ;-----------------
  4679.           PLA               ; pop ExitChar Char.
  4680.           STA EXITCHAR
  4681.           PLA
  4682.           ;-----------------
  4683.           PLA               ; pop BS_to_DEL Char.
  4684.           STA BSTODEL
  4685.           PLA
  4686. ;---------------------------
  4687.           LDA BIOSRAM       ; switch in BIOS RAM
  4688. ;---------------------------
  4689. START     JSR RSTATUS       ; returns in BUFLEN # char's in remin-buffer.
  4690.           LDA BUFLEN
  4691.           BEQ READKEY       ; read keyboard if buffer empty.
  4692.           ;-----------------
  4693.           BIT PRINTER       ; is printer on?
  4694.           BPL EMPTYRBUF     ; no : start reading remin buffer.
  4695.           ;-----------------
  4696. XOFFSEND  LDA XOFFCHAR      ; printer is on:
  4697.           JSR RWRITE        ; send xoff char to host and
  4698.           LDA XOFFWAIT      ; keep checking remin for a certain time,
  4699.           STA COUNT         ; because host may send some more char's
  4700. WAIT      JSR RSTATUS       ; before it really gets the xoff.
  4701.           DEC COUNT
  4702.           BNE WAIT
  4703.           ;-----------------
  4704. EMPTYRBUF LDX #00           ; X=0 : read request.
  4705.           JSR RREAD         ; read a char from remin buffer.
  4706.           ;-----------------
  4707.           BIT REJECT        ; reject control chars?
  4708.           BPL ECHO          ; no: echo to console.
  4709.           JSR CHECKCTRL     ; yes: check for allowed control char's.
  4710.           ;-----------------
  4711. ECHO      PHA               ; save char.
  4712.           JSR CWRITE        ; echo char to console.
  4713.           PLA               ; restore char in accu.
  4714.           ;-----------------
  4715.           BIT PRINTER       ; is printer on?
  4716.           BPL NOPRINT       ; if not, don't print char.
  4717.           ;-----------------
  4718.           CMP #FF           ; printer is on. is char a formfeed?
  4719.           BNE NOFF
  4720.           JSR REPLFF        ; yes: replace it if requested.
  4721. NOFF      LDX #01           ; write request.
  4722.           JSR PWRITE        ; print char.
  4723.           ;-----------------
  4724. NOPRINT   DEC BUFLEN        ; keep on reading remin char's until
  4725.           BNE EMPTYRBUF     ; reminbuffer is empty.
  4726.           ;-----------------
  4727.           BIT PRINTER       ; is printer on?
  4728.           BPL READKEY       ; no  : check keyboard.
  4729.           LDA XONCHAR       ; yes : send xon char to host.
  4730.           JSR RWRITE
  4731.           ;-----------------
  4732. READKEY   LDA RPTR          ; if keyboardbuffer readpointer is
  4733.           CMP WPTR          ; equal to writepointer then keyboardbuffer is
  4734.           BEQ START         ; empty. loop back to start.
  4735.           ;-----------------
  4736.           JSR CREAD         ; get a char from keyboardbuffer.
  4737.           CMP EXITCHAR      ; is it the escape char?
  4738.           BEQ EXIT          ; then exit this procedure.
  4739.           ;-----------------
  4740.           BIT HALFDUP       ; half_duplex mode ?
  4741.           BPL FULLDUP       ; if not , don't echo to screen.
  4742.           PHA               ; if half_duplex, save char
  4743.           JSR CWRITE        ; echo char to screen.
  4744.           PLA               ; restore char to accu
  4745.           ;-----------------
  4746. FULLDUP   CMP #BS           ; is char a backspace?
  4747.           BNE NOBS          ; if not, don't change it.
  4748.           LDA BSTODEL       ; if a backspace, translate it to BSTODEL value.
  4749. NOBS      JSR RWRITE        ; send keyboard char to remote host
  4750.           JMP START         ; start listening to remin again.
  4751.           ;-----------------
  4752. EXIT      LDA INTPRAM       ; switch BIOS RAM off and interpreter RAM on.
  4753.           ;-----------------
  4754.           LDA RETURN+1      ; push return adress and back to pascal.
  4755.           PHA
  4756.           LDA RETURN
  4757.           PHA
  4758.           ;-----------------
  4759.           RTS
  4760. ;---------------------------------------------------------------------------
  4761. ;---------------------------------------------------------------------------
  4762. ;
  4763. ; SUBROUTINES
  4764. ;
  4765. ;---------------------------
  4766. ;RSTATUS : prepare stack and call reminstatus routine in attached driver.
  4767. ;
  4768. RSTATUS   LDA #00           ; push controlword (=1 : statuscall )
  4769.           PHA
  4770.           LDA #01
  4771.           PHA
  4772.           ;-----------------
  4773.           LDA BUFLENPTR+1   ; push adres of BUFLEN
  4774.           PHA
  4775.           LDA BUFLENPTR
  4776.           PHA
  4777.           ;-----------------
  4778.           LDX #04           ; X=4 : statusrequest.
  4779.           JSR RSTAT
  4780.           RTS
  4781. ;---------------------------
  4782. ; CHECKCTRL
  4783. ;
  4784. CHECKCTRL CMP #20           ; is it a control char?
  4785.           BCS ECHO1         ; no: echo to console.
  4786.           CMP #CR           ; pass to console in any case CR,LF,BS,FF,BELL.
  4787.           BEQ ECHO1
  4788.           CMP #LINEFD
  4789.           BEQ ECHO1
  4790.           CMP #BS
  4791.           BEQ ECHO1
  4792.           CMP #FF
  4793.           BEQ ECHO1
  4794.           CMP #BELL
  4795.           BEQ ECHO1
  4796.           PLA
  4797.           PLA
  4798.           JMP NOPRINT       ; do not echo other control characters.  
  4799. ECHO1     RTS
  4800. ;---------------------------
  4801. ;REPLFF : replaces formfeed with 3 lf's and 1 cr,if requested.
  4802. ;
  4803. REPLFF    BIT NOFEED        ; ff to be elimininated?
  4804.           BPL NOCHANGE      ; if not, return.
  4805.           LDA #03
  4806.           STA COUNT         ; set count to 3
  4807. $04       LDA #LINEFD       ; send 3 linefeeds to printer
  4808.           LDX #01
  4809.           JSR PWRITE
  4810.           DEC COUNT
  4811.           BNE $04
  4812.           LDA #CR           ; replace formfeed with cr.
  4813. NOCHANGE  RTS               ; and return.
  4814. ;---------------------------
  4815. ;--------------------------------------------------------------------------
  4816. ;
  4817. ; VARIABLES
  4818. ;
  4819. ;--------------------------------------------------------------------------
  4820. RETURN    .WORD 00
  4821. BUFLEN    .WORD 00
  4822. BUFLENPTR .WORD BUFLEN
  4823. COUNT     .BYTE 00
  4824. HALFDUP   .BYTE 00
  4825. PRINTER   .BYTE 00
  4826. NOFEED    .BYTE 00
  4827. XOFFWAIT  .BYTE 00
  4828. XOFFCHAR  .BYTE 00
  4829. XONCHAR   .BYTE 00
  4830. EXITCHAR  .BYTE 00
  4831. BSTODEL   .BYTE 00
  4832. REJECT    .BYTE 00
  4833. EMULATE   .BYTE 00
  4834. ;----------------------------------------------------------------------
  4835.           .END
  4836. (*=== REMDRIVER.TEXT ===*)
  4837. ;>>>>>>>>>>>>>>>>>>>>>>> REMDRIVER.TEXT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  4838. ;
  4839. ; For an introduction see the file REMDR.DOC.TEXT
  4840. ;
  4841. ;----------------------------------------------------------------------
  4842. ;
  4843. ; Serial card driver for Kermit-UCSD  RUG/PT V1.0
  4844. ;
  4845. ;----------------------------------------------------------------------
  4846. ;
  4847. ; LABEL DEFINITIONS
  4848. ;
  4849. SLOT      .EQU 20          ; various slot 2 labels
  4850. SLT2MSB   .EQU 0C2
  4851. SLOT2ADR  .EQU 0C200
  4852. ;
  4853.                            ; addresses of the offset bytes to calculate :
  4854. FSTATUS   .EQU SLOT2ADR+10 ; entry point for a serial firmware card status
  4855. FREAD     .EQU SLOT2ADR+0E ;   "     "    "  "   "       "      "   read
  4856. ;
  4857. DUMMY     .EQU 0FFFF       ; dummy address. will be filled in at cold boot.
  4858. ;
  4859. AP2COMM   .EQU 0C08E+SLOT  ; IBS AP2 serial card (6551 acia) command register.
  4860. AP2STREG  .EQU 0C08D+SLOT  ;  "   "    "     "     "    "    status     "
  4861. AP2IOREG  .EQU 0C08C+SLOT  ;  "   "    "     "     "    "    I/O        "
  4862. ;
  4863. COMSTREG  .EQU 0C08E+SLOT  ; Apple Com Card (6850 acia) status register.
  4864. COMIOREG  .EQU 0C08F+SLOT  ;   "    "    "    "    "    I/O      "
  4865. ;
  4866. HAYSTREG  .EQU 0C086+SLOT  ; Hayes Micromodem (6850 acia) status register.
  4867. HAYIOREG  .EQU 0C087+SLOT  ;   "       "        "    "    I/O      "
  4868.                            ; (Com Card registers may also work.)
  4869. SPEAKER   .EQU 0C030
  4870. SPCHAR    .EQU 0BF1C       ; system location for special keyboard character
  4871.                            ; checking.
  4872. SLT2TYP   .EQU 0BF27+2     ; system location with serial card type
  4873.                            ; 0 = no card.
  4874.                            ; 1 = not recognized by system.
  4875.                            ; 3 = Apple Com card
  4876.                            ;     California 7710 ASI1 card
  4877.                            ;     Hayes Micromodem card?
  4878.                            ; 4 = serial card ( IBS AP2 )
  4879.                            ; 6 = Firmware card ( Super Serial Card )
  4880. ;
  4881. NUMSERID  .EQU 02-1        ; number(-1) of serial cards this driver checks.
  4882. ;
  4883. ACJVAFOLD .EQU 0E2         ; pointer to attached copy of BIOS jump vector.
  4884. JVAFOLD   .EQU 0EE         ; pointer to BIOS jump vector.
  4885. ;
  4886. CONCK     .EQU DUMMY       ; address of BIOS keyboard check routine.
  4887. RINIT     .EQU DUMMY       ; address of BIOS Remote Init routine.
  4888. INPORTSTAT.EQU DUMMY       ; address of this driver's Remote status routine.
  4889. ;
  4890. STATREC   .EQU 00          ; temp. zero page pointer to status record.
  4891. ;
  4892. ;----------------------------------------------------------------------
  4893. ;
  4894.           .PROC REMDRIVER
  4895. ;
  4896. ;----------------------------------------------------------------------
  4897.           JMP CONCKHDL     ; The first 3 instructions of CONCK will
  4898.                            ; be patched by SYSTEM.ATTACH to point here.
  4899. ;----------------------------------------------------------------------
  4900. ;
  4901. ; Calls to REMREAD, REMSTATUS and REMINIT will be handled here :
  4902. ;
  4903.           TXA              ; X=0 : Remote Read request.
  4904.           BEQ REMREAD
  4905.           CMP #004         ; X=4 : Remote Status request.
  4906.           BEQ REMSTATUS
  4907.           CMP #002
  4908.           BNE ERROR        ; X=2 : Remote Init request.
  4909.           ;----------------
  4910.           ;
  4911.           ; Remote Init routine :
  4912.           ;
  4913.           LDX REMRPTR      ; Empty remote input buffer.
  4914.           STX REMWPTR      ; ( read-pointer = write-pointer )
  4915.           LDX #000         ; zero buffer counter.
  4916.           STX BUFCOUNT
  4917. PATCH3    JMP ONCERINIT    ; if called for the first time ( cold boot ) then
  4918.                            ; do the cold boot init routine. This routine
  4919.                            ; patches the JMP instruction to NOP,NOP,NOP so
  4920.                            ; later init calls (warm boot) will only empty the
  4921.                            ; remin buffer.
  4922.           RTS
  4923.           ;----------------
  4924. ERROR     LDX #003         ; for any other request return error code.
  4925.           RTS
  4926. ;----------------------------------------------------------------------
  4927. ;
  4928. ; Remote read routine ( reads only the remin buffer ).
  4929. ;
  4930. REMREAD   JSR CONCKHDL     ; check keyboard and remote input port.
  4931.           LDX REMRPTR      ; if remin buffer is empty : keep checking remote
  4932.           CPX REMWPTR      ; input port until something arrives.
  4933.           BEQ REMREAD
  4934.           INX              ; read char from remin buffer, bump read-pointer
  4935.           STX REMRPTR      ; decrease buffer count and put char in accu.
  4936.           DEC BUFCOUNT
  4937.           LDA REMBUF,X
  4938. READY     LDX #000         ; no error.
  4939.           RTS
  4940. ;----------------------------------------------------------------------
  4941. ;
  4942. ; Remote status routine ( implements UNITSTATUS. see KERM.DOC2.TEXT )
  4943. ;
  4944. REMSTATUS JSR CONCKHDL     ; check keyboard and remote input port.
  4945.           PLA              ; save return address.
  4946.           STA RETURN
  4947.           PLA
  4948.           STA RETURN+1
  4949.           ;------------
  4950.           PLA              ; save address of statusrecord on zero page.
  4951.           STA STATREC
  4952.           PLA
  4953.           STA STATREC+1
  4954.           ;------------
  4955.           PLA              ; save controlword.
  4956.           STA CONTROLW
  4957.           PLA
  4958.           STA CONTROLW+1
  4959.           ;------------
  4960.           LDA RETURN+1     ; push return address back on stack.
  4961.           PHA
  4962.           LDA RETURN
  4963.           PHA
  4964.           ;----------------------------------
  4965. REMINSTAT LDX #000         ; zero registers.
  4966.           LDY #000
  4967.           ;----------------
  4968.           ;
  4969.           ; Decipher Controlword.
  4970.           ;
  4971.           LDA CONTROLW     ; if bit 1 = 0 then the purpose is statusrequest.
  4972.           AND #002         ; if bit 1 = 1 then the purpose is controlrequest.
  4973.                            ; bit 0 (direction) is not checked.
  4974.           BNE REMCNTROL
  4975.           LDA CONTROLW+1   ; if bit 13 = 0 then a "normal" request.
  4976.           AND #020
  4977.           BNE PEEK         ; if bit 13 = 1 then a "special" request.
  4978.           ;----------------
  4979.           ;
  4980.           ; Normal Status Request: load in statusrecord ( 2 bytes ) the number
  4981.           ; of characters currently in the remin buffer.
  4982.           ;
  4983.           LDA BUFCOUNT
  4984. LOAD      STA @STATREC,Y
  4985.           LDA #00
  4986.           INY
  4987.           STA @STATREC,Y
  4988.           RTS
  4989.           ;---------------
  4990.           ;
  4991.           ; Special Status Request: statusrecord first to bytes contain an
  4992.           ; address. Return in statusrecord last 2 bytes the value of the
  4993.           ; requested location.
  4994.           ;
  4995. PEEK      LDA @STATREC,Y
  4996.           STA ADR1+1
  4997.           INY
  4998.           LDA @STATREC,Y
  4999.           STA ADR1+2
  5000. ADR1      LDA DUMMY        ; DUMMY will be changed to the requested address.
  5001.           INY
  5002.           BNE LOAD         ; value returned is a Pascal Integer!
  5003.           ;----------------
  5004.           ;
  5005.           ; Control Requests :
  5006.           ;
  5007. REMCNTROL LDA CONTROLW+1   ; if bit 13 = 0 then a normal controlrequest.
  5008.           AND #020
  5009.           BNE POKE
  5010.           ;----------------
  5011.           ; Normal Control Request
  5012.           ;
  5013.           ; first byte of statusrecord contains 
  5014.           ; 0..3 : store this byte in SPCHAR.
  5015.           ; SPCHAR=0 : CONCK checks class 1 and class 2 special chars.
  5016.           ; SPCHAR=1 :   "     "    only        class 2    "     "
  5017.           ; SPCHAR=2 :   "     "    only        class 1    "     "
  5018.           ; SPCHAR=3 :   "     "           no              "     "
  5019.           ; ( see KERM.DOC2.TEXT )
  5020.           ;
  5021.           ; first byte of statusrecord contains
  5022.           ; 4  :  7 bit characters in remin buffer.
  5023.           ; 5  :  8 bit      "     "    "    "    
  5024.           ;
  5025.           LDA @STATREC,Y
  5026.           CMP #004
  5027.           BCS BIT78
  5028.           STA SPCHAR
  5029.           RTS
  5030.           ;-----------------
  5031.           ;
  5032.           ; Special Control Request : statusrecord first 2 bytes contain a
  5033.           ; address. Statusrecord third byte contains the value the location
  5034.           ; should contain.
  5035.           ;
  5036. POKE      LDA @STATREC,Y
  5037.           STA ADR2+1
  5038.           INY
  5039.           LDA @STATREC,Y
  5040.           STA ADR2+2
  5041.           INY
  5042.           LDA @STATREC,Y
  5043. ADR2      STA DUMMY        ; DUMMY will be filled in at run time.
  5044.           RTS
  5045.           ;----------------
  5046. BIT78     CMP #005         ; set the flag LOCALPAR for the remin input routine.
  5047.           BEQ EIGHTBIT     ; default startup setting is seven bit remin chars.
  5048.           LDA #000
  5049.           BEQ SETLOCPAR
  5050. EIGHTBIT  LDA #080
  5051. SETLOCPAR STA LOCALPAR
  5052.           RTS
  5053. ;----------------------------------------------------------------------
  5054. ;
  5055. ; Calls to the system CONCK routine come here. A call to this
  5056. ; driver's remin check routine is inserted so that every time the system
  5057. ; does any I/O call both the keyboard and the remote input port will be checked.
  5058. ;
  5059. CONCKHDL  PHP           ; repeat first 6 instructions of CONCK.
  5060.           PHA
  5061.           TXA
  5062.           PHA
  5063.           TYA
  5064.           PHA
  5065.           JSR REMINCK   ; check the remote input port.
  5066. PATCH2    JMP CONCK     ; enter CONCK at start+6 and return from there to
  5067.                         ; system. The 2 bytes after the JMP will be filled
  5068.                         ; in at first initialization of this driver.
  5069. ;----------------------------------------------------------------------
  5070. ;
  5071. ; REMINCK  : checks remote input port. If it finds a char, it will put it
  5072. ;            in the remin buffer.
  5073. ;
  5074. REMINCK   JSR INPORTST  ; checks remote inputport. Carry is set when a char
  5075.                         ; is waiting. Returns with char in accu.
  5076.                         ; The address INPORTST will be filled in at cold boot
  5077.                         ; initialization time to point at the correct status
  5078.                         ; routine.
  5079.           BCC EMPTY
  5080.           BIT LOCALPAR  ; depending on LOCALPAR : strip bit 8 of incomimg char.
  5081.           BMI NOCHANGE
  5082.           AND #07F
  5083. NOCHANGE  LDX REMWPTR   ; bump writepointer.
  5084.           INX
  5085.           CPX REMRPTR   ; if writepointer = readpointer then buffer is full!
  5086.           BNE BUFOK
  5087.           ;----------
  5088.           PHA           ; in case of buffer overflow :
  5089.           TXA           ; give a high pitched bell sound.
  5090.           PHA
  5091. BELL      LDY #060
  5092. BELL1     LDX #020
  5093. BELL2     DEX
  5094.           BNE BELL2
  5095.           LDA SPEAKER
  5096.           DEY
  5097.           BNE BELL1
  5098.           LDA #0FF      ; set buffer count to -1.
  5099.           STA BUFCOUNT  ; buffer will thus be emptied.
  5100.           PLA
  5101.           TAX
  5102.           PLA
  5103.           ;------------
  5104. BUFOK     STX REMWPTR   ; save new writepointer.
  5105.           INC BUFCOUNT  ; bump buffer count and
  5106.           STA REMBUF,X  ; store received char in buffer.
  5107. EMPTY     RTS
  5108. ;-----------------------------------------------------------------------
  5109. ;
  5110. ;   Remote status routines for different serial cards.
  5111. ;   Only one of these is active after cold boot initialization.
  5112. ;
  5113. ;   The status routine returns with the received character (if any) in accu
  5114. ;   and with the carry set if a character was received.
  5115. ;
  5116. ;-----------------------------------------------------------------------
  5117. ;
  5118. ;   Status routine for an IBS AP2 serial card with a 6551 acia.
  5119. ;
  5120. AP2STAT   LDA AP2COMM
  5121.           ORA #008
  5122.           STA AP2COMM
  5123.           LDA AP2STREG
  5124.           CLC
  5125.           AND #028
  5126.           EOR #008
  5127.           BNE NOTHING1
  5128.           SEC
  5129.           LDA AP2IOREG
  5130. NOTHING1  PHA
  5131.           LDA AP2COMM
  5132.           AND #0F3
  5133.           STA AP2COMM
  5134.           PLA
  5135.           RTS
  5136. ;----------------------------------------------------------------------
  5137. ;
  5138. ;   Status routine for Hayes Micromodem Card with a 6850 acia.
  5139. ;   ( Identical to Apple Com Card. Can probably be replaced by Com Card routine
  5140. ;     if Hayes card is also recognized by the Pascal system as an Apple Com
  5141. ;     card. )
  5142. ;
  5143. HAYESTAT  LDA HAYSTREG
  5144.           LSR A
  5145.           BCC NOTHING2
  5146.           LDA HAYIOREG
  5147. NOTHING2  RTS
  5148. ;-----------------------------------------------------------------------
  5149. ;
  5150. ;   Status routine for an Apple Communications Card or California 7710
  5151. ;   ASI1 card , both with a 6850 acia.
  5152. ;
  5153. COMSTAT   LDA COMSTREG
  5154.           LSR A
  5155.           BCC NOTHING3
  5156.           LDA COMIOREG
  5157. NOTHING3  RTS
  5158. ;-----------------------------------------------------------------------
  5159. ;
  5160. ;   Status routine for a "firmware" card like the Apple Super Serial Card.
  5161. ;   Firmware cards have there own status and read routines in ROM.
  5162. ;   The final addresses of the status and read routines will be calculated
  5163. ;   at cold boot initialization and filled in directly here at PATCH4 and
  5164. ;   PATCH5.
  5165. ;
  5166. FIRMSTAT  LDX #SLT2MSB   ; do the required initialization.
  5167.           LDY #SLOT
  5168.           STY 06F8
  5169.           STA 0CFFF
  5170.           LDA SLOT2ADR
  5171.           LDA #001
  5172. PATCH4    JSR FSTATUS
  5173.           BCC NOTHING
  5174.           LDX #SLT2MSB
  5175. PATCH5    JSR FREAD      ; returns with char in accu.
  5176.           SEC
  5177. NOTHING   RTS
  5178. ;------------------------
  5179. ;
  5180. ; If you have extended FINDSER to recognize more serial cards then insert
  5181. ; here the code for the new serial card's status routine.
  5182. ;
  5183. ;----------------------------------------------------------------------------
  5184. ;
  5185. ;  Local variables
  5186. ;
  5187. RETURN    .WORD 00
  5188. LOCALPAR  .BYTE 00
  5189. REMRPTR   .BYTE 00
  5190. REMWPTR   .BYTE 00
  5191. CONTROLW  .WORD 00
  5192. BUFCOUNT  .BYTE 00
  5193. ;
  5194. ;
  5195. ;----------------------------------------------------------------------------
  5196. ;----------------------------------------------------------------------------
  5197. ;
  5198. ;          START OF THE REMIN BUFFER AREA
  5199. ;
  5200. ;          Contains cold boot initialization code.
  5201. ;
  5202. REMBUF   .BYTE 00
  5203. ;----------------------------------------------------------------------------
  5204. ;
  5205. PBOTABLE .BYTE 01.,02.,04.,05.,07.,08.,28.,29.,43.,44. ; offset bytes to patch
  5206.                                                        ; back the BIOS jump
  5207.                                                        ; vector.
  5208. AP2STPTR .WORD AP2STAT     ; pointers to the various status routines.
  5209. COMSTPTR .WORD COMSTAT
  5210. HAYESTPTR.WORD HAYESTAT
  5211. FIRMSTPTR.WORD FIRMSTAT
  5212. ;
  5213. OFFSET1  .BYTE 04E,01A     ; offset and identification bytes to recognize
  5214. OFFSET2  .BYTE 065,02A     ; different serial cards :
  5215. IDBYTE1  .BYTE 04D,09C     ; first row = IBS AP2 serial card.
  5216. IDBYTE2  .BYTE 0A3,051     ; second row = Hayes Micromodem card.
  5217. ;
  5218. ; Insert more offset and Id-bytes for other serial cards here.
  5219. ; Adjust NUMSERID correspondingly.
  5220. ;
  5221. ;-------------------------
  5222. ONCERINIT LDX #009         ; cold boot init jumps here.
  5223. PATCHBACK LDA PBOTABLE,X   ; get normal BIOS addresses from the attached copy
  5224.           TAY              ; and patch back the BIOS jump vector, except
  5225.           LDA @ACJVAFOLD,Y ; remote status, read and init.
  5226.           STA @JVAFOLD,Y
  5227.           DEX
  5228.           BPL PATCHBACK
  5229. ;--------------------------
  5230.           CLC              ; get address of CONCK, add 6 to it and patch
  5231.           LDY #055.        ; this code.
  5232.           LDA @ACJVAFOLD,Y
  5233.           ADC #006
  5234.           STA PATCH2+1
  5235.           INY
  5236.           LDA @ACJVAFOLD,Y
  5237.           ADC #000
  5238.           STA PATCH2+2
  5239. ;--------------------------
  5240.           LDY #031.        ; get address of Remote INIT and patch this code.
  5241.           LDA @ACJVAFOLD,Y
  5242.           STA PATCH1+1
  5243.           INY
  5244.           LDA @ACJVAFOLD,Y
  5245.           STA PATCH1+2
  5246. ;--------------------------
  5247.           LDA #0EA         ; patch the instruction JMP ONCERINIT to NOP(3x).
  5248.           STA PATCH3       ; ONCERINIT will be done only once.
  5249.           STA PATCH3+1
  5250.           STA PATCH3+2
  5251. ;--------------------------
  5252. ;--------------------------
  5253.           LDA SLT2TYP      ; find out which serial card there is in slot 2.
  5254.           CMP #003
  5255.           BNE NXTTYP2
  5256.           LDX COMSTPTR     ; Apple Com Card : save pointer to status routine
  5257.           LDY COMSTPTR+1   ; in X and Y registers.
  5258.           BNE TORINIT
  5259. NXTTYP2   CMP #006
  5260.           BNE NXTTYP3
  5261.           LDA FSTATUS      ; firmware card : get offset bytes from card's ROM
  5262.           STA PATCH4+1     ; and patch the status and read routine entry
  5263.           LDA FREAD        ; points in the FIRMSTAT routine.
  5264.           STA PATCH5+1
  5265.           LDX FIRMSTPTR
  5266.           LDY FIRMSTPTR+1
  5267.           BNE TORINIT
  5268. NXTTYP3   CMP #004
  5269.           BNE NOTKNOWN
  5270.           JSR FINDSER      ; if it is a serial card try to recognize it.
  5271.           BMI NOTKNOWN     ; FINDSER returns with minus flag on if card was
  5272.           TYA              ; not recognized. Y = ID number of serial card.
  5273.           BEQ AP2SER       ; Y=0 : IBS AP2 card.
  5274. HAYSER    CMP #001         ; Y=1 : Hayes micromodem card.
  5275.                            ; If Hayes card is already recognized as an Apple
  5276.                            ; Com card (I don't know), then this part can be
  5277.                            ; deleted.
  5278.           BNE NOTKNOWN     ; If FINDSER recognizes more serial cards then
  5279.                            ; insert here extra code for other cards.
  5280.           LDX HAYESTPTR
  5281.           LDY HAYESTPTR+1
  5282.           BNE TORINIT
  5283. AP2SER    LDX AP2STPTR
  5284.           LDY AP2STPTR+1
  5285. ;--------------------------
  5286. TORINIT   STX REMINCK+1    ; Patch INPORTSTAT to point to the adress of status
  5287.           STY REMINCK+2    ; routine.
  5288. PATCH1    JMP RINIT        ; Initialize once the serial card according to the
  5289.                            ; card's normal init routine.
  5290. NOTKNOWN  LDX #009         ; If card was not recognized then return to system
  5291.           LDY #SLOT        ; with error code 9 ( volume not found ).
  5292.           RTS
  5293. ;-------------------------------------------------------------------------
  5294. ;
  5295. ;  Serial card recognition routine.
  5296. ;
  5297. ;  Checks two unique bytes in the cards ROM space ( C200-C2FF ).
  5298. ;
  5299. FINDSER   LDY #NUMSERID
  5300. FNDNEXT1  LDA OFFSET1,Y
  5301.           TAX
  5302.           LDA SLOT2ADR,X
  5303.           CMP IDBYTE1,Y
  5304.           BEQ CONFIRM
  5305. FNDNEXT2  DEY
  5306.           BPL FNDNEXT1
  5307.           RTS
  5308. CONFIRM   LDA OFFSET2,Y
  5309.           TAX
  5310.           LDA SLOT2ADR,X
  5311.           CMP IDBYTE2,Y
  5312.           BNE FNDNEXT2
  5313. CODEND    RTS
  5314. ;---------------------------------------------------------------------------
  5315.           .BLOCK 256.+REMBUF-CODEND,00  ; adjusts buffer if init codelength
  5316.                                         ; is changed.
  5317. ;---------------------------------------------------------------------------
  5318.           .END
  5319. (*=== REMDR.DOC.TEXT ===*)
  5320. ;>>>>>>>>>>>>>>>>>>>>>>> REMDR.DOC.TEXT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  5321. ;
  5322. ;
  5323. ;----------------------------------------------------------------------
  5324. ;
  5325. ; Serial card driver for Kermit-UCSD  RUG/PT V1.0
  5326. ;
  5327. ;----------------------------------------------------------------------
  5328. ;
  5329. ; This program should be assembled and stored in the library ATTACH.DRIVERS
  5330. ; with the aid of the system program LIBRARY.CODE. It will work only 
  5331. ; when the program SYSTEM.ATTACH and the file ATTACH.DATA are also present
  5332. ; on the boot disk. For an explanation see also KERM.DOC2.TEXT.
  5333. ;
  5334. ; According to ATTACH.DATA the following volumes are attached to this driver :
  5335. ; ( see KERM.DOC3.TEXT for instructions on how to make ATTACH.DATA )
  5336. ; REMIN:
  5337. ; REMOUT:
  5338. ; CONSOLE:
  5339. ; KEYBOARD:
  5340. ; After the cold boot initialization of this driver however the modified BIOS
  5341. ; jump vector will be patched back to point at the normal BIOS entry points
  5342. ; except for the Remote Read, Init and Status routines.
  5343. ; The BIOS routine CONCK ( checks keyboard and maintains type-ahead buffer )
  5344. ; will still point to the top of this driver. Before sending a call to CONCK
  5345. ; back to the normal entry point, this driver will make a call to the routine
  5346. ; REMINCK to check the remote input port and to maintain a circular 256 byte
  5347. ; Remin buffer. The routine REMREAD reads only from this buffer.
  5348. ;
  5349. ; In order to keep this driver short, the cold boot initialization routine,
  5350. ; is placed in the 256 byte buffer area. It will be replaced by the data
  5351. ; received at the remote input port.
  5352. ;----------------------------------------------------------------------
  5353. ;
  5354. ;                         P. Terpstra
  5355. ;                         Dept. Biochemistry
  5356. ;                         University Groningen
  5357. ;                         Nijenborgh 16
  5358. ;                         9747 AG Groningen
  5359. ;                         The Netherlands
  5360. ;
  5361. ;----------------------------------------------------------------------
  5362. ;
  5363. ; For the source text of REMDRIVER see the file REMDRIVER.TEXT
  5364. ;
  5365. ;-----------------------------------------------------------------------
  5366. (*=== AP2.TEXT ===*)
  5367. 27     ;escape char: to escape from CONNECT mode back to the Apple.
  5368. 13     ;end-of-line char send to host after a kermit package.
  5369. 35     ;the kermit quote char the Apple uses to prefix control chars.
  5370. 0      ;the kermit padding char the Apple needs.
  5371. 0      ;number of padding chars the Apple needs.
  5372. 1      ;start-of-header (SOH) char the Apple uses to indicate a kermit packet.
  5373. 5      ;Apple key to manually interrupt the sending/receiving of files: <^E>
  5374. 17     ;Xon char used during CONNECT when printing the screen.
  5375. 19     ;Xoff char used during CONNECT when printing the screen.
  5376. 40     ;number of wait-cycles after sending a Xoff during the screendump.
  5377. 94     ;max kermit packet length the Apple can handle ( 20..94 ).
  5378. 5      ;max number of retries before the Apple breaks off sending/receiving.
  5379. 5      ;number of seconds(1..31) after which the host should resend a packet.
  5380. 0      ;half-duplex mode. ( 0 = false ).
  5381. 0      ;debug mode during sending/receiving. ( 0 = false ).
  5382. 1      ;file-warning for incoming files to avoid name conflicts. ( 0 = false )
  5383. 1      ;text-file send/rec mode. ( 1 = true )
  5384. 1      ;no formfeeds during CONNECT when screendump is on. ( 1 = true )
  5385. 1      ;in CONNECT:no echoing of control chars (exc. cr,lf,ff,bs,bell )(1=true)
  5386. 0      ;backspace key translated to DEL during CONNECT. ( 1 = true )
  5387. 1      ;type of acia on serial card.(0 = unknown, 1 = 6551 acia, 2 = 6850 acia )
  5388. -16210 ;adress of the acia command register. ( IBS AP2 serial card )
  5389. -16209 ;adress of the acia control register. ( IBS AP2 serial card )
  5390. 300    ;initial baud rate.
  5391. 8      ;number of databits ( word-length ).
  5392. 1      ;number of stopbits.
  5393. 0      ;parity ( 0=nopar; 1=oddpar; 2=evenpar; 3=markpar; 4=spacepar ).
  5394. 80     ;80= 80-column card in slot 3; 40= normal 40 column screen.
  5395.        ;******************* AP2.TEXT ******************************************
  5396.  
  5397. (*=== APCOM.TEXT ===*)
  5398. 27     ;escape char: to escape from CONNECT mode back to the Apple.
  5399. 13     ;end-of-line char send to host after a kermit package.
  5400. 35     ;the kermit quote char the Apple uses to prefix control chars.
  5401. 0      ;the kermit padding char the Apple needs.
  5402. 0      ;number of padding chars the Apple needs.
  5403. 1      ;start-of-header (SOH) char the Apple uses to indicate a kermit packet.
  5404. 5      ;Apple key to manually interrupt the sending/receiving of files: <^E>
  5405. 17     ;Xon char used during CONNECT when printing the screen.
  5406. 19     ;Xoff char used during CONNECT when printing the screen.
  5407. 40     ;number of wait-cycles after sending a Xoff during the screendump.
  5408. 94     ;max kermit packet length the Apple can handle ( 20..94 ).
  5409. 5      ;max number of retries before the Apple breaks off sending/receiving.
  5410. 5      ;number of seconds(1..31) after which the host should resend a packet.
  5411. 0      ;half-duplex mode. ( 0 = false ).
  5412. 0      ;debug mode during sending/receiving. ( 0 = false ).
  5413. 1      ;file-warning for incoming files to avoid name conflicts. ( 0 = false )
  5414. 1      ;text-file send/rec mode. ( 1 = true )
  5415. 1      ;no formfeeds during CONNECT when screendump is on. ( 1 = true )
  5416. 1      ;in CONNECT:no echoing of control chars (exc. cr,lf,ff,bs,bell )(1=true)
  5417. 0      ;backspace key translated to DEL during CONNECT. ( 1 = true )
  5418. 2      ;type of acia on serial card.(0 = unknown, 1 = 6551 acia, 2 = 6850 acia )
  5419. -16210 ;adress of the acia command register. ( Apple Com Card )
  5420. 0      ;adress of the acia control register. 
  5421. 300    ;initial baud rate.
  5422. 8      ;number of databits ( word-length ).
  5423. 1      ;number of stopbits.
  5424. 0      ;parity ( 0=nopar; 1=oddpar; 2=evenpar; 3=markpar; 4=spacepar ).
  5425. 80     ;80= 80-column card in slot 3; 40= normal 40 column screen.
  5426.        ;********************* APCOM.TEXT **************************************
  5427.  
  5428. (*=== SSC.TEXT ===*)
  5429. 27     ;escape char: to escape from CONNECT mode back to the Apple.
  5430. 13     ;end-of-line char send to host after a kermit package.
  5431. 35     ;the kermit quote char the Apple uses to prefix control chars.
  5432. 0      ;the kermit padding char the Apple needs.
  5433. 0      ;number of padding chars the Apple needs.
  5434. 1      ;start-of-header (SOH) char the Apple uses to indicate a kermit packet.
  5435. 5      ;Apple key to manually interrupt the sending/receiving of files: <^E>
  5436. 17     ;Xon char used during CONNECT when printing the screen.
  5437. 19     ;Xoff char used during CONNECT when printing the screen.
  5438. 40     ;number of wait-cycles after sending a Xoff during the screendump.
  5439. 94     ;max kermit packet length the Apple can handle ( 20..94 ).
  5440. 5      ;max number of retries before the Apple breaks off sending/receiving.
  5441. 5      ;number of seconds(1..31) after which the host should resend a packet.
  5442. 0      ;half-duplex mode. ( 0 = false ).
  5443. 0      ;debug mode during sending/receiving. ( 0 = false ).
  5444. 1      ;file-warning for incoming files to avoid name conflicts. ( 0 = false )
  5445. 1      ;text-file send/rec mode. ( 1 = true )
  5446. 1      ;no formfeeds during CONNECT when screendump is on. ( 1 = true )
  5447. 1      ;in CONNECT:no echoing of control chars (exc. cr,lf,ff,bs,bell )(1=true)
  5448. 0      ;backspace key translated to DEL during CONNECT. ( 1 = true )
  5449. 1      ;type of acia on serial card.(0 = unknown, 1 = 6551 acia, 2 = 6850 acia )
  5450. -16214 ;adress of the acia command register. ( Apple Super Serial Card )
  5451. -16213 ;adress of the acia control register. ( Apple Super Serial card )
  5452. 300    ;initial baud rate.
  5453. 8      ;number of databits ( word-length ).
  5454. 1      ;number of stopbits.
  5455. 0      ;parity ( 0=nopar; 1=oddpar; 2=evenpar; 3=markpar; 4=spacepar ).
  5456. 80     ;80= 80-column card in slot 3; 40= normal 40 column screen.
  5457.        ;****************************** SSC.TEXT *******************************
  5458.  
  5459. (*=== UNKNOWN.TEXT ===*)
  5460. 27     ;escape char: to escape from CONNECT mode back to the Apple.
  5461. 13     ;end-of-line char send to host after a kermit package.
  5462. 35     ;the kermit quote char the Apple uses to prefix control chars.
  5463. 0      ;the kermit padding char the Apple needs.
  5464. 0      ;number of padding chars the Apple needs.
  5465. 1      ;start-of-header (SOH) char the Apple uses to indicate a kermit packet.
  5466. 5      ;Apple key to manually interrupt the sending/receiving of files: <^E>
  5467. 17     ;Xon char used during CONNECT when printing the screen.
  5468. 19     ;Xoff char used during CONNECT when printing the screen.
  5469. 40     ;number of wait-cycles after sending a Xoff during the screendump.
  5470. 94     ;max kermit packet length the Apple can handle ( 20..94 ).
  5471. 5      ;max number of retries before the Apple breaks off sending/receiving.
  5472. 5      ;number of seconds(1..31) after which the host should resend a packet.
  5473. 0      ;half-duplex mode. ( 0 = false ).
  5474. 0      ;debug mode during sending/receiving. ( 0 = false ).
  5475. 1      ;file-warning for incoming files to avoid name conflicts. ( 0 = false )
  5476. 1      ;text-file send/rec mode. ( 1 = true )
  5477. 1      ;no formfeeds during CONNECT when screendump is on. ( 1 = true )
  5478. 1      ;in CONNECT:no echoing of control chars (exc. cr,lf,ff,bs,bell )(1=true)
  5479. 0      ;backspace key translated to DEL during CONNECT. ( 1 = true )
  5480. 0      ;type of acia on serial card.(0 = unknown, 1 = 6551 acia, 2 = 6850 acia )
  5481. 0      ;adress of the acia command register. 
  5482. 0      ;adress of the acia control register. 
  5483. 300    ;initial baud rate.
  5484. 8      ;number of databits ( word-length ).
  5485. 1      ;number of stopbits.
  5486. 0      ;parity ( 0=nopar; 1=oddpar; 2=evenpar; 3=markpar; 4=spacepar ).
  5487. 80     ;80= 80-column card in slot 3; 40= normal 40 column screen.
  5488.        ;********************* UNKNOWN.TEXT ************************************
  5489.  
  5490. (*=== MAKEDATA.TEXT ===*)
  5491. {>>>>>>>>>>>>>>>>>>>>>>>>>> MAKEDATA.TEXT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  5492.  
  5493.  
  5494. Program  make_kermit_data;
  5495.  
  5496. var  setupname, dest_vol : string;
  5497.      tf : text;
  5498.      df : file of integer;
  5499.      infile : array[1..28] of integer;
  5500.      i  : integer;
  5501.  
  5502.  
  5503. begin
  5504.   writeln('name of the kermit setup text file? ');
  5505.   readln( setupname );
  5506.   writeln('write final kermit.data file to which volume? ');
  5507.   readln( dest_vol );
  5508.   reset( tf, setupname );
  5509.   for i := 1 to 28 do readln( tf, infile[i] );
  5510.   close( tf );
  5511.   rewrite( df, concat( dest_vol, 'KERMIT.DATA' ) );
  5512.   for i := 1 to 28 do
  5513.     begin
  5514.       df^ := infile[i];
  5515.       put( df );
  5516.     end;
  5517.   close( df, lock );
  5518.   writeln('ready');
  5519. end.
  5520. (*=== ATTACH.UPD.TEXT ===*)
  5521. {>>>>>>>>>>>>>>>>>>>> ATTACH.UPD.TEXT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  5522.  
  5523. PROGRAM ATTACHUPD ;
  5524.  
  5525. TYPE  SD = RECORD
  5526.             DISKINFO : ARRAY[0..15] OF RECORD
  5527.                                          CODELENG, CODEADDR : INTEGER
  5528.                                        END;
  5529.             SEGNAME  : ARRAY[0..15] OF PACKED ARRAY[0..7] OF CHAR;
  5530.             SEGKIND  : ARRAY[0..15] OF ( LS, HS, SP, US, SS, UI, LI, DS );
  5531.             TEXTADDR : ARRAY[0..15] OF INTEGER;
  5532.             SEGINFO  : PACKED ARRAY[0..15] OF PACKED RECORD
  5533.                                                        SEGNUM : 0..255;
  5534.                                                        MTYPE  : 0..015;
  5535.                                                        UNUSED : 0..001;
  5536.                                                        VERSION: 0..007
  5537.                                                      END;
  5538.             INTRINSEG: SET OF 0..31;
  5539.             INFO     : PACKED ARRAY[0..219] OF 0..255;
  5540.            END;
  5541.            
  5542. VAR   SEGDIC : SD;
  5543.       FILENAME : STRING;
  5544.       F : FILE;
  5545.       OPTION,J : INTEGER;
  5546.       
  5547.          
  5548.        
  5549. PROCEDURE EXPLAIN;
  5550. BEGIN
  5551.   WRITELN('This program patches the FORTRAN compiler or SYSTEM.ATTACH (V1.1).');
  5552.   WRITELN('They can then be used with the UCSD Pascal Version 1.2.');
  5553.   WRITELN('The "Segment Version Numbers" in the SEGMENT-DICTIONARY of');
  5554.   WRITELN('these files will be changed to 5.');
  5555.   WRITELN('( Operating system reference manual pp. 266-269 )');
  5556.   WRITELN;
  5557.   WRITELN('Version 1.1 also accepts these patched files.');
  5558.   WRITELN;
  5559.   WRITELN('I cannot guarantee that this patch will work for all cases!');
  5560.   WRITELN('( P. Terpstra, Dept. Biochemistry, Groningen )');
  5561.   WRITELN;
  5562.   WRITELN('Choose option 1,2,3 or 4');
  5563.   WRITELN;
  5564.   WRITELN('1) FORTRAN COMPILER ==> Version 1.2');
  5565.   WRITELN('2) FORTRAN COMPILER ==> Restore original version bytes.');
  5566.   WRITELN;
  5567.   WRITELN('3) SYSTEM.ATTACH    ==> Version 1.2');
  5568.   WRITELN('4) SYSTEM.ATTACH    ==> Restore original version bytes.');
  5569.   WRITELN;
  5570.   WRITE('Option ? ');
  5571. END;
  5572.  
  5573. BEGIN
  5574.   EXPLAIN;
  5575.   READLN(OPTION);
  5576.   IF (OPTION>4) OR (OPTION<1) THEN EXIT(PROGRAM);
  5577.   WRITE('File is on which Volume (e.g. #4: )?  ');
  5578.   READLN(FILENAME);
  5579.   IF (OPTION=1) OR (OPTION=2)
  5580.     THEN BEGIN
  5581.            (*$I-*)
  5582.            RESET(F,CONCAT(FILENAME,'SYSTEM.COMPILER'));
  5583.            IF IORESULT<>0 THEN BEGIN WRITELN('Not found');EXIT(PROGRAM) END;
  5584.            IF BLOCKREAD(F,SEGDIC,1,0)<>1 THEN BEGIN
  5585.                                                 WRITELN('IO-Error');
  5586.                                                 EXIT(PROGRAM)
  5587.                                               END;
  5588.            (*$I+*)
  5589.            IF SEGDIC.SEGNAME[1]<>'FORTRAN:' 
  5590.              THEN BEGIN
  5591.                     WRITELN('This is not the FORTRAN COMPILER!!');
  5592.                     EXIT(PROGRAM)
  5593.                   END;
  5594.            IF OPTION=1
  5595.              THEN BEGIN
  5596.                     SEGDIC.SEGINFO[1].VERSION := 5;
  5597.                     FOR J:= 7 TO 14 DO SEGDIC.SEGINFO[J].VERSION := 5;
  5598.                   END
  5599.              ELSE BEGIN
  5600.                     SEGDIC.SEGINFO[1].VERSION := 1;
  5601.                     FOR J:= 7 TO 14 DO SEGDIC.SEGINFO[J].VERSION :=1;
  5602.                   END;
  5603.              IF BLOCKWRITE(F,SEGDIC,1,0)<>1 THEN BEGIN
  5604.                                                    WRITELN('IO-Error');
  5605.                                                    EXIT(PROGRAM)
  5606.                                                  END
  5607.                                             ELSE WRITELN('Ready');
  5608.          END;
  5609.   IF (OPTION=3) OR (OPTION=4)
  5610.     THEN BEGIN
  5611.            (*$I-*)
  5612.            RESET(F,CONCAT(FILENAME,'SYSTEM.ATTACH'));
  5613.            IF IORESULT<>0 THEN BEGIN WRITELN('Not found');EXIT(PROGRAM) END;
  5614.            IF BLOCKREAD(F,SEGDIC,1,0)<>1 THEN BEGIN
  5615.                                                 WRITELN('IO-Error');
  5616.                                                 EXIT(PROGRAM)
  5617.                                               END;
  5618.            (*$I+*)
  5619.            IF SEGDIC.SEGNAME[1]<>'SYSATCH ' 
  5620.              THEN BEGIN
  5621.                     WRITELN('This is not SYSTEM.ATTACH!!');
  5622.                     EXIT(PROGRAM)
  5623.                   END;
  5624.            IF OPTION=3
  5625.              THEN BEGIN
  5626.                     SEGDIC.SEGINFO[0].VERSION := 5;
  5627.                     SEGDIC.SEGINFO[1].VERSION := 5;
  5628.                   END
  5629.              ELSE BEGIN
  5630.                     SEGDIC.SEGINFO[0].VERSION := 0;
  5631.                     SEGDIC.SEGINFO[1].VERSION := 2;
  5632.                   END;
  5633.              IF BLOCKWRITE(F,SEGDIC,1,0)<>1 THEN BEGIN
  5634.                                                    WRITELN('IO-Error');
  5635.                                                    EXIT(PROGRAM)
  5636.                                                  END
  5637.                                             ELSE WRITELN('Ready');
  5638.          END;
  5639. END.
  5640. (*=== [End, no more files] ===*)