<<< k6gsys.asm >>>
*         Kermit68K: source file K68SYS
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

********************************* InpChar *****************************
*                                                                     *
*  Try to read a character from the specified logical channel.        *
*                                                                     *
*         Entry conditions : D1.B logical channel number              *
*                                                                     *
*         Exit  conditions : D0.B character received, if any          *
*                            D1.B Completion Code (see below)         *
*                                                                     *
*              CC symbol        Meaning                               *
*                                                                     *
*              AllOk            No errors, character in D0            *
*              BadChan          Inexistent channel                    *
*              ResChan          Access reserved, permission denied    *
*              DevNotRd         Device not ready (e.g. unmounted)     *
*              NotInpCh         Input impossible on this channel      *
*              NotOpRd          File not open for read                *
*              UnrInpF          Unrecoverable failure during input    *
*              InChLost         Input character lost                  *
*              InpBreak         Break received on input               *
*              BufEmpty         Input buffer empty                    *
*              BufOvflw         Input buffer overflow                 *
*              EndOfFil         End of file reached on input          *
*                                                                     *
***********************************************************************
InpChar:  RTS

********************************* OutChar *****************************
*                                                                     *
*  Try to write a character to the specified logical channel.         *
*                                                                     *
*         Entry conditions : D0.B character to write                  *
*                            D1.B logical channel number              *
*                                                                     *
*         Exit  conditions : D0.B character just sent                 *
*                            D1.B Completion Code (see below)         *
*                                                                     *
*              CC symbol        Meaning                               *
*                                                                     *
*              AllOk            No errors                             *
*              BadChan          Inexistent channel                    *
*              ResChan          Access reserved, permission denied    *
*              DevNotRd         Device not ready (e.g. unmounted)     *
*              NotOutCh         Output impossible on this channel     *
*              NotOpWr          File not open for write               *
*              UnrOutF          Unrecoverable failure during output   *
*              DevFull          Device full, not enough space         *
*                                                                     *
***********************************************************************
OutChar:  RTS

********************************* ChanCtrl ****************************
*                                                                     *
*  Performs control operations on logical channels.                   *
*                                                                     *
*         Entry conditions : D0.B Request Code (see below)            *
*                                                                     *
*              RC symbol        Meaning                               *
*                                                                     *
*              SetBaud          Set baud rate on port                 *
*              RawMode          Enable raw mode                       *
*              TextMode         Enable text mode                      *
*              DoXCntrl         Enable XON/XOFF protocol              *
*              NoXCntrl         Disable XON/XOFF protocol             *
*              SndBreak         Send a break over RS 232 C line       *
*              ClrInpBf         Clear input buffer                    *
*              ClrOutBf         Clear output buffer                   *
*                                                                     *
*                            D1.B channel number                      *
*                            D2.L additional data (only requested     *
*                                 baud rate now)                      *
*                                                                     *
*         Exit  conditions : D0.B Completion Code (see below)         *
*                                                                     *
*              CC symbol        Meaning                               *
*                                                                     *
*              AllOk            No errors                             *
*              BadChan          Inexistent channel                    *
*              ResChan          Access reserved, permission denied    *
*              DevNotRd         Device not ready (e.g. unmounted)     *
*              BadCtReq         I/O control request code invalid      *
*                                                                     *
***********************************************************************
ChanCtrl: RTS

********************************* SysInit *****************************
*                                                                     *
*  Initialize any system dependent thing.                             *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
SysInit:  RTS

********************************* SysExod *****************************
*                                                                     *
*  Return control to system.                                          *
*                                                                     *
*         Entry conditions : D0.B completion code, exit status        *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
SysExod:

********************************** System *****************************
*                                                                     *
*  Performs system commands. Called with a request code and 0, 1 or 2 *
*  null terminated argument strings, depending on request code.       *
*                                                                     *
*         Entry conditions : D0.B Request Code (see below)            *
*                                                                     *
*         RC symbol             Meaning                               *
*                                                                     *
*         Directry              Display a directory listing           *
*         SpacInfo              Display informations about disk usage *
*         DeletFil              Delete file(s)                        *
*         CopyFile              Copy file(s)                          *
*         ChangDir              Change the default directory          *
*         PrntFile              Print file(s)                         *
*         RenamFil              Rename file(s)                        *
*         TypeFile              Type file(s)                          *
*                                                                     *
*                            A0.L pointer to argument 1 (see below)   *
*                            A1.L pointer to argument 2 (see below)   *
*                                                                     *
*         RC symbol             Arguments number and meaning          *
*                                                                     *
*         Directry              0 or 1  directory path                *
*         SpacInfo              0 or 1  device or account name        *
*         DeletFil              1       file name                     *
*         CopyFile              2       source and target file names  *
*         ChangDir              0 or 1  path to new directory         *
*         PrntFile              1       file name                     *
*         RenamFil              2       old and new file names        *
*         TypeFile              1       file name                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
System:   RTS

******************************** GetCmdLP *****************************
*                                                                     *
*  Try to return a pointer to the command line, null terminated.      *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : A0.L pointer to the command line, if any *
*                            D0.B completion code                     *
*                                                                     *
***********************************************************************
GetCmdLP  RTS

********************************* FilOpen *****************************
*                                                                     *
*  Open a disk file or an I/O channel.                                *
*                                                                     *
*         Entry conditions : D0.B Request Code (see below)            *
*                                                                     *
*              RC symbol        Meaning                               *
*                                                                     *
*              RdWrOp           Open for read/write                   *
*              ReadOp           Open for read                         *
*              WriteOp          Open for write                        *
*              AppendOp         Open for append                       *
*                                                                     *
*                            D1.B logical channel number.             *
*                            A0.L points to file name null terminated *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L still points to the file name       *
*                                                                     *
***********************************************************************
FilOpen:  RTS

******************************** FilClose *****************************
*                                                                     *
*  Close a disk file or an I/O channel.                               *
*                                                                     *
*         Entry conditions : D1.B logical channel number.             *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
FilClose: RTS

********************************* FilDelet ****************************
*                                                                     *
*  Delete a file.                                                     *
*                                                                     *
*         Entry conditions : A0.L points to file name null terminated *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
FilDelet: RTS

********************************* ExpandFN ****************************
*                                                                     *
*  Expand a wildcard file name into an array of file names, returns   *
*  the number of files that match the passed string, with data        *
*  structures set up so that the first file name (if any) will be     *
*  returned by the next GetNxtF call.                                 *
*                                                                     *
*         Entry conditions : A0.L points to file name null terminated *
*                                                                     *
*         Exit  conditions : D0.L number of matches found, negative   *
*                                 if too many matches for user buffer *
*                            A0.L still points to the file name       *
*                                                                     *
***********************************************************************
ExpandFN: RTS

********************************* GetNxtF *****************************
*                                                                     *
*  Get the next file name from the list created by ExpandFN, returns  *
*  a true completion code if there's another file, copying its name   *
*  into the target string, or false if no more file names in list.    *
*                                                                     *
*         Entry conditions : A0.L points to the target string         *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L points to the target string         *
*                                                                     *
***********************************************************************
GetNxtF:  RTS

********************************* CRemTLoc ****************************
*                                                                     *
*  Convert filenames from remote system in a form suitable for the    *
*  local system.                                                      *
*                                                                     *
*         Entry conditions : A0.L points to the string to be          *
*                                 converted                           *
*                                                                     *
*         Exit  conditions : A0.L points to the same string suitably  *
*                                 converted                           *
*                                                                     *
***********************************************************************
CRemTLoc: RTS

********************************* CLocTRem ****************************
*                                                                     *
*  Convert filenames in local system syntax in a form suitable for    *
*  the remote Kermit system. The job that this routine must do is     *
*  explained here in detail.                                          *
*                                                                     *
*  Adapted from the "Kermit Protocol Manual", Sixth Edition, p. 16    *
*                                                                     *
*   1. Delete all pathnames and attributes from the file              *
*      specification. The file name should not contain directory      *
*      or device names; if it does, it may cause the recipient to     *
*      try to store the file in an inaccessible or nonexistent area,  *
*      or it may result in a very strange filename.                   *
*                                                                     *
*   2. After stripping any pathname, convert the remainder of the     *
*      file specification to the form "name.type", with no            *
*      restriction on length (except that it fit in the data field    *
*      of the F packet), and:                                         *
*                                                                     *
*         a. Include no more than one dot.                            *
*         b. Not begin or end with a dot.                             *
*         c. The name and type fields contain digits and uppercase    *
*            letters only.                                            *
*                                                                     *
*         Entry conditions : A0.L points to the string to be          *
*                                 converted                           *
*                                                                     *
*         Exit  conditions : A0.L points to the same string suitably  *
*                                 converted                           *
*                                                                     *
***********************************************************************
CLocTRem: RTS

********************************** NewName ****************************
*                                                                     *
*  Make a new name for the given file to avoid file name collisions.  *
*                                                                     *
*         Entry conditions : A0.L points to the file name string      *
*                                                                     *
*         Exit  conditions : A0.L points to the same string suitably  *
*                                 modified                            *
*                                                                     *
***********************************************************************
NewName:  RTS

********************************** Sleep ******************************
*                                                                     *
*  Puts the process to sleep.                                         *
*                                                                     *
*         Entry conditions : D0.B time interval to wait (seconds)     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
Sleep:    RTS

          END
<<< k6ocm2.asm >>>
          nam       Kermit68K
          ttl       SET command subroutines module

*         Kermit68K: source file K68CM2
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68Commands2,0,0,Edition,0,0

DoSET:    LEA       SETTable(PC),A1    Pointer to SET parameters table
          ST        D1
          BSR       ParsKyW            Look for a valid SET parameter
          TST.B     D0                 Ok ?
          BLT.S     DoSET1             No, return
          LEA       DoSetTab(PC),A1    Pointer to SET jump table
          BRA       IndxJump           Join common jump routine
DoSET1    RTS

DoSSEND:  LEA       SSRTable(PC),A1    Point to SET SEND/RECEIVE params table
          ST        D1
          BSR       ParsKyW            Look for a valid SET SEND/RECEIVE param
          TST.B     D0                 Ok ?
          BLT.S     DoSSEND1           No, return
          LEA       DoSetSTb(PC),A1    Pointer to SET SEND jump table
          BRA       IndxJump           Join common jump routine
DoSSEND1  RTS

DoSRECV:  LEA       SSRTable(PC),A1    Point to SET SEND/RECEIVE params table
          ST        D1
          BSR       ParsKyW            Look for a valid SET SEND/RECEIVE param
          TST.B     D0                 Ok ?
          BLT.S     DoSRECV1           No, return
          LEA       DoSetRTb(PC),A1    Pointer to SET RECEIVE jump table
          BRA       IndxJump           Join common jump routine
DoSRECV1  RTS

DoSFILE:  LEA       SFILTabl(PC),A1    Point to SET FILE parameters table
          ST        D1
          BSR       ParsKyW            Look for a valid SET FILE parameter
          TST.B     D0                 Ok ?
          BLT.S     DoSFILE1           No, return
          LEA       DoSFlTab(PC),A1    Pointer to SET FILE jump table
          BRA       IndxJump           Join common jump routine
DoSFILE1  RTS

DoSRTRY:  LEA       SRETTabl(PC),A1    Point to SET RETRY parameters table
          ST        D1
          BSR       ParsKyW            Look for a valid SET RETRY parameter
          TST.B     D0                 Ok ?
          BLT.S     DoSRTRY1           No, return
          LEA       DoSRtTab(PC),A1    Pointer to SET RETRY jump table
          BRA       IndxJump           Join common jump routine
DoSRTRY1  RTS

DoStPRM:  LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Ok ?
          BLT.S     DoStPRM1           No, return
          LEA       Prompt(A6),A0      Pointer to the prompt string
          MOVEQ     #PromptML,D0       Max prompt length
          BSR       CopyStr            Copy
DoStPRM1  RTS

DoSetESC: MOVEQ     #Escape,D7         Relative address escape character
          BRA.S     SetCtCh            Join common parameter setter

DoStRMrk: MOVEQ     #IStPckCh,D7       Relative address receive pack marker
          BRA.S     SetCtCh            Join common parameter setter

DoStSMrk: MOVEQ     #OStPckCh,D7       Relative address send packet marker
          BRA.S     SetCtCh            Join common parameter setter

DoStRPdC: MOVEQ     #IPadChar,D7       Relative address receive pad character
          BRA.S     SetCtCh            Join common parameter setter

DoStSPdC: MOVEQ     #OPadChar,D7       Relative address send pad character
          BRA.S     SetCtCh            Join common parameter setter

DoStREOL: MOVEQ     #IEOL,D7           Relative address receive EOL character
          BRA.S     SetCtCh            Join common parameter setter

DoStSEOL: MOVEQ     #OEOL,D7           Relative address send EOL character
*          BRA.S     SetCtCh            Join common parameter setter

********************************* SetCtCh ****************************
*                                                                     *
*  Look for a control character ASCII code specification, then set    *
*  the addressed variable.                                            *
*                                                                     *
*         Entry conditions : D7.L Relative (to A6) address of the     *
*                                 variable to set                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
SetCtCh   MOVEQ     #Asc_Nul,D1        Valid range lower bound
          MOVEQ     #Asc_Del,D2        Valid range upper bound
          BSR       ParsNm             Try to get a number
          TST.B     D1                 Invalid number ?
          BLT.S     SetCtCh2           Yes, return
          CMPI.B    #Asc_US,D0         No, check for ASCII control range
          BLS.S     SetCtCh1           Ok, set the parameter
          CMPI.L    #Asc_Del,D0        Delete ?
          BEQ.S     SetCtCh1           Yes, set the parameter
          LEA       SetCtStr(PC),A1    No, not in control range
          LEA       DataBuf(A6),A0     Point to the guilty number
          BSR       ParsErr            Give appropriate error message
          BRA.S     SetCtCh2
SetCtCh1  MOVE.B    D0,(A6,D7.L)       Finally set the parameter
SetCtCh2  RTS

DoStRPdN: MOVEQ     #IPadNumb,D7       Relative address receive pad number
          MOVEQ     #0,D1              Valid range lower bound
          MOVEQ     #100,D2            Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoStSPdN: MOVEQ     #OPadNumb,D7       Relative address send pad number
          MOVEQ     #0,D1              Valid range lower bound
          MOVEQ     #100,D2            Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoStRTIM: ST        TimInFlg(A6)       Set flag to allow overriding Send-Init
          MOVEQ     #ITimInt,D7        Relative address receive timeout
          MOVEQ     #1,D1              Valid range lower bound
          MOVEQ     #50,D2             Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoStSTIM: MOVEQ     #OTimInt,D7        Relative address send timeout interval
          MOVEQ     #1,D1              Valid range lower bound
          MOVEQ     #50,D2             Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoStRMPS: MOVEQ     #IMPckSiz,D7       Relative address receive max packet size
          MOVEQ     #10,D1             Valid range lower bound
          MOVEQ     #94,D2             Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoStSMPS: ST        SndPSFlg(A6)       Set flag to allow overriding Send-Init
          MOVEQ     #OMPckSiz,D7       Relative address send max packet size
          MOVEQ     #10,D1             Valid range lower bound
          MOVEQ     #94,D2             Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoStDLAY: MOVEQ     #Delay,D7          Relative address delay time before send
          MOVEQ     #0,D1              Valid range lower bound
          MOVEQ     #100,D2            Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoSetRtI: MOVEQ     #RtryInit,D7       Relative address initial retry limit
          MOVEQ     #0,D1              Valid range lower bound
          MOVEQ     #100,D2            Valid range upper bound
          BRA.S     SetNPar            Join common parameter setter

DoSetRtP: MOVEQ     #RtryPack,D7       Relative address normal retry limit
          MOVEQ     #0,D1              Valid range lower bound
          MOVEQ     #100,D2            Valid range upper bound
*          BRA.S     SetNPar           Join common parameter setter

********************************* SetNPar  ***************************
*                                                                     *
*  Look for a number specification, then set the addressed variable.  *
*                                                                     *
*         Entry conditions : D7.L Relative (to A6) address of the     *
*                                 variable to set                     *
*                            D1.L range specification, lower bound    *
*                            D2.L range specification, upper bound    *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
SetNPar   BSR       ParsNm             Try to get a number
          TST.B     D1                 Invalid number ?
          BLT.S     SetNPar1           Yes, return
          MOVE.B    D0,(A6,D7.L)       No, set the parameter
SetNPar1  RTS

DoStPAR:  LEA       ParTable(PC),A1    Pointer to parity keywords table
          ST        D1
          BSR       ParsKyW            Look for a valid parity specification
          TST.B     D0                 Ok ?
          BLT.S     DoStPAR1           No, return
          MOVE.B    D0,Parity(A6)      Yes, set parity to the requested value
DoStPAR1  RTS

DoStBCT:  LEA       BlCkTabl(PC),A1    Pointer to block check type table
          ST        D1                 A keyword is mandatory
          BSR       ParsKyW            Look for valid block check specification
          TST.B     D0                 Ok ?
          BLT.S     DoStBCT1           No, return
          MOVE.B    D0,BlChkRq(A6)     Yes, set block check to requested value
DoStBCT1  RTS

DoStIFD:  LEA       IFlDTabl(PC),A1    Points to incomplete file disp table
          ST        D1
          BSR       ParsKyW            Look for valid disposition specification
          TST.B     D0                 Ok ?
          BLT.S     DoStIFD1           No, return
          SNE       Keep(A6)           Yes, set the keep flag accordingly
DoStIFD1  RTS

DoStFNm:  LEA       FNamTabl(PC),A1    Points to incomplete file disp table
          ST        D1
          BSR       ParsKyW            Look for valid disposition specification
          TST.B     D0                 Ok ?
          BLT.S     DoStFNm1           No, return
          SNE       FNameCnv(A6)       Yes, set conversion flag accordingly
DoStFNm1  RTS

DoStFDs:  LEA       OnOfTabl(PC),A1    Points to on/off keywords table
          ST        D1
          BSR       ParsKyW            Look for valid on/off specification
          TST.B     D0                 Ok ?
          BLT.S     DoStFDs1           No, return
          SEQ       Quiet(A6)          Yes, set the quiet flag accordingly
DoStFDs1  RTS

DoStFTp:  LEA       FTypTabl(PC),A1    Points to file type keywords table
          ST        D1
          BSR       ParsKyW            Look for a valid file type specification
          TST.B     D0                 Ok ?
          BLT.S     DoStFTp1           No, return
          SNE       Binary(A6)         Yes, set the binary flag accordingly
DoStFTp1  RTS

DoStFWn:  LEA       OnOfTabl(PC),A1    Points to on/off keywords table
          ST        D1
          BSR       ParsKyW            Look for valid on/off specification
          TST.B     D0                 Ok ?
          BLT.S     DoStFWn1           No, return
          SNE       Warning(A6)        Yes, set the warning flag accordingly
DoStFWn1  RTS

DoStDUP:  LEA       DuplTabl(PC),A1    Points to duplex keywords table
          ST        D1
          BSR       ParsKyW            Look for valid duplex specification
          TST.B     D0                 Ok ?
          BLT.S     DoStDUP1           No, return
          SNE       Duplex(A6)         Yes, set the duplex flag accordingly
DoStDUP1  RTS

DoStFLW:  LEA       FlowTabl(PC),A1    Points to flow control keywords table
          ST        D1
          BSR       ParsKyW            Look for valid flow specification
          TST.B     D0                 Ok ?
          BLT.S     DoStFLW1           No, return
          MOVE.B    D0,Flow(A6)        Yes, set the flow control variable
DoStFLW1  RTS

DoStHND:  LEA       HandTabl(PC),A1    Points to handshake chars keywords table
          ST        D1
          BSR       ParsKyW            Look for valid handshake specification
          TST.B     D0                 Ok ?
          BLT.S     DoStHND1           No, return
          SNE       TurnFlag(A6)       Yes, set the handshake flag accordingly
          MOVE.B    D0,TurnChar(A6)    Line turnaround character
DoStHND1  RTS

DoStLIN:  LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Ok ?
          BLT.S     DoStLIN1           No, return
          MOVEQ     #HostLine,D1       Yes, close the old line
          BSR       FilClose
          MOVEQ     #RdWrOp,D0         Try to open the new line
          MOVEQ     #HostLine,D1       This is the channel number
          MOVEA.L   A1,A0              Point to the new line name
          BSR       FilOpen            Open, if possible
          TST.B     D0                 Ok ?
          BEQ.S     DoStLIN2           No, give error message, reopen old line
          LEA       LineName(A6),A0    Yes, point to the line name string
          MOVEQ     #LinNamML,D0       Max line name length
          BSR       CopyStr            Copy
          LEA       ConLinNm(PC),A1    Point to the console line name
          BSR       CompStr            Compare the two line names
          TST.B     D0                 Are equal ?
          SEQ       Local(A6)          If not we are local, remote otherwise
          BEQ.S     DoStLIN1           If local, leave speed unchanged
          MOVE.L    #-1,Speed(A6)      If remote, say speed unknown
DoStLIN1  RTS
DoStLIN2  LEA       OpLnEStr(PC),A1    Point to the error message string
          BSR       ParsErr            Say that we can't open the new line
          LEA       LineName(A6),A0    Point to the line name string
          MOVEQ     #RdWrOp,D0         Reopen the old line
          MOVEQ     #HostLine,D1       This is the channel number
          BSR       FilOpen            Open now
          RTS

DoStSPE:  MOVEQ     #50,D1             Valid range lower bound
          MOVE.L    #19200,D2          Valid range upper bound
          BSR       ParsNm             Try to get a valid number specification
          TST.B     D1                 Valid number on input ?
          BLT.S     DoStSPE1           No, return
          BSR.S     ChkBaud            Check if requested speed is supported
          TST.B     D1                 Ok ?
          BEQ.S     DoStSPE1           No, return
          MOVE.L    D0,Speed(A6)       Yes, set the baud rate variable
          MOVE.L    D0,D2              Pass baud rate to ChanCtrl
          MOVEQ     #HostLine,D1       Pass channel number to ChanCtrl
          MOVEQ     #SetBaud,D0        Pass request code to ChanCtrl
          BSR       ChanCtrl           Physically set the host line baud rate
DoStSPE1  RTS

ChkBaud:  LEA       SpeedTbl(PC),A0    Pointer to baud rates table
ChkBaud1  TST.L     (A0)               End of table ?
          BLT.S     ChkBaud2           Yes, unsupported baud rate
          CMP.L     (A0)+,D0           No, compare, baud rate found ?
          BNE.S     ChkBaud1           No, loop until found or end of table
          ST        D1                 Yes, set completion code accordingly
          RTS
ChkBaud2  LEA       DataBuf(A6),A0     Point to the guilty number
          LEA       UnsBRStr(PC),A1    Point to the error message
          BSR       ParsErr            Give error message
          SF        D1                 Return a negative completion code
          RTS

SpeedTbl  DC.L         50
          DC.L        110
          DC.L        150
          DC.L        300
          DC.L        600
          DC.L       1200
          DC.L       2400
          DC.L       4800
          DC.L       9600
          DC.L      19200
          DC.L      38400
          DC.L      -1

          ends
          END
<<< k6ocm3.asm >>>
          nam       Kermit68K
          ttl       REMOTE and SHOW commands subroutines module

*         Kermit68K: source file K68CM3
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68Commands3,0,0,Edition,0,0

*** Code for REMOTE commands execution ***

Rm1FlOp   MOVE.B    D0,D7              Save command
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Remote file specified ?
          BLT.S     Rm1FlOp1           No, give error message
          MOVEA.L   A1,A2              Yes
          MOVE.B    D7,D0              Restore command
          SUBA.L    A3,A3              Terminate the SetGCmd arguments list
          BSR       SetGCmd            Setup data buffer and involved variables
          MOVEQ     #SndSrvIS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS
Rm1FlOp1  LEA       Rm1FOStr(PC),A0
          BSR       ConWrite
          RTS

Rm2FlOp   MOVE.B    D0,D7              Save command
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsWrd            Get a text string from the command line
          TST.B     D0                 Remote file 1 specified ?
          BLT.S     Rm2FlOp1           No, give error message
          MOVEA.L   A1,A2              Yes
          LEA       1(A0),A1
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Remote file 2 specified ?
          BLT.S     Rm2FlOp1           No, give error message
          MOVEA.L   A1,A3              Yes
          MOVE.B    D7,D0              Restore command
          SUBA.L    A4,A4              Terminate the SetGCmd arguments list
          BSR       SetGCmd            Setup data buffer and involved variables
          MOVEQ     #SndSrvIS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS
Rm2FlOp1  LEA       Rm2FOStr(PC),A0
          BSR       ConWrite
          RTS

*** REMOTE command ***

DoREMOT:  BSR       ChkLocl            Check mode
          LEA       REMTable(PC),A1    Pointer to REMOTE commands table
          ST        D1                 Keyword specification is mandatory
          BSR       ParsKyW            Look for a valid REMOTE command
          TST.B     D0                 Ok ?
          BLT.S     DoREMOT1           No, return
          LEA       DoRemTab(PC),A1    Pointer to REMOTE jump table
          BRA       IndxJump           Join common jump routine
DoREMOT1  RTS

*** REMOTE COPY command ***

DoRemCOP: MOVEQ     #'K',D0            Copy command
          BSR       Rm2FlOp            Call the remote file operation routine
          RTS

*** REMOTE CWD command ***

DoRmCWD:  SUBA.L    A2,A2              No SetGCmd arguments by default
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Remote directory specified ?
          BLT.S     DoRmCWD1           No, no arguments
          MOVEA.L   A1,A2              Yes
          SUBA.L    A3,A3              Nullify next argument pointer
DoRmCWD1  MOVEQ     #'C',D0            Change working directory command
          BSR       SetGCmd
          MOVEQ     #SndGCmdS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** REMOTE DELETE command ***

DoRemDEL: MOVEQ     #'E',D0            Delete command
          BSR       Rm1FlOp            Call the remote file operation routine
          RTS

*** REMOTE DIRECTORY command ***

DoRmDIR:  SUBA.L    A2,A2              No SetGCmd arguments by default
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Remote file or directory specified ?
          BLT.S     DoRmDIR1           No, no arguments
          MOVEA.L   A1,A2              Yes
          SUBA.L    A3,A3              Nullify next argument pointer
DoRmDIR1  MOVEQ     #'D',D0            Remote directory command
          BSR       SetGCmd            Setup data buffer and involved variables
          MOVEQ     #SndSrvIS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** REMOTE HELP command ***

DoRmHELP: SUBA.L    A2,A2              No arguments for SetGCmd
          MOVEQ     #'H',D0            Remote help command
          BSR       SetGCmd            Setup data buffer and involved variables
          MOVEQ     #SndSrvIS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** REMOTE HOST command ***

DoRemHOS: LEA       DataBuf(A6),A1
          MOVEA.L   A1,A0
          BSR       ParsTxt
          LEA       CmdBuf(A6),A0
          MOVEQ     #CmdBufLn,D0
          BSR       CopyStr
          BSR       TrnsInit
          MOVE.B    #'C',ServrCmd(A6)
          MOVEQ     #SndSrvIS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** REMOTE KERMIT command ***

DoRemKER: RTS

*** REMOTE PRINT command ***

DoRemPRI: MOVEQ     #'S',D0
          BSR       Rm1FlOp            Call the remote file operation routine
          RTS

*** REMOTE RENAME command ***

DoRemREN: MOVEQ     #'R',D0            Rename command
          BSR       Rm2FlOp            Call the remote file operation routine
          RTS

*** REMOTE SET command ***

DoRemSET: RTS

*** REMOTE SPACE command ***

DoRmSPA:  SUBA.L    A2,A2              No SetGCmd arguments by default
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Remote directory specified ?
          BLT.S     DoRmSPA1           No, no arguments
          MOVEA.L   A1,A2              Yes
          SUBA.L    A3,A3              Nullify next argument pointer
DoRmSPA1  MOVEQ     #'U',D0            Remote space query command
          BSR       SetGCmd            Setup for generic commands
          MOVEQ     #SndGCmdS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** REMOTE SUBMIT command ***

DoRemSUB: MOVEQ     #'P',D0            Submit command
          BSR       Rm1FlOp            Call the remote file operation routine
          RTS

*** REMOTE TYPE command ***

DoRemTYP: MOVEQ     #'T',D0            Type command
          BSR       Rm1FlOp            Call the remote file operation routine
          RTS

*** REMOTE WHO command ***

DoRmWHO:  SUBA.L    A2,A2              No SetGCmd arguments by default
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Remote user name specified ?
          BLT.S     DoRmWHO1           No, no arguments
          MOVEA.L   A1,A2              Yes
          SUBA.L    A3,A3              Nullify next argument pointer
DoRmWHO1  MOVEQ     #'W',D0            Remote who command
          BSR       SetGCmd            Setup data buffer and involved variables
          MOVEQ     #SndSrvIS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** SHOW command ***

DoSHOW:   LEA       SHOWTabl(PC),A1    Pointer to SHOW parameters table
          ST        D1
          BSR       ParsKyW            Look for a valid SHOW option
          TST.B     D0                 Ok ?
          BLT.S     DoSHOW1            No, return
          LEA       DoShoTab(PC),A1    Pointer to SHOW jump table
          BRA       IndxJump           Join common jump routine
DoSHOW1   RTS

*** SHOW VERSION command ***

DoShoVer: LEA       VersStr(PC),A0     Show the current Kermit68K version
          BSR       ConWrite
          LEA       ShVerStr(PC),A0    And then the warning
          BSR       ConWrite
          RTS

*** SHOW PARAMETERS command ***

DoShoP:   LEA       ShPStr1(PC),A0     Line name
          BSR       ConWrite
          LEA       LineName(A6),A0
          BSR       ConWrite

          LEA       ShPStr2(PC),A0     Line speed
          BSR       ConWrite
          MOVE.L    Speed(A6),D0       Load it
          BLT.S     DoShoP0            Negative, unknown speed
          BSR       TypeUNum           Write the baud rate
          BRA.S     DoShoP01
DoShoP0   LEA       ShPStr3(PC),A0     Say unknown speed
          BSR       ConWrite

DoShoP01  LEA       ShPStr4(PC),A0     Mode
          BSR       ConWrite
          TST.B     Local(A6)
          BEQ.S     DoShoP1
          LEA       ShPStr5(PC),A0
          BRA.S     DoShoP2
DoShoP1   LEA       ShPStr6(PC),A0
DoShoP2   BSR       ConWrite

          LEA       ShPStr7(PC),A0     Parity selected
          BSR       ConWrite
          MOVE.B    Parity(A6),D0
          CMPI.B    #'E',D0
          BEQ.S     DoShoP3
          CMPI.B    #'O',D0
          BEQ.S     DoShoP4
          CMPI.B    #'M',D0
          BEQ.S     DoShoP5
          CMPI.B    #'S',D0
          BEQ.S     DoShoP6
          LEA       ShPStr12(PC),A0    none
          BRA.S     DoShoP7
DoShoP3   LEA       ShPStr8(PC),A0     even
          BRA.S     DoShoP7
DoShoP4   LEA       ShPStr9(PC),A0     odd
          BRA.S     DoShoP7
DoShoP5   LEA       ShPStr10(PC),A0    mark
          BRA.S     DoShoP7
DoShoP6   LEA       ShPStr11(PC),A0    space
DoShoP7   BSR       ConWrite

          LEA       ShPStr13(PC),A0    Duplex
          BSR       ConWrite
          TST.B     Duplex(A6)
          BEQ.S     DoShoP8
          LEA       ShPStr14(PC),A0
          BRA.S     DoShoP9
DoShoP8   LEA       ShPStr15(PC),A0
DoShoP9   BSR       ConWrite

          LEA       ShPStr16(PC),A0    Flow control
          BSR       ConWrite
          MOVE.B    Flow(A6),D0
          BEQ.S     DoShoP11
          CMPI.B    #1,D0 Flow(A6)
          BNE.S     DoShoP10
          LEA       ShPStr17(PC),A0
          BRA.S     DoShoP12
DoShoP10  MOVEQ     #0,D2
          BSR       DoShoP42
          BRA.S     DoShoP13
DoShoP11  LEA       ShPStr12(PC),A0
DoShoP12  BSR       ConWrite

DoShoP13  LEA       ShPStr18(PC),A0    Handshake
          BSR       ConWrite
          TST.B     TurnFlag(A6)
          BNE.S     DoShoP14
          LEA       ShPStr12(PC),A0
          BSR       ConWrite
          BRA.S     DoShoP15
DoShoP14  MOVE.B    TurnChar(A6),D0
          MOVEQ     #0,D2
          BSR       DoShoP42

DoShoP15  LEA       ShPStr19(PC),A0
          BSR       ConWrite

          MOVE.B    TimInFlg(A6),D0
          OR.B      SndPSFlg(A6),D0
          BEQ.S     DoShoP16
          LEA       ShPStr20(PC),A0
          BSR       ConWrite

DoShoP16  LEA       ShPStr21(PC),A0
          BSR       ConWrite
          MOVE.B    OTimInt(A6),D0     Send timeout interval
          BSR       DoShoP40
          MOVE.B    ITimInt(A6),D0     Receive timeout interval
          BSR       DoShoP41
          TST.B     TimInFlg(A6)
          BEQ.S     DoShoP17
          MOVEQ     #'*',D0
          BSR       ConOut

DoShoP17  LEA       ShPStr22(PC),A0
          BSR       ConWrite
          MOVE.B    OPadNumb(A6),D0    Send padding
          BSR       DoShoP40
          MOVE.B    IPadNumb(A6),D0    Receive padding
          BSR       DoShoP41

          LEA       ShPStr23(PC),A0
          BSR       ConWrite
          MOVE.B    OPadChar(A6),D0    Send padding character
          BSR       DoShoP40
          MOVE.B    IPadChar(A6),D0    Receive padding character
          BSR       DoShoP41

          LEA       ShPStr24(PC),A0
          BSR       ConWrite
          MOVE.B    OStPckCh(A6),D0    Send packet start character
          BSR       DoShoP40
          MOVE.B    IStPckCh(A6),D0    Receive packet start character
          BSR       DoShoP41

          LEA       ShPStr25(PC),A0
          BSR       ConWrite
          MOVE.B    OEOL(A6),D0        Send End-Of-Line character
          BSR       DoShoP40
          MOVE.B    IEOL(A6),D0        Receive End-Of-Line character
          BSR       DoShoP41

          LEA       ShPStr26(PC),A0
          BSR       ConWrite
          MOVE.B    OMPckSiz(A6),D0    Send max packet size
          BSR       DoShoP40

          TST.B     SndPSFlg(A6)
          BEQ.S     DoShoP18
          MOVEQ     #'*',D0
          BRA.S     DoShoP19
DoShoP18  MOVEQ     #' ',D0
DoShoP19  BSR       ConOut
          MOVE.B    IMPckSiz(A6),D0    Receive max packet size
          MOVEQ     #8,D2
          BSR       DoShoP42

          LEA       ShPStr27(PC),A0
          BSR       ConWrite
          MOVE.B    BlChkRq(A6),D0     Block check type
          MOVEQ     #0,D2
          BSR       DoShoP42

          LEA       ShPStr28(PC),A0
          BSR       ConWrite
          MOVE.B    Delay(A6),D0       Delay
          MOVEQ     #0,D2
          BSR       DoShoP42

          LEA       ShPStr29(PC),A0
          BSR       ConWrite
          MOVE.B    RtryInit(A6),D0    Retry limit for initial connection
          MOVEQ     #0,D2
          BSR       DoShoP42

          LEA       ShPStr30(PC),A0
          BSR       ConWrite
          MOVE.B    RtryPack(A6),D0    Retry limit for normal packets
          MOVEQ     #0,D2
          BSR       DoShoP42

          TST.B     Bit8Flag(A6)
          BEQ.S     DoShoP20
          LEA       ShPStr31(PC),A0
          BSR       ConWrite
          MOVE.B    Bit8Quot(A6),D0    8-th bit prefix
          BSR       ConOut

DoShoP20  TST.B     ReptFlag(A6)
          BEQ.S     DoShoP21
          LEA       ShPStr32(PC),A0
          BSR       ConWrite
          MOVE.B    ReptQuot(A6),D0    Repeat prefix
          BSR       ConOut

DoShoP21  LEA       ShPStr33(PC),A0
          BSR       ConWrite
          TST.B     FNameCnv(A6)       File name
          BEQ.S     DoShoP22
          LEA       ShPStr34(PC),A0
          BRA.S     DoShoP23
DoShoP22  LEA       ShPStr35(PC),A0
DoShoP23  BSR       ConWrite

          LEA       ShPStr36(PC),A0
          BSR       ConWrite
          TST.B     Binary(A6)         File type
          BEQ.S     DoShoP24
          LEA       ShPStr37(PC),A0
          BRA.S     DoShoP25
DoShoP24  LEA       ShPStr38(PC),A0
DoShoP25  BSR       ConWrite

          LEA       ShPStr39(PC),A0
          BSR       ConWrite
          TST.B     Warning(A6)        File warning
          BEQ.S     DoShoP26
          LEA       ShPStr40(PC),A0
          BRA.S     DoShoP27
DoShoP26  LEA       ShPStr41(PC),A0
DoShoP27  BSR       ConWrite

          LEA       ShPStr42(PC),A0
          BSR       ConWrite
          TST.B     Quiet(A6)          File display
          BNE.S     DoShoP28
          LEA       ShPStr40(PC),A0
          BRA.S     DoShoP29
DoShoP28  LEA       ShPStr41(PC),A0
DoShoP29  BSR       ConWrite

          LEA       ShPStr43(PC),A0
          BSR       ConWrite
          TST.B     Keep(A6)           Incomplete file disposition
          BEQ.S     DoShoP30
          LEA       ShPStr44(PC),A0
          BRA.S     DoShoP31
DoShoP30  LEA       ShPStr45(PC),A0
DoShoP31  BSR       ConWrite

          BSR       NewLine
          RTS

DoShoP40  MOVEQ     #11,D2             Use a 11 characters field
          BRA.S     DoShoP42           Join common part
DoShoP41  MOVEQ     #9,D2              Use a 9 characters field
DoShoP42  LEA       DataBuf+34(A6),A0  Point to the end of a temporary buffer
          EXT.W     D0                 Extend to word
          EXT.L     D0                 Extend to long word
          ST        D1                 Unsigned conversion wanted
          MOVEQ     #10,D3             Base is 10
          BSR       IntToAs            Convert the number into a string
          BSR       ConWrite           Write the obtained string
          RTS

          ends
          END
<<< k6ocm4.asm >>>
          nam       Kermit68K
          ttl       Command line parser module

*         Kermit68K: source file K68CM4
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68Commands4,0,0,Edition,0,0

********************************** CmdLnP *****************************
*                                                                     *
*  Kermit68K command line parser.                                     *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
CmdLnP:   BSR       GetCmdLP           Try to get the command line pointer
          TST.B     D0                 Success ?
          BEQ       CmdLnP10           No, return
          MOVEA.L   A0,A5              Yes, load pointer for parser functions
          MOVEQ     #-1,D7             Say no protocol commands yet
          SF        D5                 Set the connect before flag to false
          SF        D6                 Set the connect after flag to false
CmdLnP1   LEA       RecBuf(A6),A4      This pointer is used by DoCmLA
          MOVEA.L   A4,A0              Put here the command line options
          BSR       ParsWrd            Try to get a word from command line
          TST.B     D0                 Success ?
          BLT.S     CmdLnP2            No, exit loop
          CMPI.B    #'-',(A4)+         Options begins with dash
          BNE       DoCmLA4            Not an options, give usage info
          BSR       DoCmLA             Got an option, handle it
          BRA.S     CmdLnP1            Loop until the whole line is parsed

CmdLnP2   TST.B     Local(A6)          Are we running in local mode ?
          BNE.S     CmdLnP4            Yes, no problem
          CMPI.B    #SndSrvIS,D7       Are we issuing a get command ?
          BEQ.S     CmdLnP3            Yes, fatal error
          MOVEQ     #SndGCmdS,D7       Are we issuing a finish command ?
          BEQ.S     CmdLnP3            Yes, fatal error
          TST.B     D5                 Are we connecting trough the host line ?
          BEQ.S     CmdLnP4            No, all ok
CmdLnP3   LEA       LBReqStr(PC),A0    Give message about -l and -b need
          BRA       FatalEr            Return to system

CmdLnP4   CMPI.B    #SndFileS,D7       Are we sending a file ?
          BEQ.S     CmdLnP5            Yes, set the display flag
          CMPI.B    #RecFileS,D7       Are we receiving a file ?
          BEQ.S     CmdLnP5            Yes, set the display flag
          CMPI.B    #SndSrvIS,D7       Are we getting a file ?
          BEQ.S     CmdLnP5            Yes, set the display flag
          TST.B     Argumnt2(A6)       No, has a file as-name been specified ?
          BEQ.S     CmdLnP5            No, all is fine
          LEA       ABadUStr(PC),A0    Yes, bad use of the -a option
          BRA       FatalEr            Give message and exit the program

CmdLnP5   TST.B     Local(A6)          Are we running in local mode ?
          BEQ.S     CmdLnP6            No
          ST        Display(A6)        Yes, set the display flag on
CmdLnP6   TST.B     TermOut(A6)        Are we outputting to the terminal ?
          BEQ.S     CmdLnP7            No
          SF        Display(A6)        Yes, set the display flag off

CmdLnP7   TST.B     Quiet(A6)          Has quiet been requested ?
          BEQ.S     CmdLnP8            No
          SF        Display(A6)        Yes, set the display flag off

          TST.B     D5                 Is the connect before flag on ?
          BEQ.S     CmdLnP8            No
          BSR       DoCONN             Yes, connect to the remote host

CmdLnP8   TST.B     D7                 We must invoke the protocol switcher ?
          BLT.S     CmdLnP10           No, let's return
          BSR       TrnsInit           Yes, initialize any protocol thing
          BSR       KPSwtch            Enter the protocol switcher

          TST.B     D6                 Is the connect after flag on ?
          BEQ.S     CmdLnP9            No, return the cc from the automaton
          BSR       DoCONN             Yes, connect to the remote host
          ST        D0                 Return a positive completion code
CmdLnP9   BRA       SysExod

CmdLnP10  RTS

********************************** DoCmLA *****************************
*                                                                     *
*  Handle command line arguments.                                     *
*                                                                     *
*         Entry conditions : A4.L pointer to a null terminated        *
*                                 string containing the command line  *
*                                 argument(s)                         *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
DoCmLA    TST.B     (A4)               Null option ?
          BEQ.S     DoCmLA4            Yes, give an error message
DoCmLA1   MOVE.B    (A4)+,D0           Get the option letter
          BNE.S     DoCmLA2            Not null, handle it
          RTS                          End of option bundling, return

DoCmLA2   SUBI.B    #97,D0             Map the option letter from zero on
          CMPI.B    #22,D0             Above 'w' ?
          BHI       DoCmLA4            Yes, error
          EXT.W     D0                 No, extend to word size
          ADD.W     D0,D0              Scale by a factor of two
          MOVE.W    DoCmLA3(PC,D0.W),D0 Load service routine relative address
          JMP       DoCmLA3(PC,D0.W)   Jump to the option service routine

DoCmLA3   DC.W      DoCmLA16-DoCmLA3   -a option, file as-name
          DC.W      DoCmLA14-DoCmLA3   -b option, line baud rate
          DC.W      DoCmLA25-DoCmLA3   -c command, connect before
          DC.W      DoCmLA4-DoCmLA3    -d invalid
          DC.W      DoCmLA4-DoCmLA3    -e invalid
          DC.W      DoCmLA24-DoCmLA3   -f option, finish remote server
          DC.W      DoCmLA23-DoCmLA3   -g command, get file(s) from server
          DC.W      DoCmLA18-DoCmLA3   -h request, give usage informations
          DC.W      DoCmLA7-DoCmLA3    -i option, treate files as binary
          DC.W      DoCmLA4-DoCmLA3    -j invalid
          DC.W      DoCmLA20-DoCmLA3   -k command, receive file(s) to terminal
          DC.W      DoCmLA11-DoCmLA3   -l option, set communication line
          DC.W      DoCmLA4-DoCmLA3    -m invalid
          DC.W      DoCmLA4-DoCmLA26   -n command, connect after
          DC.W      DoCmLA4-DoCmLA3    -o invalid
          DC.W      DoCmLA15-DoCmLA3   -p option, communication line parity
          DC.W      DoCmLA9-DoCmLA3    -q option, be quiet
          DC.W      DoCmLA19-DoCmLA3   -r command, receive file(s)
          DC.W      DoCmLA21-DoCmLA3   -s command, send file(s)
          DC.W      DoCmLA10-DoCmLA3   -t option, line turnaround handshake
          DC.W      DoCmLA4-DoCmLA3    -u invalid
          DC.W      DoCmLA4-DoCmLA3    -v invalid
          DC.W      DoCmLA8-DoCmLA3    -w option, file collisions warnings

DoCmLA4   LEA       InvArStr(PC),A0    No, invalid argument, fatal error
          BRA       FatalEr
DoCmLA5   LEA       InvABStr(PC),A0    Invalid argument bundling, fatal error
          BRA       FatalEr
DoCmLA6   LEA       CnfAcStr(PC),A0    Conflicting commands, fatal error
          BRA       FatalEr

*** -i image option ***

DoCmLA7   ST        Binary(A6)         Treat files as binary
          BRA       DoCmLA1            See if options are bundled

*** -w warning option ***

DoCmLA8   ST        Warning(A6)        Give file collisions warnings
          BRA       DoCmLA1            See if options are bundled

*** -q quiet option ***

DoCmLA9   ST        Quiet(A6)          Yes, be quiet during file transfers
          BRA       DoCmLA1            See if options are bundled

*** -t line turnaround option ***

DoCmLA10  ST        Duplex(A6)         Set half duplex on
          SF        Flow(A6)           Set flow control off
          ST        TurnFlag(A6)       Set line turnaround handshake on
          MOVE.B    Asc_DC1,TurnChar(A6) Set XON as the turnaround character
          BRA       DoCmLA1            See if options are bundled

*** -l set line option ***

DoCmLA11  TST.B     (A4)               Invalid argument bundling ?
          BNE.S     DoCmLA5            Yes, error

          LEA       DataBuf(A6),A0     No, put here the line name
          BSR       ParsWrd            Get the line name, if any
          TST.B     D0                 Has the line name been specified ?
          BLT.S     DoCmLA12           No, error

          LEA       DataBuf(A6),A0     Reload pointer to the parsed line name
          MOVEQ     #RdWrOp,D0         Try to open the new line
          MOVEQ     #HostLine,D1       This is the channel number
          BSR       FilOpen            Open, if possible
          TST.B     D0                 Ok ?
          BEQ.S     DoCmLA13           No, give an error message

          LEA       LineName(A6),A1    This is the line name string
          EXG       A0,A1              Adjust pointers
          MOVEQ     #LinNamML,D0       Maximum line name length
          BSR       CopyStr            Copy now

          LEA       ConLinNm(PC),A1    Point to the console line name
          BSR       CompStr            Compare the two line names
          TST.B     D0                 Are equal ?
          SEQ       Local(A6)          If not we are local, remote otherwise
          BEQ       DoCmLA1            If local, leave speed unchanged
          MOVE.L    #-1,Speed(A6)      If remote, say speed unknown
          RTS

DoCmLA12  LEA       MisLNStr(PC),A0    Give missing line name error
          BRA       FatalEr
DoCmLA13  LEA       UnOpLStr(PC),A0    Give unable to open line error
          BRA       FatalEr

*** -b set line baud rate option ***

DoCmLA14  TST.B     (A4)               Invalid argument bundling ?
          BNE       DoCmLA5            Yes, error
          MOVEQ     #50,D1             Valid range lower bound
          MOVE.L    #19200,D2          Valid range upper bound
          BSR       ParsNm             Try to get a valid number specification
          TST.B     D1                 Valid number on input ?
          BLT       FatalEr1           No, fatal error
          BSR       ChkBaud            Check if requested speed is supported
          TST.B     D1                 Ok ?
          BEQ       FatalEr1           No, fatal error
          MOVE.L    D0,Speed(A6)       Yes, set the baud rate variable
          MOVE.L    D0,D2              Pass baud rate to ChanCtrl
          MOVEQ     #HostLine,D1       Pass channel number to ChanCtrl
          MOVEQ     #SetBaud,D0        Pass request code to ChanCtrl
          BSR       ChanCtrl           Physically set the host line baud rate
          RTS

*** -p set parity option ***

DoCmLA15  TST.B     (A4)               Invalid argument bundling ?
          BNE       DoCmLA5            Yes, error
          LEA       ParTable(PC),A1    No, point to the parity keywords table
          ST        D1                 This keyword is mandatory
          BSR       ParsKyW            Look for a valid parity specification
          TST.B     D0                 Ok ?
          BLT       FatalEr1           No, fatal error
          MOVE.B    D0,Parity(A6)      Yes, set parity to the requested value
          RTS

*** -a file as-name option ***

DoCmLA16  TST.B     (A4)               Invalid argument bundling ?
          BNE       DoCmLA5            Yes, error
          LEA       Argumnt2(A6),A0    No, put here the file as-name
          BSR       ParsWrd            Get the file as-name, if any
          TST.B     D0                 Has it been specified ?
          BLT.S     DoCmLA17           No, error
          RTS

DoCmLA17  LEA       MsFlNStr(PC),A0    Give missing file name error message
          BSR       FatalEr

*** -h help request ***

DoCmLA18  LEA       UsageStr(PC),A0    Point to the usage string
          BSR       ConWrite           Write it to the terminal
          BRA       DoCmLA1            See if options are bundled

*** -r receive command ***

DoCmLA19  TST.B     D7                 Conflicting commands ?
          BGE       DoCmLA6            Yes, error
          MOVEQ     #RecInitS,D7       Start state for the protocol automaton
          BRA       DoCmLA1            See if options are bundled

*** -k receive to terminal command ***

DoCmLA20  TST.B     D7                 Conflicting commands ?
          BGE       DoCmLA6            Yes, error
          ST        TermOut(A6)        We want output to the terminal line
          MOVEQ     #RecInitS,D7       Start state for the protocol automaton
          BRA       DoCmLA1            See if options are bundled

*** -s send command ***

DoCmLA21  TST.B     D7                 Conflicting commands ?
          BGE       DoCmLA6            Yes, error
          TST.B     (A4)               Invalid argument bundling ?
          BNE       DoCmLA5            Yes, error
          LEA       Argumnt1(A6),A0    Point to file name string
          BSR       ParsInF            Try to get a valid input file name
          TST.B     D0                 Some error ?
          BLT.S     DoCmLA22           Yes
          MOVEQ     #SndInitS,D7       No, Send-Init is the start state
          RTS
DoCmLA22  CMPI.B    #-3,D0             Has a file name been specified ?
          BEQ.S     DoCmLA17           No, give missing file name message
          RTS                          Yes, message already given, return

*** -g get command ***

DoCmLA23  TST.B     D7                 Conflicting commands ?
          BGE       DoCmLA6            Yes, error
          TST.B     (A4)               Invalid argument bundling ?
          BNE       DoCmLA5            Yes, error
          LEA       Argumnt1(A6),A0    Point to file name string
          BSR       ParsWrd            Try to get a file name
          TST.B     D0                 Missing file name ?
          BLT.S     DoCmLA17           Yes, give error message
          MOVE.B    #'R',ServrCmd(A6)  Get command
          MOVEQ     #SndSrvIS,D7       Send-Server-Init is the start state
          RTS

*** -f finish command ***

DoCmLA24  TST.B     D7                 Conflicting commands ?
          BGE       DoCmLA6            Yes, error
          SUBA.L    A2,A2              No arguments for SetGCmd
          MOVEQ     #'F',D0            Finish server command
          BSR       SetGCmd            Set up for generic commands
          MOVEQ     #SndGCmdS,D7
          BRA       DoCmLA1            See if options are bundled

*** -c connect before ***

DoCmLA25  ST        D5                 Set the connect before flag on
          BRA       DoCmLA1            See if options are bundled

*** -n connect after ***

DoCmLA26  ST        D6                 Set the connect after flag on
          BRA       DoCmLA1            See if options are bundled

FatalEr   BSR       ConWrite           Write the message
FatalEr1  SF        D0                 Set a bad completion code
          BRA       SysExod            Return it to system

          ends
          END
<<< k6ocmd.asm >>>
          nam       Kermit68K
          ttl       Top-level commands subroutines module

*         Kermit68K: source file K68CMD
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68Commands,0,0,Edition,0,0

********************************** Parser *****************************ok
*                                                                     *
*  Kermit68K interactive command parser.                              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.B destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
Parser:   LEA       VersStr(PC),A0     Give version informations
          BSR       ConWrite

Parser1   TST.B     IntMacro(A6)       Are we interpreting a macro ?
          BEQ.S     Parser2            No, see if we are interpreting a file
          BSR       McCmdIn            Yes, get the next line of the macro
          TST.B     D0                 End of macro ?
          BNE.S     Parser4            No, join the common part
          SF        IntMacro(A6)       Yes, we're no longer interpreting a macro

Parser2   MOVE.B    TakLevel(A6),D1    Are we interpreting a take file ?
          BLT.S     Parser3            No, get a command from terminal
          ADD.B     #TakeFil0,D1       Yes, compute its channel number
          BSR       FlCmdIn            Get a command line from file
          TST.B     D0                 End of file ?
          BNE.S     Parser4            No, join the common part
          MOVE.B    TakLevel(A6),D1    Yes, compute the file channel number
          ADD.B     #TakeFil0,D1       Add this offset
          BSR       FilClose           Close it
          SUBQ.B    #1,TakLevel(A6)    Continue with outer take file, if any
          BRA.S     Parser1

Parser3   LEA       Prompt(A6),A0      Point to the prompt string
          BSR       ConWrite           Write it
          BSR       CCmdIn             Input a command line
          TST.B     D0                 EOF ?
          SEQ       Done(A6)           Set the termination flag accordingly
          BSR       NewLine            Start a new line

Parser4   SF        Display(A6)        Turn off the display flag
          LEA       CmdBuf(A6),A0      Command to parse is here
          BSR       DoCommd            Parse command and execute it
          TST.B     Done(A6)           Done ?
          BEQ.S     Parser1            No, stay in loop
          RTS                          Yes, return to main

********************************** DoCommd ****************************ok
*                                                                     *
*  Main switcher for commands execution.                              *
*                                                                     *
*         Entry conditions : A0.L points to the command line          *
*                                                                     *
*         Exit  conditions : D1.B destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
DoCommd   MOVEA.L   A0,A5              This is the pointer to command line
          TST.B     IntMacro(A6)       Are we interpreting a macro ?
          BNE.S     DoCommd6           Yes, don't search in macro table
          MOVE.L    A5,-(A7)           No, save the pointer to command line
          LEA       Argumnt1(A6),A0    Put here the command verb, if any
          BSR       ParsWrd            Try to get the command verb
          TST.B     D0                 Success ?
          BLT.S     DoCommd2           No, return
          LEA       Argumnt1(A6),A0    Yes, here is the macro name to find
          BSR       MacFind            Search this name in macro table
          TST.B     D0                 Found ?
          BEQ.S     DoCommd4           No, search in command table
DoCommd1  TST.B     (A0)+              Yes, skip the macro name
          BNE.S     DoCommd1           Loop until end of macro name
          MOVE.L    A0,MacroPnt(A6)    Setup this pointer for reading the macro
          ST        IntMacro(A6)       NOW we are intepreting a macro !
DoCommd2  ADDQ.L    #4,A7              Remove the line pointer from stack
DoCommd3  RTS

DoCommd4  MOVE.L    (A7)+,A5           Restore the pointer to command line
DoCommd6  LEA       CmdTable(PC),A1    Pointer to command table
          SF        D1                 The command verb is not mandatory
          BSR       ParsKyW            Look for a valid command verb
          TST.B     D0                 Ok ?
          BLT.S     DoCommd3           No, return
          LEA       DoCmdTab(PC),A1    Start of jump table
          BRA       IndxJump           Jump to appropriate command handler

*** Code for top level commands execution ***

ChkLocl:  TST.B     Local(A6)          Are we running in local mode ?
          BNE.S     ChkLocl1           Yes, all ok
          LEA       StLnFStr(PC),A0    No, load pointer to the error message
          BSR       ConWrite           Give error message
          ADDQ.L    #4,A7              Remove caller's return address
ChkLocl1  RTS

DoBYE:    BSR       ChkLocl            Check mode
          SUBA.L    A2,A2              No arguments for SetGCmd
          MOVEQ     #'L',D0            Logout command
          BSR       SetGCmd            Setup for generic commands
          MOVEQ     #SndGCmdS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** % command (Treat the rest of the line as a comment) ***

DoCOMMNT: LEA       DataBuf(A6),A0     Pointer to temporary buffer
          BSR       ParsWrd            Get a word from the command line
          TST.B     D0                 End of line ?
          BGE.S     DoCOMMNT           No, continue
          RTS                          Yes, return

*** CONNECT command ***

DoCONN:   BSR       ChkLocl            Check mode
          TST.L     Speed(A6)          Is line speed setted ?
          BGT.S     DoCONN1            Yes, continue
          LEA       StSpeStr(PC),A0    No, give error message and return
          BSR       ConWrite
          RTS

DoCONN1   LEA       ConnStr1(PC),A0    Yes, give the start of connection message
          BSR       ConWrite
          LEA       LineName(A6),A0    Write the line name
          BSR       ConWrite

          LEA       ConnStr3(PC),A0    Line speed
          BSR       ConWrite
          MOVE.L    Speed(A6),D0       Load speed
          BSR       TypeUNum           Write the baud rate

          LEA       ConnStr5(PC),A0    Escape character
          BSR       ConWrite
          MOVE.B    Escape(A6),D0      Get the escape character
          CMPI.B    #' ',D0            Printable character ?
          BGE.S     DoCONN3            Yes, print it out
          ADDI.B    #64,D0             Make it printable
          MOVEQ     #'^',D2            Prefix character for control
          EXG       D0,D2              Exchange
          BSR       ConOut             Output prefix
          EXG       D0,D2              Exchange
DoCONN3   BSR       ConOut             Output character
          MOVEQ     #' ',D0            Write a blank
          BSR       ConOut
          MOVEQ     #'(',D0            Write an open parenthesis
          BSR       ConOut
          MOVEQ     #0,D0              Write the ASCII code of the escape char
          MOVE.B    Escape(A6),D0
          BSR       TypeUNum
          LEA       ConnStr6(PC),A0    Close the parenthesis and give some info
          BSR       ConWrite

          MOVEQ     #TextMode,D0       Put line in text mode
          MOVEQ     #HostLine,D1
          BSR       ChanCtrl
          CMPI.B    #AllOk,D0          All ok ?
          BEQ.S     DoCONN4            Yes, enter the connect loop
          LEA       CCndLStr(PC),A0    No, point to the error message
          BSR       ConWrite           Write it on the screen
          RTS

DoCONN4   MOVEQ     #Terminal,D1       Try to get a character from terminal
          BSR       InpChar
          TST.B     D1                 Character received ?
          BNE       DoCONN14           No, look at the host line
          CMP.B     Escape(A6),D0      Escape character ?
          BNE       DoCONN13           No
          BSR       ConInp             Get a single character command
          MOVE.B    D0,D3              Uppercase it
          BSR       UppCase
          CMPI.B    #'C',D3            Close command ?
          BEQ       DoCONN12           Yes
          CMPI.B    #'?',D3            Help command ?
          BNE.S     DoCONN5            No
          LEA       ConnStr8(PC),A0    Yes, give the help message
          BSR       ConWrite
          BRA       DoCONN14
DoCONN5   CMPI.B    #'0',D3            Send null command ?
          BNE.S     DoCONN6            No
          MOVEQ     #0,D0              Yes, obey it
          BSR       HostOut
          BRA.S     DoCONN14
DoCONN6   CMPI.B    #'B',D3            Send break command ?
          BNE.S     DoCONN7
          MOVEQ     #SndBreak,D0       Request code
          MOVEQ     #HostLine,D1       Logical channel number
          BSR       ChanCtrl           Call the channel control routine
          BRA.S     DoCONN14
DoCONN7   CMPI.B    #'S',D3            Show status command ?
          BNE.S     DoCONN9            No
          LEA       ConnStr2(PC),A0    Yes, show the communication status
          BSR       ConWrite
          LEA       LineName(A6),A0    Write the line name
          BSR       ConWrite
          LEA       ConnStr3(PC),A0    Write the line speed
          BSR       ConWrite
          MOVE.L    Speed(A6),D0       Load speed
          BSR       TypeUNum           Write the baud rate
          BSR       NewLine            Start a new line
          BRA.S     DoCONN14
DoCONN9   CMPI.B    #'H',D3            Hangup and close command ?
          BNE.S     DoCONN10           No
*
*         Place code for hangup here
*
          BRA.S     DoCONN12           Close the connection
DoCONN10  CMP.B     Escape(A6),D3      Escape character again ?
          BNE.S     DoCONN11           No
          MOVE.B    Escape(A6),D0      Yes, send it
          BSR       HostOut
          BRA.S     DoCONN14
DoCONN11  MOVEQ     #Asc_Bel,D0        Invalid command, ring bell
          BSR       ConOut
          BRA.S     DoCONN14
DoCONN12  LEA       ConnStr7(PC),A0    Yes, give the end of connection message
          BSR       ConWrite
          RTS                          Exit from transparent mode

DoCONN13  BSR       HostOut            Output the character just received
          TST.B     Duplex(A6)         Half duplex ?
          BEQ.S     DoCONN14           No
          BSR       ConOut             Yes, echo the character to the terminal
DoCONN14  MOVEQ     #HostLine,D1       Try to get a character from host
          BSR       InpChar
          TST.B     D1                 Character received ?
          BNE       DoCONN4            No, look at the terminal line
          BSR       HndlPar            Yes, handle the parity bit
          BSR       ConOut             Output the character just received
          BRA       DoCONN4

*** (Local) COPY command ***

DoCOPY:   LEA       Argumnt1(A6),A0    Source file specification
          BSR       ParsWrd            Get it, if any
          LEA       Argumnt2(A6),A0    Target file specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass arguments addresses ...
          LEA       Argumnt2(A6),A1    ... to the System subroutine
          MOVEQ     #CopyFile,D0       Copy file system function wanted
          BSR       System             Call the external handler
          LEA       NoCopStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** (Local) CWD command ***

DoCWD:    LEA       Argumnt1(A6),A0    Directory specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #ChangDir,D0       Change working directory function
          BSR       System             Call the external handler
          LEA       NoCWDStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** DEFINE command ***

DoDEFN:   TST.B     IntMacro(A6)       Are we interpreting from a macro ?
          BNE       DoDEFN11           Yes, error
          LEA       Argumnt1(A6),A0    Put here the macro name, if any
          BSR       ParsWrd            Try to get it
          TST.B     D0                 Success ?
          BLT       DoLIST3            No, notify that macro name is missing
          LEA       Argumnt1(A6),A0    Yes, point to the parsed macro name
          BSR       MacFind            Check if this macro is already defined
          TST.B     D0                 Found ?
          BEQ.S     DoDEFN4            No, create it
*                                      Yes, erase it from macro table
DoDEFN1   MOVEA.L   A0,A1              Macro definition start address
          BSR       MacSkip            Skip to end of macro body
          TST.B     D0                 It was the last one ?
          BNE.S     DoDEFN3            Yes, simply adjust pointer to table end
          MOVE.L    MTNxtChF(A6),D0    No, load address of the next byte free
DoDEFN2   MOVE.B    (A1)+,(A0)+        Shift the macro table
          CMP.L     A1,D0              At end of macro table ?
          BNE.S     DoDEFN2            No, stay in loop
DoDEFN3   MOVE.L    A0,MTNxtChF(A6)    Next byte free in macro table is here

DoDEFN4   LEA       Argumnt1(A6),A1    Point to the parsed macro name
DoDEFN5   MOVE.B    (A1)+,(A0)+        Store the macro name in macro table
          BNE.S     DoDEFN5            Loop until end of macro name
          BSR       ParsTxt            Try to get a one-line macro body
          TST.B     D0                 Success ?
          BLT.S     DoDEFN6            No, it's a multi-line macro
          ADDQ.L    #1,A0              Yes, skip the termination null
          BRA.S     DoDEFN10           Adjust the end pointer and return

DoDEFN6   MOVE.L    A0,-(A7)           Save the pointer to the macro table

          MOVE.B    TakLevel(A6),D1    Are we defining from a take file ?
          BLT.S     DoDEFN7            No, get next macro line from terminal
          ADD.B     #TakeFil0,D1       Yes, compute its channel number
          BSR       FlCmdIn            Get the next macro line from file
          TST.B     D0                 End of file ?
          BEQ.S     DoDEFN9            Yes, end of macro body
          SF        D2                 No, set the termination flag to false
          BNE.S     DoDEFN8            Join the common part

DoDEFN7   BSR       CCmdIn             Get another line of text from terminal
          TST.B     D0                 EOF on input ?
          SEQ       D2                 Set the termination flag accordingly
          BSR       NewLine            Start a new line on the terminal

DoDEFN8   LEA       CmdBuf(A6),A5      The macro line is here
          MOVE.L    (A7)+,A0           Restore the pointer to the macro table
          BSR       ParsTxt            Try to get it into the macro table
          MOVE.B    #Asc_CR,(A0)+      Terminate the line whit a CR
          TST.B     D0                 The line was null ?
          BLT.S     DoDEFN9            Yes, this is an end condition
          TST.B     D2                 Is the termination flag true ?
          BEQ.S     DoDEFN6            No, continue entering macro lines
DoDEFN9   CLR.B     -1(A0)             Null terminate the macro body
DoDEFN10  MOVE.L    A0,MTNxtChF(A6)    Update next byte free in macro table
          RTS

DoDEFN11  SUBA.L    A0,A0              No guilty
          LEA       MNstAStr(PC),A1    Error message, can't nest macros
          BSR       ParsErr            Write it
          RTS

*** (Local) DELETE command ***

DoDELETE: LEA       Argumnt1(A6),A0    File to delete specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #DeletFil,D0       Delete file function wanted
          BSR       System             Call the external handler
          LEA       NoDelStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** (Local) DIRECTORY command ***

DoDIR:    LEA       Argumnt1(A6),A0    File or directory specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #Directry,D0       Directory function wanted
          BSR       System             Call the external handler
          LEA       NoDirStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** ECHO command ***

DoECHO:   LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Pass it to ParsTxt
          BSR       ParsTxt            Get a text string from the command line
          TST.B     D0                 Ok ?
          BLT.S     DoECHO1            No, return
          MOVEA.L   A1,A0              Reload pointer
          BSR       ConWrite           Write the string to the terminal line
          BSR       NewLine            Start a new line
DoECHO1   RTS

*** EXIT command ***

DoEXIT:   ST        Done(A6)           Set the termination flag
          RTS

*** FINISH command ***

DoFINISH: BSR       ChkLocl            Check mode
          SUBA.L    A2,A2              No arguments for SetGCmd
          MOVEQ     #'F',D0            Finish server command
          BSR       SetGCmd            Set up for generic commands
          MOVEQ     #SndGCmdS,D7
          BSR       KPSwtch            Enter the protocol automaton switcher
          RTS

*** GET command ***

DoGET:    BSR       ChkLocl            Check mode
          LEA       Argumnt1(A6),A0    Point to file name string
          BSR       ParsWrd            Try to get a file name
          TST.B     D0                 Missing file name ?
          BLT.S     DoGET1             Yes, give error message
          LEA       Argumnt2(A6),A0    Point to file as-name string
          BSR       ParsOuF            Look for a valid output file name
          LEA       CmdBuf(A6),A0      Put here the file name
          LEA       Argumnt1(A6),A1    Copy from here
          MOVEQ     #CmdBufLn,D0       Buffers length
          BSR       CopyStr            Copy now
          TST.B     Local(A6)          Are we in local mode ?
          SNE       Display(A6)        Set transaction display flag accordingly
          BSR       TrnsInit           Initialize transaction related variables
          MOVE.B    #'R',ServrCmd(A6)  Get command
          MOVEQ     #SndSrvIS,D7       Send-Server-Init is the start state
          BSR       KPSwtch            Enter protocol switcher
          RTS
DoGET1    SUBA.L    A0,A0              No guilty
          LEA       MsFSpStr(PC),A1    Point to error message
          BSR       ParsErr            Write it
          RTS

*** HELP command ***

ScrnMxLL  EQU       78
ColumnLn  EQU       12

DoHELP:   LEA       KerCmStr(PC),A0    Write introduction to Kermit68K commands
          BSR       ConWrite
          LEA       CmdTable(PC),A0    Point to top-level commands table start
          CLR.B     D2                 Initialize the line length counter
DoHELP1   MOVE.B    (A0)+,D0           Get a character from command table
          CMP.B     #-1,D0             End of table ?
          BEQ.S     DoHELP2            Yes, now write macro names
          BSR.S     DoHELP5            No, write the command name
          BRA.S     DoHELP1            Loop until end of table

DoHELP2   BSR       NewLine            Start a new line on the screen
          CLR.B     D2                 Re-initialize the line length counter
          LEA       MacroTbl(A6),A1    Load start address of macro table
          CMPA.L    MTNxtChF(A6),A1    The macro table is empty ?
          BEQ.S     DoHELP4            Yes, notify this and return
          LEA       MacCmStr(PC),A0    No, write introduction to user macros
          BSR       ConWrite
DoHELP3   MOVEA.L   A1,A0              Now A0 points to tha macro name
          BSR.S     DoHELP5            Write the macro name
          BSR       MacSkip            Skip to next macro name
          TST.B     D0                 The previous was the last macro ?
          BEQ.S     DoHELP3            No, so write this one
          BSR       NewLine            Yes, start a new line and return
          RTS

DoHELP4   LEA       NoMacStr(PC),A0    Say that there are no user macros
          BSR       ConWrite
          RTS

DoHELP5   MOVEQ     #ColumnLn,D3       Initialize the column length counter
DoHELP6   MOVE.B    (A0)+,D0           Get a character from the source string
          BEQ.S     DoHELP7            End of name, write separators
          BSR       ConOut             Output this character
          ADDQ.B    #1,D2              Count it
          SUBQ.B    #1,D3              Decrement the column length counter
          BEQ.S     DoHELP5            If zero reload it
          BRA.S     DoHELP6            Loop until end of name

DoHELP7   CMPI.B    #ScrnMxLL-ColumnLn,D2 There is room for another column ?
          BGT.S     DoHELP9            No, start a new line on the screen
          MOVEQ     #' ',D0            Yes, let's pad the column with blanks
DoHELP8   BSR       ConOut             Write one blank
          ADDQ.B    #1,D2              Count it
          SUBQ.B    #1,D3              At end of column ?
          BNE.S     DoHELP8            No, repeat
          RTS
DoHELP9   BSR       NewLine            Start a new line on the terminal screen
          CLR.B     D2                 Re-initialize the line length counter
          RTS

*** LIST command ***

DoLIST:   LEA       Argumnt1(A6),A0    Put here the macro name, if any
          BSR       ParsWrd            Try to get the macro name
          TST.B     D0                 Success ?
          BLT.S     DoLIST3            No, give error and return
          LEA       Argumnt1(A6),A0    Yes, point to the parsed macro name
          BSR       MacFind            Search it in the macro table
          TST.B     D0                 Found ?
          BEQ.S     DoLIST4            No, give error and return
DoLIST0   TST.B     (A0)+              Skip the macro name
          BNE.S     DoLIST0
DoLIST1   MOVE.B    (A0)+,D0           Type the macro body, get a character
          BEQ.S     DoLIST2            End of macro body, exit
          BSR       ConOut             Output the character just read
          CMPI.B    #Asc_CR,D0         It was a carriage return ?
          BNE.S     DoLIST1            No, continue
          MOVEQ     #Asc_LF,D0         Yes, output a line feed
          BSR       ConOut
          BRA.S     DoLIST1            Stay in loop
DoLIST2   BSR       NewLine            Start a new line on the terminal
          RTS
DoLIST3   SUBA.L    A0,A0              No guilty
          LEA       MsMcNStr(PC),A1    Error message, missing macro name
          BSR       ParsErr            Write it
          RTS
DoLIST4   LEA       Argumnt1(A6),A0    Here is the guilty word
          LEA       UnkMcStr(PC),A1    Error message, macro not found
          BSR       ParsErr            Write it
          RTS

*** PRINT command ***

DoPRINT:  LEA       Argumnt1(A6),A0    File to print specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #PrntFile,D0       Print file function wanted
          BSR       System             Call the external handler
          LEA       NoPriStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** RECEIVE command ***

DoRECVE:  LEA       Argumnt2(A6),A0    Point to file as-name string
          BSR       ParsOuF            Look for a valid output file name
          TST.B     D0                 Ok ?
          BGE.S     DoRECVE1           Yes, file must be stored under this name
          CMPI.B    #-3,D0             Missing file specification ?
          BEQ.S     DoRECVE1           Yes, no problem
          RTS                          No, some other error, return
DoRECVE1  TST.B     Local(A6)          Are we in local mode ?
          SNE       Display(A6)        Set transaction display flag accordingly
          BSR       TrnsInit           Setup transaction related variables
          MOVEQ     #RecInitS,D7       Receive-Init is the start state
          BSR       KPSwtch            Enter protocol switcher
          RTS

*** RENAME command ***

DoRENAME: LEA       Argumnt1(A6),A0    Old file name specification
          BSR       ParsWrd            Get it, if any
          LEA       Argumnt2(A6),A0    New file name specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass arguments addresses ...
          LEA       Argumnt2(A6),A1    ... to the System subroutine
          MOVEQ     #RenamFil,D0       Rename file function wanted
          BSR       System             Call the external handler
          LEA       NoRenStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** SEND command ***

DoSEND:   LEA       Argumnt1(A6),A0    Point to file name string
          BSR       ParsInF            Try to get a valid input file name
          TST.B     D0                 Some error ?
          BLT.S     DoSEND1            Yes, handle it
          LEA       Argumnt2(A6),A0    Point to file as-name string
          BSR       ParsTxt            Try to get an as name for this file
          TST.B     Local(A6)          Are we in local mode ?
          SNE       Display(A6)        Set transaction display flag accordingly
          BSR       TrnsInit           Initialize transaction related variables
          MOVEQ     #SndInitS,D7       Send-Init is the start state
          BSR       KPSwtch            Enter protocol switcher
          RTS
DoSEND1   CMPI.B    #-3,D0             Missing file specification ?
          BNE.S     DoSEND2            No, error already given
          SUBA.L    A0,A0              No guilty
          LEA       MsFSpStr(PC),A1    Point to error message
          BSR       ParsErr            Write it
DoSEND2   RTS

*** (Local) SPACE command ***

DoSPACE:  LEA       Argumnt1(A6),A0    Directory or device specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #SpacInfo,D0       Disk usage query function wanted
          BSR       System             Call the external handler
          LEA       NoSpaStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** STATISTICS command ***

DoSTATS:  LEA       StatStr1(PC),A0    Header line and characters sent string
          MOVE.L    ChrsSent(A6),D6    Characters sent this transaction
          MOVE.L    TChsSent(A6),D7    Total characters sent
          BSR.S     DoSTATS1           Display this
          LEA       StatStr2(PC),A0    Data characters sent string
          MOVE.L    DChsSent(A6),D6    Data characters sent this transaction
          MOVE.L    TDChSent(A6),D7    Total data characters sent
          BSR.S     DoSTATS1           Display this
          LEA       StatStr3(PC),A0    NAKs received string
          MOVE.L    NAKsRecd(A6),D6    NAKs received this transaction
          MOVE.L    TNAKRecd(A6),D7    Total NAKs received
          BSR.S     DoSTATS1           Display this
          LEA       StatStr4(PC),A0    Packets sent string
          MOVE.L    PcksSent(A6),D6    Packets sent this transaction
          MOVE.L    TPckSent(A6),D7    Total packets sent
          BSR.S     DoSTATS1           Display this
          LEA       StatStr5(PC),A0    Characters received string
          MOVE.L    ChrsRecd(A6),D6    Characters received this transaction
          MOVE.L    TChsRecd(A6),D7    Total characters received
          BSR.S     DoSTATS1           Display this
          LEA       StatStr6(PC),A0    Data characters received string
          MOVE.L    DChsRecd(A6),D6    Data characters received this transaction
          MOVE.L    TDChRecd(A6),D7    Total data characters received
          BSR.S     DoSTATS1           Display this
          LEA       StatStr7(PC),A0    NAKs received string
          MOVE.L    NAKsSent(A6),D6    NAKs sent this transaction
          MOVE.L    TNAKSent(A6),D7    Total NAKs sent
          BSR.S     DoSTATS1           Display this
          LEA       StatStr8(PC),A0    Packets received string
          MOVE.L    PcksRecd(A6),D6    Packets received this transaction
          MOVE.L    TPckRecd(A6),D7    Total packets received
          BSR.S     DoSTATS1           Display this
          RTS

DoSTATS1  BSR       ConWrite           Write the string
          MOVE.L    D6,D0              Total for last transaction
          BSR.S     DoSTATS2           Write number
          MOVE.L    D7,D0              Total since start of Krmit68K
          BSR.S     DoSTATS2           Write number
          BSR       NewLine            Start a new line
          RTS

DoSTATS2  SF        D1                 Unsigned conversion wanted
          MOVEQ     #12,D2             Field length
          MOVEQ     #10,D3             Base 10
          LEA       DataBuf+34(A6),A0  Point to the end of a temporary buffer
          BSR       IntToAs            Convert the number into a string
          BSR       ConWrite           Write the obtained string
          RTS

*** % command (Forward the rest of line to system command processor) ***

DoSYSCMD: LEA       Argumnt1(A6),A0    Put here the system command
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #SysCommd,D0       System command function wanted
          BSR       System             Call the external handler
          LEA       NoSyCStr(PC),A0    This is the "on failure" error message
          BRA       CSysErr            Check cc and, on failure, give message

*** TAKE command ***

DoTAKE:   CMPI.B    #MaxTakeF,TakLevel(A6) Take level number at our limit ?
          BEQ.S     DoTAKE1            Yes, give error and return

          LEA       Argumnt1(A6),A0    Point to the file name buffer
          BSR       ParsInF            Try to get a valid input file name
          TST.B     D0                 Some error ?
          BLT.S     DoTAKE2            Yes

          BSR       ChkWild            Check the specified file name
          TST.B     D0                 Wildcarded name ?
          BNE.S     DoTAKE4            Yes, give error and return

          MOVE.B    TakLevel(A6),D1    Get the take level number
          ADDQ.B    #1,D1              Increment this temporary variable
          ADD.B     #TakeFil0,D1       Compute the new file channel number

          MOVEQ     #ReadOp,D0         We want open the file for input
          BSR       FilOpen            Open the new take file
*
*         Warning, the cc is not checked !!!
*
          ADDQ.B    #1,TakLevel(A6)    Finally increment the take level
          RTS

DoTAKE1   LEA       TFNDpStr(PC),A1    Say take file nested too deeply
          SUBA.L    A0,A0              No guilty word
          BSR       ParsErr            Call the error messages routine
          RTS

DoTAKE2   CMPI.B    #-3,D0             Has a file name been specified ?
          BNE.S     DoTAKE3            Yes, message already given, return
          LEA       MsFSpStr(PC),A1    Give missing file specification error
          SUBA.L    A0,A0              No guilty word
          BSR       ParsErr            Write the error message
DoTAKE3   RTS

DoTAKE4   LEA       POuFStr1(PC),A1    Give illegal wildcard error message
          BSR       ParsErr            Call the error messages routine
          RTS

*** (Local) TYPE command ***

DoTYPE:   LEA       Argumnt1(A6),A0    File to type specification
          BSR       ParsTxt            Get it, if any
          LEA       Argumnt1(A6),A0    Pass argument address to System
          MOVEQ     #TypeFile,D0       Type file function wanted
          BSR       System             Call the external handler
          LEA       NoTypStr(PC),A0    This is the "on failure" error message
*          BRA       CSysErr            Check cc and, on failure, give message


CSysErr   TST.B     D0                 System operation failed ?
          BNE.S     CSysErr1           No, return
          BSR       ConWrite           Yes, write corresponding error message
          BSR       NewLine            Start a new line
CSysErr1  RTS

          ends
          END
<<< k6octb.asm >>>
          nam       Kermit68K
          ttl       Commands keywords tables module

*         Kermit68K: source file K68CTB
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68CmdTables,0,0,Edition,0,0

* Values associated with top-level commands.

CmdBYE    EQU       0                  BYE
CmdCONCT  EQU       1                  CONNECT
CmdCOPY   EQU       2                  COPY
CmdCWD    EQU       3                  CWD (Change Working Directory)
CmdDEFIN  EQU       4                  DEFINE (a command macro)
CmdDELET  EQU       5                  (Local) DELETE
CmdDIR    EQU       6                  (Local) DIRECTORY
CmdECHO   EQU       7                  ECHO
CmdEXIT   EQU       8                  EXIT
CmdFINSH  EQU       9                  FINISH
CmdGET    EQU      10                  GET
CmdHELP   EQU      11                  HELP
CmdLIST   EQU      12                  LIST
CmdPRINT  EQU      13                  (Local) PRINT
CmdRCEIV  EQU      14                  RECEIVE
CmdREMOT  EQU      15                  REMOTE
CmdRENAM  EQU      16                  (Local) RENAME
CmdSEND   EQU      17                  SEND
CmdSET    EQU      18                  SET
CmdSHOW   EQU      19                  SHOW
CmdSPACE  EQU      20                  (Local) SPACE
CmdSTATS  EQU      21                  STATISTICS
CmdTAKE   EQU      22                  TAKE
CmdTYPE   EQU      23                  (Local) TYPE
CmdCOMMN  EQU      24                  Comment
CmdSYSC   EQU      25                  System command

* Top-level commands string table.

CmdTable: DC.B      CmdBYE,"BYE",Asc_Nul
          DC.B      CmdCONCT,"C",Asc_Nul
          DC.B      CmdCONCT,"CONNECT",Asc_Nul
          DC.B      CmdCOPY,"COPY",Asc_Nul
          DC.B      CmdCWD,"CWD",Asc_Nul
          DC.B      CmdDEFIN,"DEFINE",Asc_Nul
          DC.B      CmdDELET,"DELETE",Asc_Nul
          DC.B      CmdDIR,"DIRECTORY",Asc_Nul
          DC.B      CmdECHO,"ECHO",Asc_Nul
          DC.B      CmdEXIT,"EXIT",Asc_Nul
          DC.B      CmdFINSH,"FINISH",Asc_Nul
          DC.B      CmdGET,"GET",Asc_Nul
          DC.B      CmdHELP,"HELP",Asc_Nul
          DC.B      CmdLIST,"LIST",Asc_Nul
          DC.B      CmdPRINT,"PRINT",Asc_Nul
          DC.B      CmdEXIT,"QUIT",Asc_Nul
          DC.B      CmdRCEIV,"R",Asc_Nul
          DC.B      CmdRCEIV,"RECEIVE",Asc_Nul
          DC.B      CmdREMOT,"REMOTE",Asc_Nul
          DC.B      CmdRENAM,"RENAME",Asc_Nul
          DC.B      CmdSEND,"S",Asc_Nul
          DC.B      CmdSEND,"SEND",Asc_Nul
          DC.B      CmdSET,"SET",Asc_Nul
          DC.B      CmdSHOW,"SHOW",Asc_Nul
          DC.B      CmdSPACE,"SPACE",Asc_Nul
          DC.B      CmdSTATS,"STATISTICS",Asc_Nul
          DC.B      CmdTAKE,"TAKE",Asc_Nul
          DC.B      CmdTYPE,"TYPE",Asc_Nul
          DC.B      CmdCOMMN,"%",Asc_Nul
          DC.B      CmdSYSC,"!",Asc_Nul
          DC.B      -1
          DC.B      "command verb",Asc_Nul

* Top-level commands jump table.

DoCmdTab: DC.W      DoBYE-DoCmdTab     CmdBYE
          DC.W      DoCONN-DoCmdTab    CmdCONCT
          DC.W      DoCOPY-DoCmdTab    CmdCOPY
          DC.W      DoCWD-DoCmdTab     CmdCWD
          DC.W      DoDEFN-DoCmdTab   CmdDEFIN
          DC.W      DoDELETE-DoCmdTab  CmdDELET
          DC.W      DoDIR-DoCmdTab     CmdDIR
          DC.W      DoECHO-DoCmdTab    CmdECHO
          DC.W      DoEXIT-DoCmdTab    CmdEXIT
          DC.W      DoFINISH-DoCmdTab  CmdFINSH
          DC.W      DoGET-DoCmdTab     CmdGET
          DC.W      DoHELP-DoCmdTab    CmdHELP
          DC.W      DoLIST-DoCmdTab    CmdLIST
          DC.W      DoPRINT-DoCmdTab   CmdPRINT
          DC.W      DoRECVE-DoCmdTab   CmdRCEIV
          DC.W      DoREMOT-DoCmdTab   CmdREMOT
          DC.W      DoRENAME-DoCmdTab  CmdRENAM
          DC.W      DoSEND-DoCmdTab    CmdSEND
          DC.W      DoSET-DoCmdTab     CmdSET
          DC.W      DoSHOW-DoCmdTab    CmdSHOW
          DC.W      DoSPACE-DoCmdTab   CmdSPACE
          DC.W      DoSTATS-DoCmdTab   CmdSTATS
          DC.W      DoTAKE-DoCmdTab    CmdTAKE
          DC.W      DoTYPE-DoCmdTab    CmdTYPE
          DC.W      DoCOMMNT-DoCmdTab  CmdCOMMN
          DC.W      DoSYSCMD-DoCmdTab  CmdSYSC

* Values associated with SET command qualifiers.

SetBCHKT  EQU       0                  Block check type
SetDELAY  EQU       1                  Delay
SetDUPLX  EQU       2                  Duplex
SetESCAP  EQU       3                  Escape character
SetFILE   EQU       4                  File Parameters
SetFLOW   EQU       5                  Flow Control
SetHNDSH  EQU       6                  Handshake
SetINCFD  EQU       7                  Incomplete File Disposition
SetLINE   EQU       8                  Communication line to use
SetPRITY  EQU       9                  Parity
SetPRMPT  EQU      10                  Program prompt string
SetRETRY  EQU      11                  Retry limits
SetSPEED  EQU      12                  Line speed (baud rate)
SetSEND   EQU      13                  SEND parameters
SetRCEIV  EQU      14                  RECEIVE parameters

* SET command qualifiers string table.

SETTable: DC.B      SetSPEED,"BAUD",Asc_Nul
          DC.B      SetBCHKT,"BLOCK_CHECK_TYPE",Asc_Nul
          DC.B      SetDELAY,"DELAY",Asc_Nul
          DC.B      SetDUPLX,"DUPLEX",Asc_Nul
          DC.B      SetESCAP,"ESCAPE_CHARACTER",Asc_Nul
          DC.B      SetFILE,"FILE",Asc_Nul
          DC.B      SetFLOW,"FLOW_CONTROL",Asc_Nul
          DC.B      SetHNDSH,"HANDSHAKE",Asc_Nul
          DC.B      SetINCFD,"INCOMPLETE_FILE_DISPOSITION",Asc_Nul
          DC.B      SetLINE,"LINE",Asc_Nul
          DC.B      SetPRITY,"PARITY",Asc_Nul
          DC.B      SetPRMPT,"PROMPT",Asc_Nul
          DC.B      SetRCEIV,"RECEIVE",Asc_Nul
          DC.B      SetRETRY,"RETRY",Asc_Nul
          DC.B      SetSEND,"SEND",Asc_Nul
          DC.B      SetSPEED,"SPEED",Asc_Nul
          DC.B      -1
          DC.B      "SET option or parameter",Asc_Nul

* SET command qualifiers jump table.

DoSetTab: DC.W      DoStBCT-DoSetTab   SetBCHKT
          DC.W      DoStDLAY-DoSetTab  SetDELAY
          DC.W      DoStDUP-DoSetTab   SetDUPLX
          DC.W      DoSetESC-DoSetTab  SetESCAP
          DC.W      DoSFILE-DoSetTab   SetFILE
          DC.W      DoStFLW-DoSetTab   SetFLOW
          DC.W      DoStHND-DoSetTab   SetHNDSH
          DC.W      DoStIFD-DoSetTab   SetINCFD
          DC.W      DoStLIN-DoSetTab   SetLINE
          DC.W      DoStPAR-DoSetTab   SetPRITY
          DC.W      DoStPRM-DoSetTab   SetPRMPT
          DC.W      DoSRTRY-DoSetTab   SetRETRY
          DC.W      DoStSPE-DoSetTab   SetSPEED
          DC.W      DoSSEND-DoSetTab   SetSEND
          DC.W      DoSRECV-DoSetTab   SetRCEIV

* Values associated with SET SEND/RECEIVE parameters.

SetEOL    EQU       0                  End-Of-Line (packet terminator)
SetMARKR  EQU       1                  Start of Packet marker
SetMXPLN  EQU       2                  Maximum packet length to send
SetNPAD   EQU       3                  Amount of padding
SetPDCHR  EQU       4                  Pad character
SetTMOUT  EQU       5                  Timeout interval

* SET SEND/RECEIVE parameters string table.

SSRTable: DC.B      SetEOL,"END_OF_LINE",Asc_Nul
          DC.B      SetMARKR,"MARKER",Asc_Nul
          DC.B      SetMXPLN,"PACKET_LENGTH",Asc_Nul
          DC.B      SetNPAD,"PADDING",Asc_Nul
          DC.B      SetPDCHR,"PAD_CHARACTER",Asc_Nul
          DC.B      SetTMOUT,"TIMEOUT",Asc_Nul
          DC.B      -1
          DC.B      "SET SEND/RECEIVE parameter",Asc_Nul

* SET SEND parameters jump table.

DoSetSTb: DC.W      DoStSEOL-DoSetSTb  SetEOL
          DC.W      DoStSMrk-DoSetSTb  SetMARKR
          DC.W      DoStSMPS-DoSetSTb  SetMXPLN
          DC.W      DoStSPdN-DoSetSTb  SetNPAD
          DC.W      DoStSPdC-DoSetSTb  SetPDCHR
          DC.W      DoStSTIM-DoSetSTb  SetTMOUT

* SET RECEIVE parameters jump table.

DoSetRTb: DC.W      DoStREOL-DoSetRTb  SetEOL
          DC.W      DoStRMrk-DoSetRTb  SetMARKR
          DC.W      DoStRMPS-DoSetRTb  SetMXPLN
          DC.W      DoStRPdN-DoSetRTb  SetNPAD
          DC.W      DoStRPdC-DoSetRTb  SetPDCHR
          DC.W      DoStRTIM-DoSetRTb  SetTMOUT

* Values associated with REMOTE command qualifiers.

RemCOPY   EQU       0                  Copy
RemCWD    EQU       1                  Change Working Directory
RemDELET  EQU       2                  Delete
RemDIR    EQU       3                  Directory
RemHELP   EQU       4                  Help
RemHOST   EQU       5                  Host
RemKRMIT  EQU       6                  Kermit
RemPRINT  EQU       7                  Print
RemRENAM  EQU       8                  Rename
RemSET    EQU       9                  SET
RemSPACE  EQU      10                  Space
RemSUBMT  EQU      11                  Submit
RemTYPE   EQU      12                  Type
RemWHO    EQU      13                  Who

* REMOTE command qualifiers string table.

REMTable: DC.B      RemCOPY,"COPY",Asc_Nul
          DC.B      RemCWD,"CWD",Asc_Nul
          DC.B      RemDELET,"DELETE",Asc_Nul
          DC.B      RemDIR,"DIRECTORY",Asc_Nul
          DC.B      RemHELP,"HELP",Asc_Nul
          DC.B      RemHOST,"HOST",Asc_Nul
          DC.B      RemKRMIT,"KERMIT",Asc_Nul
          DC.B      RemPRINT,"PRINT",Asc_Nul
          DC.B      RemRENAM,"RENAME",Asc_Nul
          DC.B      RemSET,"SET",Asc_Nul
          DC.B      RemSPACE,"SPACE",Asc_Nul
          DC.B      RemSUBMT,"SUBMIT",Asc_Nul
          DC.B      RemTYPE,"TYPE",Asc_Nul
          DC.B      RemWHO,"WHO",Asc_Nul
          DC.B      -1
          DC.B      "REMOTE Kermit server command",Asc_Nul

* REMOTE command qualifiers jump table.

DoRemTab: DC.W      DoRemCOP-DoRemTab  RemCOPY
          DC.W      DoRmCWD-DoRemTab   RemCWD
          DC.W      DoRemDEL-DoRemTab  RemDELET
          DC.W      DoRmDIR-DoRemTab   RemDIR
          DC.W      DoRmHELP-DoRemTab  RemHELP
          DC.W      DoRemHOS-DoRemTab  RemHOST
          DC.W      DoRemKER-DoRemTab  RemKRMIT
          DC.W      DoRemPRI-DoRemTab  RemPRINT
          DC.W      DoRemREN-DoRemTab  RemRENAM
          DC.W      DoRemSET-DoRemTab  RemSET
          DC.W      DoRmSPA-DoRemTab   RemSPACE
          DC.W      DoRemSUB-DoRemTab  RemSUBMT
          DC.W      DoRemTYP-DoRemTab  RemTYPE
          DC.W      DoRmWHO-DoRemTab   RemWHO

* Values associated with SHOW command qualifiers.

ShoPARAM  EQU       0                  Parameters
ShoVERS   EQU       1                  Version

* SHOW command qualifiers table.

SHOWTabl: DC.B      ShoPARAM,"PARAMETERS",Asc_Nul
          DC.B      ShoVERS,"VERSION",Asc_Nul
          DC.B      -1
          DC.B      "SHOW option",Asc_Nul

* SHOW command options jump table.

DoShoTab: DC.W      DoShoP-DoShoTab    ShoPARAM
          DC.W      DoShoVer-DoShoTab  ShoVERS

* Values associated with SET FILE command parameters.

SetFDISP  EQU       0                  File display
SetFNAME  EQU       1                  File naming
SetFTYPE  EQU       2                  File type
SetFWARN  EQU       3                  File warning

* SET FILE command parameters table.

SFILTabl: DC.B      SetFDISP,"DISPLAY",Asc_Nul
          DC.B      SetFNAME,"NAMES",Asc_Nul
          DC.B      SetFTYPE,"TYPE",Asc_Nul
          DC.B      SetFWARN,"WARNING",Asc_Nul
          DC.B      -1
          DC.B      "file parameter",Asc_Nul

* SET FILE command parameters jump table.

DoSFlTab: DC.W      DoStFDs-DoSFlTab   SetFDISP
          DC.W      DoStFNm-DoSFlTab   SetFNAME
          DC.W      DoStFTp-DoSFlTab   SetFTYPE
          DC.W      DoStFWn-DoSFlTab   SetFWARN

* Values associated with SET RETRY command parameters.

SetRtINI  EQU       0                  Set retry initial connection packet
SetRtPAK  EQU       1                  Set retry normal packet

* SET RETRY command parameters table.

SRETTabl: DC.B      SetRtINI,"INITIAL_CONNECTION",Asc_Nul
          DC.B      SetRtPAK,"PACKET",Asc_Nul
          DC.B      -1
          DC.B      "retry parameter",Asc_Nul

* SET RETRY command parameters jump table.

DoSRtTab: DC.W      DoSetRtI-DoSRtTab  SetRtINI
          DC.W      DoSetRtP-DoSRtTab  SetRtPAK

* On/Off specification keyword table.

OnOfTabl: DC.B      0,"FALSE",Asc_Nul
          DC.B      0,"OFF",Asc_Nul
          DC.B      0,"NO",Asc_Nul
          DC.B      0,"0",Asc_Nul
          DC.B      1,"TRUE",Asc_Nul
          DC.B      1,"ON",Asc_Nul
          DC.B      1,"YES",Asc_Nul
          DC.B      1,"1",Asc_Nul
          DC.B      -1
          DC.B      "on/off specification",Asc_Nul

* Block check specification keyword table.

BlCkTabl: DC.B      1,"1",Asc_Nul
          DC.B      1,"ONE",Asc_Nul
          DC.B      2,"2",Asc_Nul
          DC.B      2,"TWO",Asc_Nul
          DC.B      3,"3",Asc_Nul
          DC.B      3,"THREE",Asc_Nul
          DC.B      -1
          DC.B      "block check type specification",Asc_Nul

* Parity specification keyword table.

ParTable: DC.B      0,"NONE",Asc_Nul
          DC.B      "O","ODD",Asc_Nul
          DC.B      "E","EVEN",Asc_Nul
          DC.B      "M","MARK",Asc_Nul
          DC.B      "S","SPACE",Asc_Nul
          DC.B      -1
          DC.B      "parity specification",Asc_Nul

* Incomplete file disposition keyword table.

IFlDTabl: DC.B      0,"DISCARD",Asc_Nul
          DC.B      1,"KEEP",Asc_Nul
          DC.B      -1
          DC.B      "incomplete file disposition",Asc_Nul

* File type specification keyword table.

FTypTabl: DC.B      0,"TEXT",Asc_Nul
          DC.B      1,"BINARY",Asc_Nul
          DC.B      -1
          DC.B      "file type specification",Asc_Nul

* File naming specification keyword table.

FNamTabl: DC.B      0,"LITERAL",Asc_Nul
          DC.B      1,"CONVERTED",Asc_Nul
          DC.B      -1
          DC.B      "file naming specification",Asc_Nul

* Flow control specification keyword table.

FlowTabl: DC.B      0,"NONE",Asc_Nul
          DC.B      1,"XON/XOFF",Asc_Nul
          DC.B      -1
          DC.B      "flow control specification",Asc_Nul

* Duplex specification keyword table.

DuplTabl: DC.B      0,"FULL",Asc_Nul
          DC.B      1,"HALF",Asc_Nul
          DC.B      -1
          DC.B      "duplex specification",Asc_Nul

* Handshake characters specification keyword table.

HandTabl: DC.B      0,"NONE",Asc_Nul
          DC.B      Asc_Bel,"BELL",Asc_Nul
          DC.B      Asc_LF,"LF",Asc_Nul
          DC.B      Asc_CR,"CR",Asc_Nul
          DC.B      Asc_DC1,"XON",Asc_Nul
          DC.B      Asc_DC3,"XOFF",Asc_Nul
          DC.B      Asc_Esc,"ESC",Asc_Nul
          DC.B      -1
          DC.B      "handshake character specification",Asc_Nul

          align                        Following code aligned on word boundary
          ends
          END
<<< k6odef.asm >>>
*         Kermit68K: source file K68DEF
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release
* ??????   ??????  Steve Williams   Modified for OS9 (see below)

*  This file is adapted in a very straightforward manner from the original
*  k68def.src file.
*
*  Since the OS-9 assembler will not allow the declaration of labels inside
*  a macro definition (ala the'\3 equ VarIndex' used previously) the do.b,
*  do.w, and do.l pseudo instructions are used instead.  These perform a
*  very similiar offset definition function.
*
*  This file has been converted to its own psect for the following reasons:
*
*  1.  It makes defining the dependencies in the make utility makefile much
*      easier, since each object file depends on only one source file.
*
*  2.  It greatly decreases the development cycle time by reducing the disk
*      accesses needed during reassembly.
*
*  3.  The OS-9 symobolic debugger needs global symbols in order to provide
*      meaningful interpretation of programs being debugged.

Edition   set       1
          psect     K68Definitions,0,0,Edition,0,0

*         Truth values

True:     EQU      -1                  True value, in the sense of Scc opcode
False:    EQU       0                  False value, in the sense of Scc opcode

*         ASCII control characters

Asc_Nul:  EQU       0                  Nul or tape feed
Asc_SOH:  EQU       1                  Start of heading
Asc_STx:  EQU       2                  Start of text
Asc_ETx:  EQU       3                  End of text
Asc_EOT:  EQU       4                  End of transmission
Asc_Enq:  EQU       5                  Enquire
Asc_Ack:  EQU       6                  Acknowledge
Asc_Bel:  EQU       7                  Bell
Asc_BS:   EQU       8                  Backspace
Asc_HT:   EQU       9                  Horizontal tab
Asc_LF:   EQU      10                  Line feed
Asc_VT:   EQU      11                  Vertical tab
Asc_FF:   EQU      12                  Form feed
Asc_CR:   EQU      13                  Carriage return
Asc_SO:   EQU      14                  Shift out
Asc_SI:   EQU      15                  Shift in
Asc_DLE:  EQU      16                  Data link escape
Asc_DC1:  EQU      17                  Device control 1
Asc_DC2:  EQU      18                  Device control 2
Asc_DC3:  EQU      19                  Device control 3
Asc_DC4:  EQU      20                  Device control 4
Asc_NAk:  EQU      21                  Negative acknowledge
Asc_Syn:  EQU      22                  Synchronous idle
Asc_ETB:  EQU      23                  End of transmission block
Asc_Can:  EQU      24                  Cancel
Asc_EM:   EQU      25                  End of medium
Asc_Sub:  EQU      26                  Substitute
Asc_Esc:  EQU      27                  Escape, prefix
Asc_FS:   EQU      28                  File separator
Asc_GS:   EQU      29                  Group separator
Asc_RS:   EQU      30                  Record separator
Asc_US:   EQU      31                  Unit separator
Asc_Del:  EQU     127                  Delete

*          Buffers and strings sizes

StkMDpth: EQU     512                  Max stack depth (long words)
McrTblLn: equ    2000                  Mcaro table length
RBufLen:  EQU     200                  Receive buffer length
CmdBufLn: EQU     200                  Command buffer length
PromptML: EQU      32                  Prompt string max length
LinNamML: EQU      32                  Line name string max length
FilNamML: EQU      28                  File names max length (for OS9--was 40)
MxPckSiz: EQU      94                  Maximum packet size
MaxTakeF: EQU      20                  Maximum number of nested take files

*         Kermit protocol automaton states

SndInitS: EQU       0                  Send-Init
OpnFileS: EQU       1                  Open-File
SndFileS: EQU       2                  Send-File
SndDataS: EQU       3                  Send-Data
SendEOFS: EQU       4                  Send-End-Of-File
SendEOTS: EQU       5                  Send-Break
RecInitS: EQU       6                  Receive-Init
RecFileS: EQU       7                  Receive-File
RecDataS: EQU       8                  Receive-Data
SndSrvIS: EQU       9                  Send-Server-Init
SndGCmdS: EQU      10                  Send-Generic-Command
CompletS: EQU      11                  Complete
AbortS:   EQU      12                  Abort

*         Logical channels

Null:     EQU       0                  Null logical channel number
Terminal: EQU       1                  Terminal line logical channel number
HostLine: EQU       2                  Host line logical channel number
IOFile:   EQU       3                  I/O file logical channel number
TakeFil0: EQU       4                  Outer level take file ...
TakeFil1: EQU       5                  ... and so on

*         System I/O routines InpChar, OutChar and ChanCtrl completion codes

AllOk:    EQU       0                  No errors
BadChan:  EQU       1                  Inexistent channel
ResChan:  EQU       2                  Access reserved, permission denied
DevNotRd: EQU       3                  Device not ready (e.g. unmounted)
NotInpCh: EQU       4                  Input impossible on this channel
NotOutCh: EQU       5                  Output impossible on this channel
NotOpRd:  EQU       6                  File not open for read
NotOpWr:  EQU       7                  File not open for write
UnrInpF:  EQU       8                  Unrecoverable failure during input
UnrOutF:  EQU       9                  Unrecoverable failure during output
InChLost: EQU      10                  Input character lost
InpBreak: EQU      11                  Break received on input
BufEmpty: EQU      12                  Input buffer empty
BufOvflw: EQU      13                  Input buffer overflow
EndOfFil: EQU      14                  End of file reached on input
DevFull:  EQU      15                  Device full, not enough space
BadCtReq: EQU      16                  I/O control request code invalid

*         FilOpen function request codes

RdWrOp:   EQU       0                  Open for read/write
ReadOp:   EQU       1                  Open for read
WriteOp:  EQU       2                  Open for write
AppendOp: EQU       3                  Open for append

*         I/O channel control requests

SetBaud:  EQU       0                  Set baud rate on port
RawMode:  EQU       1                  Enable raw mode
TextMode: EQU       2                  Enable text mode
DoXCntrl: EQU       3                  Enable XON/XOFF protocol
NoXCntrl: EQU       4                  Disable XON/XOFF protocol
SndBreak: EQU       5                  Send a break over RS 232 C line
ClrInpBf: EQU       6                  Clear input buffer
ClrOutBf: EQU       7                  Clear output buffer

*         System function request codes

SysCommd: equ       0                  Forward a command to system
Directry: EQU       1                  Display a directory listing
SpacInfo: EQU       2                  Display informations about disk usage
DeletFil: EQU       3                  Delete file(s)
CopyFile: EQU       4                  Copy file(s)
ChangDir: EQU       5                  Change the default directory
PrntFile: EQU       6                  Print file(s)
RenamFil: EQU       7                  Rename file(s)
TypeFile: EQU       8                  Type file(s)

*         Screen request codes

SFilName: EQU       0                  Outgoing file name
RFilName: EQU       1                  Inbound file name
FlAsName: EQU       2                  File as-name
XPckData: EQU       3                  X packet data
FlTranOk: EQU       4                  File transfer ok
FlDiscrd: EQU       5                  File discarded
FlIntrrp: EQU       6                  File interrupted
FlSkippd: EQU       7                  File skipped
PackType: EQU       8                  Packet type
TranCmpl: EQU       9                  Transaction complete
ErrMessg: EQU      10                  Error message
WarnMess: EQU      11                  Warning message
UndelTxt: EQU      12                  Undelimited text
TxtDlBeg: EQU      13                  Text delimited at the beginning
TxtDlEnd: EQU      14                  Text delimited at the end
ScrnMxRq: EQU      14                  Screen function max request code

*         Program variables defaults

DefDuplx: equ       False              Default duplex
DefPrity: EQU       0                  Default parity
DefEscap: EQU       5                  Default escape character for connect
DefFlow:  EQU       1                  Default line flow control
DefLocal: EQU       True               Default mode, local or remote
DefSpeed: EQU    9600                  Default line speed
DefDelay: EQU       5                  Default initial delay before sending
DefRetIn: EQU      16                  Defaulut retry limit initial connection
DefRetPk: EQU      10                  Defaulut retry limit normal packets

*         Send Init parameters

MyMxPSiz: EQU      90                  Biggest packet I want receive
MyTimOut: EQU      10                  When I want to be timed out
MyPad:    EQU       0                  How much padding I need
MyPadChr: EQU       Asc_Nul            Padding character I want
MyEOL:    EQU       Asc_CR             End-Of-Line character I want
MyCtlQot: EQU       '#'                Control-Quote character I send
MyRptQot: EQU       $7E                Repeat-Quote character I send
My8BQuot: EQU       '&'                8th-Bit prefix char I will use

*         Receive Init default parameters

DefMxPSz: EQU      80                  Default biggest packet you can receive
DefTmOut: EQU      10                  Default when you want to be timed out
DefPadNm: EQU       0                  Default how much padding you need
DefPadCr: EQU       Asc_Nul            Default padding character you want
DefEOL:   EQU       Asc_CR             Default End-Of-Line character you want
DefCtlQt: EQU       '#'                Default Control-Quote character you send

*    System variables
*    OS-9 will not accept a macro argument as a label, so the variable
*    declarations have been done in another way.  The do.s directive keeps
*    a running offset location counter (separate from the code counter) that
*    can be reset at any time using the org directive.

          org       0

*    Packet related variables

PackNum:  do.b      1                  Packet number
PrevPckN: do.b      1                  Previous packet number
NextPckN: do.b      1                  Next packet number
SendType: do.b      1                  Packet type just sent
IStPckCh: do.b      1                  Incoming packet start character
OStPckCh: do.b      1                  Outbound packet start character
Size:     do.b      1                  Current output data packet size
OldSize:  do.b      1                  Previous output data packet size
First:    do.b      1                  Flag for first character from input
Current:  do.b      1                  Current character from input
Next:     do.b      1                  Next character from input

*    Communication line variables

Speed:    do.l      1                  Line speed, -1 if unknown
Parity:   do.b      1                  Parity specified, 0, 'E', 'O', 'M', 'S'
Flow:     do.b      1                  Flow control, 1 for xon/xoff
TurnFlag: do.b      1                  Line turnaround handshake flag
TurnChar: do.b      1                  Line turnaround character
Delay:    do.b      1                  Initial delay before sending
Duplex:   do.b      1                  Duplex, full by default
Escape:   do.b      1                  Escape character for connect

*    Program variables

CmdBfPnt: do.b      1                  Relative pointer to command buffer
ServrCmd: do.b      1                  Server command to send
Retry:    do.b      1                  Retry limit currently in use
RtryInit: do.b      1                  Retry limit initial connection packets
RtryPack: do.b      1                  Retry limit for normal packets
TakLevel: do.b      1                  Take file level

LFSave:   do.b      1                  This is for newline processing

* If the system uses a single character for text file line delimitation,
* assign to NewLinCh the ASCII value of that character.  For text files,
* that character will be converted to CRLF upon output, and CRLF will be
* converted to that character on input.

NewLinCh: EQU       Asc_CR             Line delimiter for text files

*    Variables for Send-Init parameters

ICtlQuot: do.b      1                  Control prefix in incoming data
OCtlQuot: do.b      1                  Control prefix in outgoing data
IEOL:     do.b      1                  End-Of-Line character to look for
OEOL:     do.b      1                  End-Of-Line character to send
IPadNumb: do.b      1                  How much padding to ask for
OPadNumb: do.b      1                  How much padding to send
IPadChar: do.b      1                  Padding character to ask for
OPadChar: do.b      1                  Padding character to send
ITimInt:  do.b      1                  Timeout interval I use
OTimInt:  do.b      1                  Timeout interval I want you to use
IMPckSiz: do.b      1                  Biggest packet size I want to receive
OMPckSiz: do.b      1                  Biggest packet size I can send
BlChkUs:  do.b      1                  Block check type used
BlChkRq:  do.b      1                  Block check type requested
ReptCnt:  do.b      1                  Repeat count
ReptQuot: do.b      1                  Repeat prefix
ReptFlag: do.b      1                  Repeat processing flag
Bit8Quot: do.b      1                  8th bit prefix
Bit8Flag: do.b      1                  8th bit quoting flag
TimInFlg: do.b      1                  Flag to override the timeout requested
SndPSFlg: do.b      1                  Flag to override the size requested

*    Flags

MStrFlag: do.b      1                  Flag for input from memory string
TermOut:  do.b      1                  Flag for output to the terminal channel
CtlXSeen: do.b      1                  Flag for cancelling a file
CtlZSeen: do.b      1                  Flag for cancelling a file group
Binary:   do.b      1                  Flag for binary file
FNameCnv: do.b      1                  Flag for converting file names
Keep:     do.b      1                  Flag for incomplete file disposition
Warning:  do.b      1                  Flag for file warning
Display:  do.b      1                  Flag for file transfer display
Quiet:    do.b      1                  Be quiet during file transfer
Local:    do.b      1                  Flag for running in local mode
IntMacro: do.b      1                  Flag for interpreting macros
Done:     do.b      1                  Flag for exiting the command parser

*    String and buffer variables

LeftOver: do.b      6                  Small buffer for optimal packet filling
Prompt:   do.b      PromptML           Prompt string
LineName: do.b      LinNamML           Communication line name
FilName:  do.b      FilNamML           Current file name
Argumnt1: do.b      CmdBufLn           First command argument
Argumnt2: do.b      CmdBufLn           Second command argument
DataBuf:  do.b      MxPckSiz+4         Packet data buffer
SendBuf:  do.b      MxPckSiz+4         Send packet buffer
RecBuf:   do.b      RBufLen            Receive packet buffer
CmdBuf:   do.b      CmdBufLn           Buffer for command interpretation
MacroTbl: do.b      McrTblLn           Macro definitions table

*    Statistic variables

ChrsSent: do.l      1                  Chars sent last transaction
TChsSent: do.l      1                  Total characters sent
ChrsRecd: do.l      1                  Chars received last transaction
TChsRecd: do.l      1                  Total characters received
DChsSent: do.l      1                  Data chars sent last transaction
TDChSent: do.l      1                  Total data characters sent
DChsRecd: do.l      1                  Data chars received last transaction
TDChRecd: do.l      1                  Total data characters received
PcksSent: do.l      1                  Packets sent last transaction
TPckSent: do.l      1                  Total packet sent
PcksRecd: do.l      1                  Packets received last transaction
TPckRecd: do.l      1                  Total packet received
NAKsSent: do.l      1                  NAKs sent last transaction
TNAKSent: do.l      1                  Total NAKs sent
NAKsRecd: do.l      1                  NAKs received last transaction
TNAKRecd: do.l      1                  Total NAKs received

*    Pointers

MStrgPnt: do.l      1                  Pointer for input from memory string
MacroPnt: do.l      1                  Pointer for macro interpretation
MTNxtChF: do.l      1                  Pointer to the end of the macro table

*    System dependent routines variables

LinLngth: do.b      1                  For the dumb terminal Screen routine
MyFNBuff: do.b      FilNamML           This is for tests on my system

*    OS-9/68000 specific variables

CR_Last:  do.b      1                  Flag for CR/LF stripping on terminal
TermFlag: do.b      1                  Flag used in OutChar for terminal.
Pathnums: do.w     20                  OS-9 path numbers for logical channels
NumFiles: do.l      1                  Number of files left to process
NextFile: do.l      1                  Pointer to next file name
CmdLinPt: do.l      1                  Pointer to the OS-9 command arguments
FNBuffer: do.b     50*FilNamML         File names buffer for ExpandFN

ShellCmd: do.b    128                  Buffer for constructing shell commands

OptBuff:  do.b    128                  Save area for terminal input PD options

*  Must set the VarIndex variable to the current offset location counter
*  so that the variable section can be set up properly

VarIndex: do.w      1                  Seems reasonable to be word aligned

          vsect
VarArea:  ds.b      VarIndex           Storage definition for the variables area
          ends
          ends
          end
<<< k6oiof.asm >>>
          nam       Kermit68K
          ttl       IO subroutines module

*         Kermit68K: source file K68IOF
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68IOFunctions,0,0,Edition,0,0

********************************* ConInp ******************************ok
*                                                                     *
*  Expect a character from the terminal line.                         *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B character received                  *
*                            D1.B AllOk completion code               *
*                                                                     *
***********************************************************************
ConInp:   MOVEQ     #Terminal,D1       Terminal line I/O channel
          BSR       InpChar            Try to read a character
          TST.B     D1                 All ok ?
          BNE.S     ConInp             No, assume not ready for input, wait
          RTS                          Yes, return

********************************* ConOut ******************************ok
*                                                                     *
*  Send a character to the terminal line.                             *
*                                                                     *
*         Entry conditions : D0.B character to send                   *
*                                                                     *
*         Exit  conditions : D0.B character just sent                 *
*                            D1.B completion code                     *
*                                                                     *
***********************************************************************
ConOut:   MOVEQ     #Terminal,D1       Terminal line I/O channel
          BSR       OutChar            Try to send the character
          RTS                          Return completion code from OutChar

********************************* HostOut *****************************ok
*                                                                     *
*  Send a character to the host line adding a parity bit.             *
*                                                                     *
*         Entry conditions : D0.B character to send                   *
*                                                                     *
*         Exit  conditions : D0.B character just sent                 *
*                            D1.B completion code                     *
*                                                                     *
***********************************************************************
HostOut:  BSR       DoPrity            Add an appropriate parity bit
          MOVEQ     #HostLine,D1       Terminal line I/O channel
          BSR       OutChar            Try to send the character
          RTS                          Return completion code from OutChar

********************************* FileOut *****************************ok
*                                                                     *
*  Write a character to the current I/O file. If an error occurs      *
*  during output then set an interruption flag to stop the file       *
*  transfer.                                                          *
*                                                                     *
*         Entry conditions : D0.B character to send                   *
*                                                                     *
*         Exit  conditions : D0.B character just sent                 *
*                            D1.B completion code                     *
*                                                                     *
***********************************************************************
FileOut:  MOVEQ     #IOFile,D1         Current file I/O channel
          BSR       OutChar            Output the character to it
          TST.B     D1                 Some error ?
          BEQ.S     FileOut1           No, return
          ST        CtlZSeen(A6)       Yes, interrupt the file transfer
FileOut1  RTS

******************************* ConWrite ******************************ok
*                                                                     *
*  Write a null terminated string on the terminal line.               *
*                                                                     *
*         Entry conditions : A0.L pointer to string buffer            *
*                                                                     *
*         Exit  conditions : D1.L destroyed                           *
*                                                                     *
***********************************************************************
ConWrite: MOVEQ     #Terminal,D1       Terminal line I/O channel
          BSR.S     Write              Write now
          RTS

******************************* TypeUNum ******************************ok
*                                                                     *
*  Write a decimal unsigned number to the terminal line.              *
*                                                                     *
*         Entry conditions : D0.L number to be typed                  *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
TypeUNum: MOVEM.L   D1-D3,-(A7)        Save working registers
          SF        D1                 Unsigned conversion wanted
          MOVEQ     #0,D2              Null field
          MOVEQ     #10,D3             Base 10
          LEA       DataBuf+34(A6),A0  Point to the end of a temporary buffer
          BSR       IntToAs            Convert the number into a string
          BSR       ConWrite           Write the obtained string
          MOVEM.L   (A7)+,D1-D3        Restore working registers
          RTS

********************************* Write *******************************ok
*                                                                     *
*  Write a null terminated string on a logical channel.               *
*                                                                     *
*         Entry conditions : D1.B channel number                      *
*                            A0.L pointer to string buffer            *
*                                                                     *
*         Exit  conditions : D1.B channel number                      *
*                                                                     *
***********************************************************************
Write:    MOVE.W    D2,-(A7)           Save working register
          MOVE.B    D1,D2              Save channel number
Write1    MOVE.B    (A0)+,D0           Get a character
          BEQ.S     Write2             Leave if end of string reached
          BSR       OutChar            Send the character, assume no errors
          MOVE.B    D2,D1              Restore channel number
          BRA.S     Write1             Repeat until end of string
Write2    MOVE.W    (A7)+,D2           Restore working register
          RTS

********************************* NewLine *****************************ok
*                                                                     *
*  Send a newline sequence (CR+LF) to the terminal line.              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                                                                     *
***********************************************************************
NewLine:  MOVE.L    D1,-(A7)           Save this register, destroyed by ConOut
          MOVEQ     #Asc_CR,D0         Send a CR
          BSR       ConOut
          MOVEQ     #Asc_LF,D0         And then a LF
          BSR       ConOut
          MOVE.L    (A7)+,D1           Restore working register
          RTS

********************************* CCmdIn ******************************ok
*                                                                     *
*  Input a command line from the terminal line, store it to CmdBuf.   *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B completion code, false on EOF       *
*                                                                     *
***********************************************************************
CCmdIn:   MOVEM.L   A0-A1/D1-D3,-(A7)  Save working registers
          LEA       CmdBuf(A6),A0      Start address
          MOVEA.L   A0,A1              Save start address
CCmdIn1   BSR       ConInp             Get a character
          CMPI.B    #Asc_Sub,D0        EOF character ?
          BEQ.S     CCmdIn10           Yes
          CMPI.B    #Asc_CR,D0         CR ?
          BEQ.S     CCmdIn8            Yes
          CMPI.B    #Asc_LF,D0         CR ?
          BEQ.S     CCmdIn8            Yes
          CMPI.B    #Asc_FF,D0         CR ?
          BEQ.S     CCmdIn8            Yes
          CMPI.B    #Asc_Del,D0        Delete ?
          BEQ.S     CCmdIn2            Yes
          CMPI.B    #Asc_BS,D0         Backspace ?
          BNE.S     CCmdIn3            No
CCmdIn2   CMPA.L    A1,A0              At line begin ?
          BEQ.S     CCmdIn1            Yes, no action
          BSR.S     CCmdIn11           No, delete last character
          BRA.S     CCmdIn1            Another character please !
CCmdIn3   CMPI.B    #Asc_Can,D0        Ctrl X ?
          BNE.S     CCmdIn5            No
CCmdIn4   CMPA.L    A1,A0              At line begin ?
          BEQ.S     CCmdIn1            Yes, exit
          BSR.S     CCmdIn11           No, delete last character
          BRA.S     CCmdIn4            Repeat until the whole line is deleted
CCmdIn5   MOVE.B    D0,(A0)+           Store the character
          CMPI.B    #' ',D0            Printable character ?
          BGE.S     CCmdIn6            Yes, print it out
          CMPI.B    #Asc_HT,D0         Horizontal tab ?
          BEQ.S     CCmdIn6            Yes, print it out
          ADDI.B    #64,D0             Make it printable
          MOVEQ     #'^',D2            Prefix character for control
          EXG       D0,D2              Exchange
          BSR       ConOut             Output prefix
          EXG       D0,D2              Exchange
CCmdIn6   BSR       ConOut             Output character
CCmdIn7   MOVE.L    A0,D3              Other characters to read ?
          SUB.L     A1,D3
          CMPI.W    #CmdBufLn,D3
          BLT.S     CCmdIn1            Yes, again please !!!
CCmdIn8   ST        D0                 Return a positive completion code
CCmdIn9   CLR.B     (A0)+              Null as terminator
          MOVEM.L   (A7)+,A0-A1/D1-D3  Restore working registers
          RTS
CCmdIn10  SF        D0                 Return a negative cc, EOF on input
          BRA.S     CCmdIn9            Join common part
CCmdIn11  MOVE.B    -(A0),D0           Back off
          CMPI.B    #' ',D0            Printable character ?
          BGE.S     CCmdIn12           Yes, only one character to delete
          BSR.S     CCmdIn13           No, delete the prefix
CCmdIn12  BSR.S     CCmdIn13           Delete character
          RTS
CCmdIn13  MOVEQ     #Asc_BS,D0         Delete the last character
          BSR       ConOut
          MOVEQ     #' ',D0
          BSR       ConOut
          MOVEQ     #Asc_BS,D0
          BSR       ConOut
          RTS

********************************* FlCmdIn *****************************ok
*                                                                     *
*  Input a command line from a take file, store it to CmdBuf.         *
*                                                                     *
*         Entry conditions : D1.B take file channel number            *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            D1.B destroyed                           *
*                            D2.B destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
FlCmdIn:  LEA      CmdBuf(A6),A0       Pointer to target buffer
          MOVE.B   D1,D2               Save the channel number
FlCmdIn1  BSR      InpChar             Try to get a character
          CMP.B    #AllOk,D1           Ok ?
          BEQ.S    FlCmdIn3            Yes
          CMP.B    #EndOfFil,D1        End of file ?
          BEQ.S    FlCmdIn2            Yes, return the proper completion code
          LEA      FlCmdStr(PC),A0     No, some error during read
          BSR      ConWrite            Give this message
FlCmdIn2  SF       D0
          RTS
FlCmdIn3  CMPI.B   #NewLinCh,D0        End of line ?
          BEQ.S    FlCmdIn4            Yes, exit loop
          MOVE.B   D0,(A0)+            No, store the character just read
          MOVE.B   D2,D1               Reload channel number for the next read
          BRA.S    FlCmdIn1            Stay in loop
FlCmdIn4  CLR.B    (A0)                Terminate the command buffer
          ST       D0                  Return a positive completion code
          RTS

********************************* McCmdIn *****************************ok
*                                                                     *
*  Input a command line from a macro, store it to CmdBuf.             *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
McCmdIn:  LEA      CmdBuf(A6),A0       Pointer to target buffer
          MOVEA.L  MacroPnt(A6),A1     Pointer to source buffer
          TST.B    (A1)                Are we at the end of the macro body ?
          BEQ.S    McCmdIn4            Yes, end of macro, return false
McCmdIn1  MOVE.B   (A1)+,D0            Get a character
          BEQ.S    McCmdIn2            If null, this is the last line
          CMPI.B   #Asc_CR,D0          End of line ?
          BEQ.S    McCmdIn3            Yes, ...
          MOVE.B   D0,(A0)+            Store the character in target buffer
          BRA.S    McCmdIn1            Loop until end of line
McCmdIn2  SUBQ.L   #1,A1               Still point to the null, next time ...
McCmdIn3  MOVE.L   A1,MacroPnt(A6)     Save the pointer to next macro line
          CLR.B    (A0)                Terminate the command buffer
          ST       D0                  Return a positive completion code
          RTS
McCmdIn4  SF       D0                  End of macro, return a negative cc
          RTS

********************************* SendPad *****************************ok
*                                                                     *
*  Send padding characters to the communication line.                 *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B destroyed                           *
*                                                                     *
***********************************************************************
SendPad:  MOVEM.L   D1-D2,-(A7)        Save working registers
          CLR.W     D2                 Clear counter register
          MOVE.B    OPadNumb(A6),D2    Number of padding char to send
          BRA.S     SendPad2           Enter loop
SendPad1  MOVE.B    OPadChar(A6),D0    Padding character to send
          BSR       HostOut            Send padding character to host line
SendPad2  DBF       D2,SendPad1        Repeat
          MOVEM.L   (A7)+,D1-D2        Restore working registers
          RTS

********************************* TxPackt *****************************ok
*                                                                     *
*  Send the packet stored in SendBuf to the host line.                *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
TxPackt:  MOVEM.L   D1/A0,-(A7)        Save working registers
          BSR       SendPad            Do any requested padding
          LEA       SendBuf(A6),A0     Packet buffer start
TxPackt1  MOVE.B    (A0)+,D0           Get a character
          BEQ.S     TxPackt2           Leave if end of string reached
          BSR       HostOut            Send the character
          ADDQ.L    #1,ChrsSent(A6)    Increment chars sent this transaction
          ADDQ.L    #1,TChsSent(A6)    Increment total characters sent
          BRA.S     TxPackt1           Repeat until end of string
TxPackt2  ADDQ.L    #1,PcksSent(A6)    Increment packets sent this trans
          ADDQ.L    #1,TPckSent(A6)    Increment total packets sent
          MOVEM.L   (A7)+,D1/A0        Restore working registers
          RTS

******************************** InpLine ******************************ok
*                                                                     *
*  Input a line (up to the break char) from the communication line.   *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L number of characters received       *
*                            D1.B completion code                     *
*                            A0.L destroyed                           *
*                            D2.L destroyed                           *
*                            D3.W destroyed                           *
*                            D4.B destroyed                           *
*                                                                     *
***********************************************************************
InpLine:  LEA       RecBuf(A6),A0      Point to receive buffer
          CLR.L     D2                 Clear the character counter
          CLR.W     D3                 Clear the timeout counter
          TST.B     TurnFlag(A6)       Is the turnaround handshake flag on ?
          BEQ.S     InpLine0           No, look for Input EOL as terminator
          MOVE.B    TurnChar(A6),D4    Yes, turnaround character as terminator
          BRA.S     InpLine1
InpLine0  MOVE.B    IEOL(A6),D4        Load the Input End Of Line character
InpLine1  MOVE.B    ITimInt(A6),D3     Preset the timeout counter
InpLine2  BSR       RdChrTO            Get a character
          TST.B     D1                 Timed out ?
          BNE.S     InpLine3           No, continue
          DBF       D3,InpLine2        Yes, repeat unless timeout limit reached
          SF        D1                 Provide a negative completion code
          RTS

InpLine3  CMP.B     D4,D0              End Of Line or turnaround character ?
          BEQ.S     InpLine4           Yes
          MOVE.B    D0,(A0)+           No, got a character, save it
          ADDQ.L    #1,D2              Increment the character counter
          CMPI.B    #RBufLen,D2        Receive buffer full ?
          BNE.S     InpLine1           No, again please !
InpLine4  CLR.B     (A0)               Mark the end of buffer
          ADD.L     D2,ChrsRecd(A6)    Increment chars received this transaction
          ADD.L     D2,TChsRecd(A6)    Increment total characters received
          MOVE.L    D2,D0              Return number of characters received
          ST        D1                 Return a positive completion code
          RTS

******************************** RdChrTO ******************************ok
*                                                                     *
*  Called only by InpLine, read a character from the host line with   *
*  1 second software timeout limit. Warning, this routine is          *
*  absolutely provisory.                                              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B character received                  *
*                            D1.B completion code                     *
*                                                                     *
***********************************************************************
MaxIter   SET       10000              To set the timeout value
*
RdChrTO   MOVE.W    D2,-(A7)           Save the counter register
          MOVE.W    #MaxIter,D2        Set up the timeout counter
RdChrTO1  MOVEQ     #HostLine,D1       Try to read the host line
          BSR       InpChar
          TST.B     D1                 Check completion code
          BEQ.S     RdChrTO2           Character received, handle 8th bit
          DBF       D2,RdChrTO1        Timeout period expired ?
          SF        D1                 Yes, return negative completion code
          MOVE.W    (A7)+,D2           Restore the counter register
          RTS
RdChrTO2  BSR       HndlPar            Handle the parity bit
          ST        D1                 Return positive completion code
          MOVE.W    (A7)+,D2           Restore the counter register
          RTS

********************************* ChkInpF *****************************ok
*                                                                     *
*  Check if an input file exists and is readable.                     *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
*                            -3 file exists but protected from read   *
*                            -2 file exists but is not readable       *
*                            -1 inexistent or inaccessable file       *
*                             0 all ok                                *
*                                                                     *
*                            D1.L destroyed                           *
*                            D2.B destroyed                           *
*                                                                     *
***********************************************************************
ChkInpF:  MOVEQ     #ReadOp,D0         Try to open for read the input file
          MOVEQ     #IOFile,D1         Assign it to this channel number
          BSR       FilOpen            Open now
          TST.B     D0                 Some failure ?
          BEQ.S     ChkInpF1           Yes, return this bad completion code
          MOVEQ     #IOFile,D1         No, try to read a character
          BSR       InpChar
          MOVE.B    D1,D2              Save the returned completion code
          MOVEQ     #IOFile,D1         Close the file just opened
          BSR       FilClose
          TST.B     D2                 The read was successful ?
          BEQ.S     ChkInpF0           Yes, all ok
          CMPI.B    #EndOfFil,D2       No, end of file ?
          BEQ.S     ChkInpF0           Yes, the file is null, but ok
          CMPI.B    #ResChan,D2        No privilege to read this file ?
          BEQ.S     ChkInpF2           Yes, return this bad completion code
          MOVEQ     #-2,D0             No, some other error, unreadable file cc
          RTS
ChkInpF0  MOVEQ     #0,D0              Return all ok
          RTS
ChkInpF1  MOVEQ     #-1,D0             Return inexistent file cc
          RTS
ChkInpF2  MOVEQ     #-3,D0             Return protected file cc
          RTS

********************************* ChkOutF *****************************ok
*                                                                     *
*  Check if an output file can be created.                            *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
*                            -1 permission denied                     *
*                             0 all ok                                *
*                                                                     *
***********************************************************************
ChkOutF:  MOVEQ     #0,D0              Always succeeds for now
          RTS

********************************* OpnInpF *****************************ok
*                                                                     *
*  Try to open an existing file for input.                            *
*                                                                     *
*         Entry conditions : A0.L pointer to the file name            *
*                                                                     *
*         Exit  conditions : A0.L pointer to the file name            *
*                            D0.B completion code                     *
*                            D1.L destroyed                           *
*                                                                     *
***********************************************************************
OpnInpF:  MOVE.B    MStrFlag(A6),D0    Input from memory string ?
          BNE.S     OpnInpF1           Yes, return a positive cc
          MOVEQ     #ReadOp,D0         Try to open the input file
          MOVEQ     #IOFile,D1
          BSR       FilOpen
          TST.B     D0                 Open succeed ?
          BEQ.S     OpnInpF1           Yes, return this completion code
          BSR       CRemTLoc           No, convert name to local form
          MOVEQ     #ReadOp,D0         Try again to open the input file
          MOVEQ     #IOFile,D1
          BSR       FilOpen
OpnInpF1  RTS                          Return cc from FilOpen

********************************* OpnOutF *****************************ok
*                                                                     *
*  Try to open an existing file for output.                           *
*                                                                     *
*         Entry conditions : A0.L pointer to the file name            *
*                            A1.L pointer to the file name            *
*                                 target buffer                       *
*                                                                     *
*         Exit  conditions : A0.L pointer to the file name target     *
*                                 buffer containing the file name     *
*                                 under wich the file was opened      *
*                            D0.B completion code                     *
*                            D1.L destroyed                           *
*                                                                     *
***********************************************************************
OpnOutF:  MOVE.B    TermOut(A6),D0     Terminal output wanted ?
          BNE.S     OpnOutF3           Yes, return a positive cc
          MOVE.B    CtlXSeen(A6),D0    Some interruption ?
          OR.B      CtlZSeen(A6),D0
          BNE.S     OpnOutF3           Yes, don't destroy existing file
          EXG       A0,A1              Exchange buffers pointers
          MOVEQ     #FilNamML,D0       Load buffers length
          BSR       CopyStr            Fill target buffer, copy from source
          TST.B     FNameCnv(A6)       File names conversion ?
          BEQ.S     OpnOutF1           No, proceed
          BSR       CRemTLoc           Yes, convert file name to local form
OpnOutF1  TST.B     Warning(A6)        File collision avoidance ?
          BEQ.S     OpnOutF2           No, proceed
          BSR       ChkInpF            Yes, check if file exists
          CMPI.B    #-1,D0             File exists ?
          BEQ.S     OpnOutF2           No, proceed
          BSR       NewName            Yes, make a new name
OpnOutF2  MOVEQ     #WriteOp,D0        Finally open the file for output
          MOVEQ     #IOFile,D1
          BSR       FilOpen
OpnOutF3  RTS                          Return the completion code

********************************* ClsInpF *****************************ok
*                                                                     *
*  Close the current input file.                                      *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                                                                     *
***********************************************************************
ClsInpF:  TST.B     MStrFlag(A6)       Input from memory string ?
          BEQ.S     ClsInpF1           No, close the input file
          SF        MStrFlag(A6)       Yes, reset flag
          BRA.S     ClsInpF2
ClsInpF1  MOVEQ     #IOFile,D1         Close the output file
          BSR       FilClose
ClsInpF2  MOVE.B    CtlXSeen(A6),D0    File interrupt ...
          OR.B      CtlZSeen(A6),D0    ... or file group interrupt ?
          BNE.S     ClsInpF3           Yes, give discard message
          MOVEQ     #FlTranOk,D0       No, give comforting messages
          BSR       Screen
          BRA.S     ClsInpF4
ClsInpF3  MOVEQ     #FlDiscrd,D0       Give discard message
          BSR       Screen
ClsInpF4  SF        CtlXSeen(A6)       Reset file interrupt flag
          CLR.B     FilName(A6)        Nullify current file name
          RTS

********************************* ClsOutF *****************************ok
*                                                                     *
*  Close the current output file.                                     *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
ClsOutF:  TST.B     TermOut(A6)        Output to the terminal line ?
          BNE.S     ClsOutF3           Yes, just reset flag and return
          LEA       FilName(A6),A0     No, point to current file name
          TST.B     (A0)               File open ?
          BEQ.S     ClsOutF1           No
          MOVEQ     #IOFile,D1         Yes, close the output file
          BSR       FilClose
          MOVE.B    CtlXSeen(A6),D0    File interrupt ...
          OR.B      CtlZSeen(A6),D0    ... or file group interrupt ?
          BEQ.S     ClsOutF1           No, just keep it
          TST.B     Keep(A6)           Yes, keeping incomplete files ?
          BNE.S     ClsOutF1           Yes
          BSR       FilDelet           No, discard it
          MOVEQ     #FlDiscrd,D0       Give discard message
          BSR       Screen
          BRA.S     ClsOutF2           Nullify file name and return
ClsOutF1  MOVEQ     #FlTranOk,D0       Give comforting messages
          BSR       Screen
ClsOutF2  CLR.B     (A0)               Nullify current file name
          RTS
ClsOutF3  SF        TermOut(A6)        Clear the terminal output flag
          RTS

********************************* ChekInt *****************************ok
*                                                                     *
*  Terminal interrupts handler.                                       *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
ChekInt:  TST.B     Local(A6)          Are we running in local mode ?
          BEQ.S     ChekInt1           No, return
          TST.B     Quiet(A6)          Quiet requested ?
          BNE.S     ChekInt1           Yes, return
          MOVEQ     #Terminal,D1       Try to get a character from terminal
          BSR       InpChar
          TST.B     D1                 Success ?
          BNE.S     ChekInt1           No, return
          CMPI.B    #Asc_Sub,D0        Control Z ?
          BEQ.S     ChekInt2           Yes
          CMPI.B    #Asc_Can,D0        Control X ?
          BEQ.S     ChekInt3           Yes, set the file interrupt flag
          CMPI.B    #Asc_DC2,D0        Control R ?
          BEQ.S     ChekInt4           Yes, resend the last packet
          MOVEQ     #Asc_Bel,D0        No, ignore, ring the bell
          BSR       ConOut
ChekInt1  RTS

ChekInt2  LEA       CnBchStr(PC),A1    Cancel batch
          MOVEQ     #TxtDlBeg,D0       Give message
          BSR       Screen
          ST        CtlZSeen(A6)       Set the file batch interrupt flag
          RTS

ChekInt3  LEA       CnFilStr(PC),A1    Cancel file
          MOVEQ     #TxtDlBeg,D0       Give message
          BSR       Screen
          ST        CtlXSeen(A6)       Set the file interrupt flag
          RTS

ChekInt4  LEA       ReSndStr(PC),A1    Resend packet
          MOVEQ     #TxtDlBeg,D0       Give message
          BSR       Screen
          BSR       Resend             Resend the last packet
          RTS

********************************** Screen *****************************ok
*                                                                     *
*  Screen diplay routine.                                             *
*                                                                     *
*         Entry conditions : D0.B request code                        *
*                            D1.B packet type or pseudotype           *
*                            D2.B packet number                       *
*                            D3.B packet length                       *
*                            A1.L pointer to a string to write        *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
ScrnMxLL  EQU       78                 Maximum line length

Screen:   TST.B     Display(A6)        The display flag is off ?
          BEQ.S     Screen1            Yes, no update
          TST.B     Quiet(A6)          Are we requested to be quiet ?
          BEQ.S     Screen2            No, update the screen
Screen1   RTS

Screen2   MOVEM.L   A0-A1/D1-D7,-(A7)  Save some registers
          MOVE.B    LinLngth(A6),D6    Length of the current screen line
          CLR.W     D4                 Compute the length of the passed string
Screen3   TST.B     (A1,D4.W)          End of line ?
          BEQ.S     Screen4            Yes, continue
          ADDQ.B    #1,D4              No, count
          BRA.S     Screen3            Repeat until end of line

Screen4   MOVEQ     #ScrnMxRq,D5       Maximum request code
          CMP.W     D5,D0              Request code out of range ?
          BHI       Screen30           Yes, return
          ADD.W     D0,D0              No, scale it
          MOVE.W    Screen5(PC,D0.W),D0 Relative address of the service routine
          JMP       Screen5(PC,D0.W)   Jump to it

Screen5   DC.W      Screen6-Screen5    SFilName
          DC.W      Screen7-Screen5    RFilName
          DC.W      Screen9-Screen5    FlAsName
          DC.W      Screen11-Screen5   XPckData
          DC.W      Screen12-Screen5   FlTranOk
          DC.W      Screen14-Screen5   FlDiscrd
          DC.W      Screen16-Screen5   FlIntrrp
          DC.W      Screen18-Screen5   FlSkippd
          DC.W      Screen19-Screen5   PackType
          DC.W      Screen22-Screen5   TranCmpl
          DC.W      Screen23-Screen5   ErrMessg
          DC.W      Screen24-Screen5   WarnMess
          DC.W      Screen25-Screen5   UndelTxt
          DC.W      Screen27-Screen5   TxtDlBeg
          DC.W      Screen28-Screen5   TxtDlEnd

Screen6   LEA       ScrnStr1(PC),A0    Display outgoing file name
          BRA.S     Screen8

Screen7   LEA       ScrnStr2(PC),A0    Display inbound file name

Screen8   BSR       NewLine            Display file name
          BSR       ConWrite
          MOVE.B    #10,D6
          MOVEA.L   A1,A0
          BSR       ConWrite
          MOVEQ     #' ',D0
          BSR       ConOut
          ADD.B     D4,D6
          ADDQ.B    #1,D6
          BRA       Screen30

Screen9   MOVE.B    D4,D5              Display file as-name
          ADD.B     D6,D5
          CMPI.B    #ScrnMxLL-3,D5
          BLS.S     Screen10
          BSR       NewLine
          CLR.B     D6
Screen10  LEA       ScrnStr3(PC),A0
          BSR       ConWrite
          MOVEA.L   A1,A0
          BSR       ConWrite
          MOVEQ     #' ',D0
          BSR       ConOut
          ADD.B     D4,D6
          ADDQ.B    #3+1,D6
          CMPI.B    #ScrnMxLL,D6
          BLS       Screen30
          BSR       NewLine
          CLR.B     D6
          BRA       Screen30

Screen11  BSR       NewLine            Display X-packet data
          MOVEA.L   A1,A0
          BSR       ConWrite
          BSR       NewLine
          CLR.B     D6
          BRA       Screen30

Screen12  CMPI.B    #ScrnMxLL-5,D6     Successful file transfer message
          BLS.S     Screen13
          BSR       NewLine
          CLR.B     D6
Screen13  LEA       ScrnStr4(PC),A0
          BSR       ConWrite
          ADDQ.B    #5,D6
          BRA       Screen30

Screen14  CMPI.B    #ScrnMxLL-12,D6    File discarded message
          BLS.S     Screen15
          BSR       NewLine
          CLR.B     D6
Screen15  LEA       ScrnStr5(PC),A0
          BSR       ConWrite
          ADDI.B    #12,D6
          BRA       Screen30

Screen16  CMPI.B    #ScrnMxLL-14,D6    File transfer interrupted message
          BLS.S     Screen17
          BSR       NewLine
          CLR.B     D6
Screen17  LEA       ScrnStr6(PC),A0
          BSR       ConWrite
          ADDI.B    #14,D6
          BRA       Screen30

Screen18  BSR       NewLine            File skipped message
          LEA       ScrnStr7(PC),A0
          BSR       ConWrite
          MOVEA.L   A1,A0
          BSR       ConWrite
          BSR       NewLine
          CLR.B     D6
          BRA       Screen30

*                                      Display packet type or pseudo-type
Screen19  CMPI.B    #'Y',D1            ACK packet ?
          BEQ       Screen30           Yes, return
          CMPI.B    #'D',D1            Data packet ?
          BNE.S     Screen20           No
          ANDI.B    #3,D2              Yes, only display every 4 packets
          BNE       Screen30           Return
          MOVEQ     #'.',D0
          BRA.S     Screen21
Screen20  MOVE.B    D1,D0              Display the packet type
Screen21  BSR       ConOut
          ADDQ.B    #1,D6              Increment current line length
          CMPI.B    #ScrnMxLL,D6       Near the right margin ?
          BLS.S     Screen30           No, return
          BSR       NewLine            Yes, start a new line
          CLR.B     D6                 Reset the counter
          BRA.S     Screen30

Screen22  MOVEQ     #Asc_Bel,D0        Transaction complete message (bell)
          BSR       ConOut
          BSR       NewLine            Start a new line
          BRA.S     Screen30

Screen23  BSR       NewLine            Error message
          MOVEQ     #'?',D0
          BSR       ConOut
          MOVEA.L   A1,A0
          BSR       ConWrite
          BSR       NewLine
          CLR.B     D6
          BRA.S     Screen30

Screen24  BSR       NewLine            Warning message
          MOVEA.L   A1,A0
          BSR       ConWrite
          BSR       NewLine
          CLR.B     D6
          BRA.S     Screen30

Screen25  ADD.B     D4,D6              Undelimited text
          CMPI.B    #ScrnMxLL,D6
          BLS.S     Screen26
          BSR       NewLine
          MOVE.B    D4,D6
Screen26  MOVEA.L   A1,A0
          BSR       ConWrite
          BRA.S     Screen30

Screen27  BSR       NewLine            Text delimited at beginning
          MOVEA.L   A1,A0
          BSR       ConWrite
          MOVE.B    D4,D6
          BRA.S     Screen30

Screen28  ADD.B     D4,D6              Text delimited at end
          CMPI.B    #ScrnMxLL,D6
          BLS.S     Screen29
          BSR       NewLine
          MOVE.B    D4,D6
Screen29  MOVEA.L   A1,A0
          BSR       ConWrite
          BSR       NewLine
*          BRA.S     Screen30

Screen30  MOVE.B    D6,LinLngth(A6)
          MOVEM.L   (A7)+,A0-A1/D1-D7
          RTS

          ends
          END
<<< k6omai.asm >>>
          nam       Kermit68K
          ttl       Main program module

*         Kermit68K: source file K68MAI

********************************************************************************
********************************************************************************
*  ****  *        *       ***   *****   *  *        ***      **      **  ****  *
*  ***  **  *******  ***   **    ***    *  ****  *****  ******  ****  *  ***  **
*  **  ***  *******  ****  **  *  *  *  *  ****  ****  *******  ****  *  **  ***
*  *  ****  *******  ***   **  **   **  *  ****  ****  *******  ****  *  *  ****
*    *****      ***       ***  *** ***  *  ****  ****       ***      **    *****
*  *  ****  *******  **  ****  *******  *  ****  ****  ****  *  ****  *  *  ****
*  **  ***  *******  ***  ***  *******  *  ****  ****  ****  *  ****  *  **  ***
*  ***  **  *******  ****  **  *******  *  ****  ****  ****  *  ****  *  ***  **
*  ****  *        *  *****  *  *******  *  ****  *****      ***      **  ****  *
********************************************************************************
********************************************************************************
*                                                                              *
*         Kermit implementation for the MC68000 microprocessors family         *
*                                                                              *
*                                                                              *
*   Author:        Roberto Bagnara, Physics Department, Bologna University     *
*                                                                              *
*   Started:       02 May       1986 by rb                                     *
*   Last modified: 01 July      1987 by rb                                     *
*                                                                              *
*   Modified by:   Steve Williams, University of Texas at Austin               *
*                                                                              *
*   Status :       INCOMPLETE                                                  *
*                                                                              *
*                                                                              *
*   Modification History:                                                      *
*                                                                              *
*   Version  Date    Who              Comments                                 *
*                                                                              *
*   1.0.00   870701  Roberto Bagnara  First official release                   *
*                                                                              *
********************************************************************************

          use       DefsFile

TypeLang  equ       (Prgrm<<8)+Objct    Executable 68000 native code
AttrRev   equ       (ReEnt<<8)+0        Re-entrant code, revision 0
Edition   equ       0                   Edition number
Stack     equ       8192                Stack space needed

          psect     Kermit,TypeLang,AttrRev,Edition,Stack,Kerm68K


********************************* Kerm68K *****************************ok
*                                                                     *
*  Kermit68K main program.                                            *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
Kerm68K:  LEA       VarArea(A6),A6     Correct the $8000 bias of OS-9
          BSR       InitAll            Initialize all Kermit68K variables
          BSR       SysInit            Initialize any system dependent thing
          BSR       CmdLnP             Parse the command line, if possible
          LEA       InitFile(PC),A0    Point to the init file name
          MOVEQ     #ReadOp,D0         We want to read it
          MOVEQ     #TakeFil0,D1       This is the channel number
          BSR       FilOpen            Try to open the init file
          TST.B     D0                 Success ?
          BEQ.S     Kerm68K1           No, no message, parse user commands
          CLR.B     TakLevel(A6)       Yes, we are interpreting the take file 0
Kerm68K1  BSR       Parser             Parse interactive commands until done
          ST        D0                 Finally return a positive cc ...
          BRA       SysExod            ... and the control to system

******************************** InitAll ******************************ok
*                                                                     *
*  Startup initialization routine.                                    *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                                                                     *
***********************************************************************
InitAll   MOVE.B    #MyEOL,IEOL(A6)        Set EOL for incoming packets
          MOVE.B    #DefEOL,OEOL(A6)       Set EOL for outgoing packets
          MOVE.B    #DefCtlQt,ICtlQuot(A6) Set incoming packets control quote
          MOVE.B    #MyCtlQot,OCtlQuot(A6) Set outgoing packets control quote
          MOVE.B    #MyPad,IPadNumb(A6)    Set how much padding to ask for
          MOVE.B    #DefPadNm,OPadNumb(A6) Set how much padding to send
          MOVE.B    #MyPadChr,IPadChar(A6) Set padding character to ask for
          MOVE.B    #DefPadCr,OPadChar(A6) Set padding character to send
          MOVEQ     #Asc_SOH,D0            Default packet start character
          MOVE.B    D0,IStPckCh(A6)        Set incoming packet start char
          MOVE.B    D0,OStPckCh(A6)        Set outgoing packet start char
          MOVE.B    #DefTmOut,ITimInt(A6)  Set when I should time out
          MOVE.B    #MyTimOut,OTimInt(A6)  Set when I want to be timed out
          MOVE.B    #MyMxPSiz,IMPckSiz(A6) Set max packet size I want receive
          MOVE.B    #DefMxPSz,OMPckSiz(A6) Set max packet size I can send
          MOVE.B    #MyRptQot,ReptQuot(A6) Set the default repeat prefix
          MOVE.B    #My8BQuot,Bit8Quot(A6) Set the default 8th bit prefix
          MOVE.B    #1,BlChkRq(A6)         Set the default block check type
          MOVE.B    #DefDuplx,Duplex(A6)   Set default duplex
          MOVE.B    #DefFlow,Flow(A6)      Set default flow control
          MOVE.B    #DefPrity,Parity(A6)   Set default parity
          MOVE.B    #DefEscap,Escape(A6)   Set default escape character
          MOVE.B    #DefDelay,Delay(A6)    Set default delay before sending
          MOVE.B    #DefRetIn,RtryInit(A6) Set default retry init limit
          MOVE.B    #DefRetPk,RtryPack(A6) Set default retry normal limit

          LEA       MacroTbl(A6),A0
          MOVE.L    A0,MTNxtChF(A6)

          CLR.B     LinLngth(A6)       For the dumb terminal Screen routine

          SF        ReptFlag(A6)       No repeat processing by default
          SF        TimInFlg(A6)       No timeout overriding
          SF        SndPSFlg(A6)       No packet size overriding
          SF        Binary(A6)         File type is text
          SF        Quiet(A6)          File display is on
          SF        FNameCnv(A6)       File names conversion is off
          SF        Warning(A6)        File warning is off
          SF        Keep(A6)           Don't keep incomplete files

          SF        IntMacro(A6)

          CLR.L     ChrsSent(A6)       Clear the statistic variables
          CLR.L     TChsSent(A6)
          CLR.L     ChrsRecd(A6)
          CLR.L     TChsRecd(A6)
          CLR.L     DChsSent(A6)
          CLR.L     TDChSent(A6)
          CLR.L     DChsRecd(A6)
          CLR.L     TDChRecd(A6)
          CLR.L     PcksSent(A6)
          CLR.L     TPckSent(A6)
          CLR.L     PcksRecd(A6)
          CLR.L     TPckRecd(A6)
          CLR.L     NAKsSent(A6)
          CLR.L     TNAKSent(A6)
          CLR.L     NAKsRecd(A6)
          CLR.L     TNAKRecd(A6)

          MOVE.B    #DefLocal,Local(A6) Setup the initial mode
          MOVE.L    #DefSpeed,Speed(A6) Setup the default line speed

          LEA       DefLinNm(PC),A1    Setup the default line, if any
          LEA       LineName(A6),A0    This is the line name string
          MOVEQ     #LinNamML,D0       Maximum line name length
          BSR       CopyStr            Copy now
          TST.B     (A0)               The default line name was null ?
          BEQ.S     InitAll2           Yes, we hope that somebody does this job

          MOVEQ     #RdWrOp,D0         No, try to open it
          MOVEQ     #HostLine,D1       This is the channel number
          BSR       FilOpen            Open, if possible
          TST.B     D0                 Ok ?
          BNE.S     InitAll1           Yes
          CLR.B     (A0)               No, nullify the line name
          BEQ.S     InitAll2           Proceed initialization, no error messages

InitAll1  LEA       ConLinNm(PC),A1    Yes, point to the console line name
          BSR       CompStr            Compare the two line names
          TST.B     D0                 Are equal ?
          SEQ       Local(A6)          If not we are local, remote otherwise
          BEQ.S     InitAll2           If local, leave speed unchanged
          MOVE.L    #-1,Speed(A6)      If remote, say speed unknown

InitAll2  MOVE.B    #-1,TakLevel(A6)   No files to take yet
          SF        TermOut(A6)        No terminal output, by now
          SF        Done(A6)           Set to false the parser exit flag
          CLR.B     Argumnt1(A6)       Nullify the first command argument
          CLR.B     Argumnt2(A6)       Nullify the second command argument
          CLR.B     FilName(A6)        Nullify current file name
          CLR.B     LinLngth(A6)       *** To be removed -rb- ***

          LEA       DefPrmpt(PC),A1    Set up the default prompt
          LEA       Prompt(A6),A0      This is the prompt string
          MOVEQ     #PromptML,D0       Maximum prompt length
          BSR       CopyStr            Copy now
          RTS

          ends

          END       Kerm68K
<<< k6opro.asm >>>
          nam       Kermit68K
          ttl       Protocol automaton subroutines module

*         Kermit68K: source file K68PRO
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68Protocol,0,0,Edition,0,0

******************************** KPSwtch ******************************ok
*                                                                     *
*  Kermit protocol state table switcher. It loops until either it     *
*  finishes, or an error is encountered. D7.W contains the present    *
*  state of the automaton. The routines called by KPSwtch are         *
*  responsible for changing the state.                                *
*                                                                     *
*         Entry conditions : D7.W initial state of the automaton      *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
KPSwtch:  TST.B     Local(A6)          Are we running in local mode ?
          BEQ.S     KPSwtch1           No, no mind about speed
          TST.L     Speed(A6)          Is line speed setted ?
          BLT.S     KPSwtch3           No, give error and return
KPSwtch1  MOVEQ     #RawMode,D0        Put line in raw mode
          MOVEQ     #HostLine,D1
          BSR       ChanCtrl
          CMPI.B    #AllOk,D0          All ok ?
          BEQ.S     KPSwtch5           Yes, enter the protocol switcher
KPSwtch2  LEA       CCndLStr(PC),A1    No, point to the error message
          BRA.S     KPSwtch4           Display this on the screen
KPSwtch3  LEA       StSpeStr(PC),A1    Point to the 'set speed' error message
KPSwtch4  MOVEQ     #ErrMessg,D0       Error message display request code
          BSR       Screen             Display on the screen
          RTS

KPSwtch5  PEA       KPSwtch5(PC)       Provide return address
          MOVE.W    D7,D0              Load the present state of the automaton
          ADD.W     D0,D0              Scale it
          MOVE.W    KPSwtch6(PC,D0.W),D0 Load index
          JMP       KPSwtch6(PC,D0.W)  Jump to the appropriate address

KPSwtch6  DC.W      SndInit-KPSwtch6   Send-Init
          DC.W      OpnFile-KPSwtch6   Open-File
          DC.W      SndFile-KPSwtch6   Send-File
          DC.W      SndData-KPSwtch6   Send-Data
          DC.W      SendEOF-KPSwtch6   Send-End-Of-File
          DC.W      SendEOT-KPSwtch6   Send-Break
          DC.W      RecInit-KPSwtch6   Receive-Init
          DC.W      RecFile-KPSwtch6   Receive-File
          DC.W      RecData-KPSwtch6   Receive-Data
          DC.W      SndSrvI-KPSwtch6   Send-Server-Init
          DC.W      SndGCmd-KPSwtch6   Send-Generic-Command
          DC.W      Complete-KPSwtch6  Complete
          DC.W      Abort-KPSwtch6     Abort

******************************** SndSrvI ******************************ok
*                                                                     *
*  Send Server Init, send this host's parameters and get other side's *
*  back, then enter Send Generic Command state.                       *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            D2.L destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                                                                     *
***********************************************************************
SndSrvI   MOVEQ     #ClrInpBf,D0       Clear the input buffer
          MOVEQ     #HostLine,D1       Host line channel, of course
          BSR       ChanCtrl           Call the channel control routine
          BSR       SndParm            Fill up the init info packet
          MOVEQ     #'I',D1            Send an I packet
          MOVEQ     #0,D2              Packet number (always 0)
          MOVE.B    D0,D3              Packet length as returned by SndParm
          BSR       SndPack            Ok, send now

          BSR       InpPack            What was the reply ?
          CMPI.B    #'Y',D1            ACK ?
          BEQ.S     SndSrvI4           Yes
          CMPI.B    #'E',D1            Error packet ?
          BNE       BadPack            No, bad packet
          CLR.B     DataBuf(A6)        Yes, ignore it, clear data buffer
*                                      Fall thru, use default parameters
SndSrvI4  BSR       RdParam            Get other side's init info
          MOVE.B    BlChkRq(A6),BlChkUs(A6) Setup block check type
          MOVEQ     #SndGCmdS,D7       OK, switch state to Send-Generic-Command
          RTS

******************************** SndGCmd ******************************ok
*                                                                     *
*  Send Generic Command.                                              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            D2.L destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
SndGCmd   LEA       CmdBuf(A6),A0      Point to command buffer
          BSR       EncStrng           Fill up the data buffer
          MOVE.B    ServrCmd(A6),D1    Send a packet of the appropriate type
          MOVEQ     #0,D2              Packet number (always 0)
          MOVE.B    Size(A6),D3        Packet size
          BSR       SndPack            Ok, send now
          BSR       InpPack            What was the reply ?

          CMPI.B    #'Y',D1            ACK ?
          BEQ.S     SndGCmd2           Yes
          CMPI.B    #'S',D1            Send-Init packet ?
          BEQ.S     SndGCmd3           Yes
          CMPI.B    #'X',D1            X packet ?
          BNE       BadPack            No, unknown packet type, abort
          ST        TermOut(A6)        Yes, set the terminal output flag
          BSR       SendACK            Acknowledge
          MOVEQ     #RecDataS,D7       Enter Receive-Data state
          RTS

SndGCmd2  LEA       ConOut(PC),A0      ACK received
          BSR       Decode             Decode packet and output it
          BSR       NewLine            Start a new line on the screen
          MOVEQ     #CompletS,D7       Ok, enter complete state
          RTS

SndGCmd3  BSR       RdParam            Get the other side's init data
          BSR       SndParm            Fill up packet with my init info
          MOVEQ     #'Y',D1            ACK my parameters
          MOVEQ     #0,D2              Packet number (0)
          MOVE.B    D0,D3              Packet length as returned by SndParm
          BSR       SndPack            OK, send now
          BSR       BumpPckN           Bump packet number, modulo 64
          MOVE.B    BlChkRq(A6),BlChkUs(A6) Setup block check type
          MOVEQ     #RecFileS,D7       Enter Receive-File state
          RTS

******************************** Complete *****************************ok
*                                                                     *
*  Successful end of transaction.                                     *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B positive completion code            *
*                                                                     *
***********************************************************************
Complete  ADDQ.L    #4,A7              Drop return address
          MOVEQ     #TranCmpl,D0       Say transaction complete
          BSR       Screen
          ST        D0                 Return a positive completion code
          RTS

********************************* Abort *******************************ok
*                                                                     *
*  Unsuccessful end of transaction.                                   *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B negative completion code            *
*                            D4.B destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
Abort     ADDQ.L    #4,A7              Drop return address

          CMPI.B    #'E',D1            Error packet received ?
          BNE.S     Abort1             No, too many tries or invalid type

          BSR       NewLine
          LEA       ErFRHStr(PC),A0    Yes, point to error string
          BSR       ConWrite           Write it to terminal
          LEA       DataBuf(A6),A0     Point to error packet contents
          BSR       ConWrite           Write it to terminal
          MOVE.B    Quiet(A6),D4       Save the quiet flag
          ST        Quiet(A6)          Set the quiet flag on
          BSR       ClsInpF            Close the input file silently
          ST        CtlZSeen(A6)       Force discarding of the ouput file
          BSR       ClsOutF            Close the output file silently
          MOVE.B    D4,Quiet(A6)       Restore the quiet flag
          BRA.S     Abort7

Abort1    CMPI.B    #'N',D1            NAK packet ?
          BEQ.S     Abort2             Yes
          CMPI.B    #'T',D1            Timeout pseudo-packet ?
          BEQ.S     Abort3             Yes
          CMPI.B    #'Q',D1            Garbage pseudo-packet ?
          BEQ.S     Abort4             Yes
          CMP.B     PackNum(A6),D2     Packet out of sequence ?
          BNE.S     Abort5             Yes
          BSR       NewLine
          LEA       UkUxPStr(PC),A0    No, unknown or unexpected packet type
          BSR       ConWrite
          BRA.S     Abort7

Abort2    PEA       NAKRcStr(PC)       NAK received string
          BRA.S     Abort6
Abort3    PEA       TimLEStr(PC)       Timeout limit expired string
          BRA.S     Abort6
Abort4    PEA       GbPRcStr(PC)       Garbage packet received string
          BRA.S     Abort6
Abort5    PEA       POuOSStr(PC)       Packet out of sequence string
Abort6    BSR       NewLine
          LEA       TooMTStr(PC),A0    Point to the abort string
          BSR       ConWrite           Write it to the terminal line
          MOVEA.L   (A7)+,A0           Now write the last error string
          BSR       ConWrite
Abort7    BSR       NewLine            Start a new line
          SF        D0                 Return a negative completion code
          RTS

BadPack   MOVEQ     #AbortS,D7         This is for code reduction
          RTS

********************************* SndInit *****************************ok
*                                                                     *
*  Send Initiate, send this host's parameters and get other side's    *
*  back.                                                              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            D2.L destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
SndInit   LEA       Argumnt1(A6),A0    Pointer to file name
          BSR       ExpandFN           Expand it into a file names list
          TST.L     D0                 Check the returned number
          BLT.S     SndInit4           Too many files match
          BNE.S     SndInit1           Some files match, get the first one
          BSR       CRemTLoc           No files match, convert name to local
          BSR       ExpandFN           Try again the file name expansion
          TST.L     D0                 Check the returned number
          BLE.S     SndInit3           If no or too many files match, error

SndInit1  BSR       NextFil            Get the first file name into FilName
          TST.B     D0                 Check completion code
          BEQ.S     SndInit5           Failed, exit protocol (don't enter it)

          MOVEQ     #ClrInpBf,D0       Clear the input buffer
          MOVEQ     #HostLine,D1
          BSR       ChanCtrl           Call the channel control routine
          TST.B     Local(A6)          Are we running in local mode ?
          BNE.S     SndInit2           Yes, no need for delay
          MOVE.B    Delay(A6),D0       Load initial delay before sending
          BSR       Sleep              Sleep the requested amount of time
SndInit2  BSR       SndParm            Fill up init info packet
          MOVEQ     #'S',D1            Send an S packet
          MOVEQ     #0,D2              Packet number (always 0)
          MOVE.B    D0,D3              Packet length as returned by SndParm
          BSR       SndPack            Ok, send now

          BSR       InpPack            What was the reply ?
          CMPI.B    #'Y',D1            ACK ?
          BNE       BadPack            No, bad packet
          BSR       RdParam            Yes, get other side's init info
          BSR       BumpPckN           Bump packet count
          MOVE.B    BlChkRq(A6),BlChkUs(A6) Setup block check type
          MOVE.B    RtryPack(A6),Retry(A6) Setup retry limit for normal packets
          MOVEQ     #OpnFileS,D7       OK, switch state to Open-File
          RTS

SndInit3  LEA       FNFStr(PC),A1      Point to file not found error message
          BRA.S     SndInit6           Join common part
SndInit4  LEA       TMFStr(PC),A1      Point to too many files error message
          BRA.S     SndInit6           Join common part
SndInit5  LEA       NRFStr(PC),A1      Point to no readable files error message
SndInit6  MOVEQ     #ErrMessg,D0       Give bad news
          BSR       Screen
          MOVEQ     #CompletS,D7       Enter complete state
          RTS

********************************* OpnFile *****************************ok
*                                                                     *
*  Open File or set up text to send.                                  *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D7.L next state of the automaton         *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
OpnFile   LEA       FilName(A6),A0     Point to file name
          BSR       OpnInpF            Try to open the file
          TST.B     D0                 Success ?
          BEQ.S     OpnFile1           No
          MOVEQ     #SndFileS,D7       Yes switch state to Send-File
          RTS

OpnFile1  LEA       FlOErStr(PC),A1    Point to open failed error message
          MOVEQ     #ErrMessg,D0       Give bad news
          BSR       Screen             Screen return the pointer unchanged
          BSR       SndEPack           Send an Error packet
          MOVEQ     #AbortS,D7         Abort
          RTS

******************************** SndFile ******************************ok
*                                                                     *
*  Send File Header.                                                  *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
SndFile   LEA       FilName(A6),A1     Point to the local file name
          MOVEQ     #SFilName,D0       Display it on the screen
          BSR       Screen
          LEA       Argumnt2(A6),A0    Point to the file send-as name
          TST.B     (A0)               Has it been specified ?
          BNE.S     SndFile1           Yes, send it in the packet data field
          LEA       FilName(A6),A1     No, same as local file name
          MOVEQ     #CmdBufLn,D0       Copy it to Argumnt2
          BSR       CopyStr
          TST.B     FNameCnv(A6)       Are we converting file names ?
          BEQ.S     SndFile1           No
          BSR       CLocTRem           Yes, so convert file name in Argumnt2

SndFile1  MOVEA.L   A0,A1              Display the file send-as name
          MOVEQ     #FlAsName,D0
          BSR       Screen
          BSR       EncStrng           Encode the file name into the data field
          CLR.B     (A0)               Finally nullify Argumnt2

          MOVEQ     #'F',D1            Send a F packet
          MOVE.B    PackNum(A6),D2     Packet number
          MOVE.B    Size(A6),D3        Packet length
          BSR       SndPack            Ok, send now

          BSR       InpPack            What was the reply ?
          CMPI.B    #'Y',D1            ACK ?
          BNE       BadPack            No, bad packet
          BSR       BumpPckN           Bump packet counters
          MOVE.B    #1,First(A6)       Init file character lookahead
          BSR       GetPack            Get the first buffer of data
          TST.B     D0                 Null file ?
          BNE.S     SndFile4           No, enter Send-Data state
          MOVEQ     #SendEOFS,D7       Enter Send-EOF state
          RTS
SndFile4  MOVEQ     #SndDataS,D7       Switch state to Send-Data
          RTS

******************************** SndData ******************************ok
*                                                                     *
*  Send File Data.                                                    *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B destroyed                           *
*                            D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                                                                     *
***********************************************************************
SndData   MOVE.B    CtlXSeen(A6),D0    Current file or file group cancelled ?
          OR.B      CtlZSeen(A6),D0
          BNE.S     SndData4           Yes
          MOVEQ     #'D',D1            No, send a D packet
          MOVE.B    PackNum(A6),D2     Packet number
          MOVE.B    Size(A6),D3        Packet length
          BSR       SndPack            Ok, send now
          BSR       InpPack            What was the reply ?

SndData2  CMPI.B    #'Y',D1            ACK ?
          BNE       BadPack            No, bad packet
          BSR       BumpPckN           Bump packet count
          TST.B     D3                 Empty ACK packet ?
          BEQ.S     SndData5           Yes, get next data buffer
          MOVE.B    DataBuf(A6),D0     No, get first character of data buffer
          CMPI.B    #'X',D0            File interrupt directive ?
          SEQ       CtlXSeen(A6)       Yes, set the appropriate flag
          BEQ.S     SndData4           And enter, Send-EOF state
          CMPI.B    #'Z',D0            File group interrupt directive ?
          SEQ       CtlZSeen(A6)       Yes, set the appropriate flag
          BNE.S     SndData5           No, ignore ACK contents
SndData4  MOVEQ     #SendEOFS,D7       Enter Send-EOF state
          RTS
SndData5  BSR       GetPack            Get next data buffer
          TST.B     D0                 EOF or end of memory string ?
          BEQ.S     SndData4           Yes, switch state to Send-EOF
          RTS                          No, remain in this state

******************************** SendEOF ******************************ok
*                                                                     *
*  Send End-Of-File.                                                  *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B destroyed                           *
*                            D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.L destroyed                           *
*                            D7.L next state of the automaton         *
*                                                                     *
***********************************************************************
SendEOF   BSR       ClsInpF            Close the input file
          MOVEQ     #'Z',D1            Send a Z packet
          MOVE.B    PackNum(A6),D2     Packet number
          MOVE.B    CtlXSeen(A6),D0    Current file or file group cancelled ?
          OR.B      CtlZSeen(A6),D0
          BEQ.S     SendEOF1           No
          MOVE.B    #'D',DataBuf(A6)   Yes, put discard directive in data space
          MOVEQ     #1,D3              Packet length (1, Z/D packet)
          BRA.S     SendEOF2
SendEOF1  MOVEQ     #0,D3              Packet length (0, empty Z packet)
SendEOF2  BSR       SndPack            OK, send now

          BSR       InpPack            What was the reply ?
          CMPI.B    #'Y',D1            ACK ?
          BNE       BadPack            No, bad packet
          BSR       BumpPckN           Bump packet counters

          BSR       NextFil            Look for another file
          TST.B     D0                 Is there ?
          BEQ.S     SendEOF3           No, end of transaction
          MOVEQ     #OpnFileS,D7       Yes, send it
          RTS
SendEOF3  MOVEQ     #SendEOTS,D7       Enter Send-EOT state
          RTS

******************************** SendEOT ******************************ok
*                                                                     *
*  Send Break (EOT).                                                  *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.L destroyed                           *
*                            D7.L next state of the automaton         *
*                                                                     *
***********************************************************************
SendEOT   MOVEQ     #'B',D1            Send a B packet
          MOVE.B    PackNum(A6),D2     Packet number
          MOVEQ     #0,D3              Packet length
          BSR       SndPack            Ok, send now
          CLR.B     NextPckN(A6)       If the expected ACK lost, the next
*                                      packet from the receiver will be NAK(0)
          BSR       InpPack            What was the reply ?
          CMPI.B    #'Y',D1            ACK ?
          BNE       BadPack            No, bad packet
          MOVEQ     #CompletS,D7       Yes, enter Complete state
          RTS

********************************* RecInit *****************************ok
*                                                                     *
*  Receive Initialization.                                            *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.L destroyed                           *
*                            D2.L destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                                                                     *
***********************************************************************
RecInit   BSR       InpPack            Try to get a packet
          CMPI.B    #'S',D1            Send-Init packet received ?
          BNE       BadPack            No, bad packet
          BSR       RdParam            Get the other side's init data
          BSR       SndParm            Fill up packet with my init info
          MOVEQ     #'Y',D1            ACK my parameters
          MOVEQ     #0,D2              Packet number (0)
          MOVE.B    D0,D3              Packet length as returned by SndParm
          BSR       SndPack            OK, send now
          BSR       BumpPckN           Bump packet number, modulo 64
          MOVE.B    BlChkRq(A6),BlChkUs(A6) Setup block check type
          MOVE.B    RtryPack(A6),Retry(A6) Setup retry limit for normal packets
          MOVEQ     #RecFileS,D7       Enter Receive-File state
          RTS

********************************* RecFile *****************************ok
*                                                                     *
*  Receive File Header.                                               *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.B destroyed                           *
*                            D7.L next state of the automaton         *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
RecFile   BSR       InpPack            Try to get a packet

          CMPI.B    #'X',D1            Send-File packet received ?
          BEQ       RecFile4           Yes
          CMPI.B    #'B',D1            Break packet received ?
          BEQ       RecFile5           Yes
          CMPI.B    #'F',D1            Send-File packet received ?
          BNE       BadPack            No, abort

          CLR.B     CmdBfPnt(A6)       Yes, prepare CmdBuf to receive file name
          LEA       CmdBfOut(PC),A0    File name decoded to CmdBuf
          BSR       Decode

          LEA       CmdBuf(A6),A0      Pointer to the file name just decoded
          TST.B     (A0)               The F packet was null ?
          BNE.S     RecFile1           No
          LEA       NoNamStr(PC),A1    Yes, provide a default name
          MOVEQ     #CmdBufLn,D0       Copy it to CmdBuf
          BSR       CopyStr
RecFile1  MOVEA.L   A0,A1              Display the file name on the screen
          MOVEQ     #RFilName,D0       Load the appropriate request code
          BSR       Screen             Call the screen handler
          LEA       Argumnt2(A6),A1    Check for alternate file name
          TST.B     (A1)               Has been specified ?
          BEQ.S     RecFile2           No
          MOVEQ     #CmdBufLn,D0       Yes, copy it to CmdBuf
          BSR       CopyStr
          CLR.B     (A1)               Nullify Argumnt2
RecFile2  LEA       FilName(A6),A1     Return here the actual name
          BSR       OpnOutF            Try to open (create) the file
          TST.B     D0                 Check the completion code
          BEQ.S     RecFile3           Open fails
          MOVEA.L   A1,A0              Open succeeds, here is the actual name
          MOVEQ     #FlAsName,D0       Display it on the screen
          BSR       Screen
          BSR       EncStrng           Encode the file name into the data field
          MOVEQ     #'Y',D1            Send an ACK packet
          MOVE.B    PackNum(A6),D2     Packet number
          MOVE.B    Size(A6),D3        Packet length
          BSR       SndPack            Ok, send now
          BSR       BumpPckN           Bump packet counters
          MOVEQ     #RecDataS,D7       Enter Receive-Data state
          RTS

RecFile3  LEA       FlCrEStr(PC),A1    Point to open failed error message
          MOVEQ     #ErrMessg,D0       Give bad news
          BSR       Screen             Screen return the pointer unchanged
          BSR       SndEPack           Send an Error packet
          MOVEQ     #AbortS,D7         Abort
          RTS

RecFile4  ST        TermOut(A6)        Set the terminal output flag
          BSR       SendACK            Acknowledge
          MOVEQ     #RecDataS,D7       Enter Receive-Data state
          RTS

RecFile5  BSR       SendACK            Acknowledge
          MOVEQ     #CompletS,D7       Enter Complete state
          RTS

********************************* RecData *****************************ok
*                                                                     *
*  Receive File Data.                                                 *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.L destroyed                           *
*                            D7.L next state of the automaton         *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
RecData   BSR       InpPack            Try to get a packet

          CMPI.B    #'Z',D1            EOF packet received ?
          BEQ.S     RecData6           Yes
          CMPI.B    #'D',D1            Send-Data packet received ?
          BNE       BadPack            No, bad packet

          TST.B     TermOut(A6)        Output to the terminal channel wanted ?
          BEQ.S     RecData1           No, file output
          LEA       ConOut(PC),A0      Yes
          BRA.S     RecData2
RecData1  LEA       FileOut(PC),A0     Address of the file output function
RecData2  BSR       Decode             Decode packet and output it
          LEA       DataBuf(A6),A0     Pointer to data buffer
          TST.B     CtlXSeen(A6)       File transfer interrupt request ?
          BEQ.S     RecData3           No, look for group transfer interrupt
          MOVE.B    #'X',(A0)+         Put "X" in the ACK packet data space
          BRA.S     RecData4
RecData3  TST.B     CtlZSeen(A6)       File group transfer interrupt request ?
          BEQ.S     RecData5           No, send a normal (empty) ACK packet
          MOVE.B    #'Z',(A0)+         Put "Z" in the ACK packet data space
RecData4  CLR.B     (A0)+              Mark end of data
          MOVEQ     #'Y',D1            ACK packet type
          MOVE.B    PackNum(A6),D2     Packet number
          MOVEQ     #1,D3              Packet length (1, "X" or "Z")
          BSR       SndPack            OK, send now
          BSR       BumpPckN           Bump packet number, modulo 64
          RTS                          Return, state unchanged

RecData5  BSR       SendACK            Acknowledge
          RTS                          Return, state unchanged

RecData6  TST.B     CtlXSeen(A6)       File transfer interrupted ?
          BNE.S     RecData7           Yes, close file
          TST.B     D3                 Empty Z packet ?
          BEQ.S     RecData7           Yes, close file
          CMPI.B    #'D',DataBuf(A6)   Discard directive ?
          SEQ       CtlXSeen(A6)       Set flag for ClsOutF
RecData7  BSR       ClsOutF            Close the output file
          SF        CtlXSeen(A6)       Reset flag, necessary for next file
          BSR       SendACK            Acknowledge
          MOVEQ     #RecFileS,D7       Enter Receive-File state
          RTS

          ends
          END
<<< k6opsf.asm >>>
          nam       Kermit68K
          ttl       Parser subroutines module

*         Kermit68K: source file K68PSF
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68ParserSubs,0,0,Edition,0,0

******************************** ParsWrd ******************************ok
*                                                                     *
*  Parse a word string.                                               *
*                                                                     *
*         Entry conditions : A0.L points to the target string         *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*         Exit  conditions : A0.L points to the last byte of          *
*                                 the target string                   *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                            D0.B completion code                     *
*                                                                     *
*                            -3 nothing to look up (source was null)  *
*                             0 all ok                                *
*                                                                     *
***********************************************************************
ParsWrd:  BSR      SkipSpr             Skip leading separators
          TST.B    (A5)                Null source ?
          BEQ.S    ParsWrd4            Yes, return this
ParsWrd1  MOVE.B   (A5)+,D0            No, get the first character
          BEQ.S    ParsWrd2            End of line, exit loop
          CMPI.B   #' ',D0             Blank ?
          BEQ.S    ParsWrd3            Yes, exit loop
          CMPI.B   #Asc_HT,D0          Tab ?
          BEQ.S    ParsWrd3            Yes, exit loop
          MOVE.B   D0,(A0)+            No, store the character
          BRA.S    ParsWrd1            Loop until end of word
ParsWrd2  SUBQ.L   #1,A5               Backup line pointer
ParsWrd3  CLR.B    (A0)                Terminate target
          MOVEQ    #0,D0               Return positive completion code
          RTS
ParsWrd4  CLR.B    (A0)                Terminate target
          MOVEQ    #-3,D0              Return null source completion code
          RTS

******************************** ParsTxt ******************************ok
*                                                                     *
*  Parse a text string, quoted or unquoted, this is to allow the      *
*  specification of trailing delimiters.                              *
*                                                                     *
*         Entry conditions : A0.L points to the target string         *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*         Exit  conditions : A0.L points to the last byte of          *
*                                 the target string                   *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                            D0.B completion code                     *
*                            D1.B destroyed                           *
*                                                                     *
*                            -3 nothing to look up (source was null)  *
*                             0 all ok                                *
*                                                                     *
***********************************************************************
ParsTxt:  BSR      SkipSpr             Skip leading separators
          MOVE.B   (A5)+,D0            Get the first character, null source ?
          BEQ.S    ParsTxt7            Yes, return null target cc
          CMPI.B   #$22,D0             Look for a quote character (")
          BEQ.S    ParsTxt1
          CMPI.B   #$27,D0             Look for a quote character (')
          BEQ.S    ParsTxt1
          CMPI.B   #$60,D0             Look for a quote character (`)
          BNE.S    ParsTxt2
ParsTxt1  MOVE.B   D0,D1               Save the quote character
          BRA.S    ParsTxt4
ParsTxt2  CLR.B    D1                  Clear the quote register
ParsTxt3  MOVE.B   D0,(A0)+            Write character to target string
ParsTxt4  MOVE.B   (A5)+,D0            Get a character
          BEQ.S    ParsTxt6            If end of line exit loop
          CMP.B    D0,D1               Quote character again ?
          BNE.S    ParsTxt3            No, write char to target, stay in loop
          CLR.B    (A0)                Yes, terminate target
ParsTxt5  MOVEQ    #0,D0               Return positive completion code
          RTS
ParsTxt6  MOVE.B   -(A5),(A0)          Backup line pointer and terminate target
          BRA.S    ParsTxt5            Return positive completion code
ParsTxt7  MOVE.B   -(A5),(A0)          Backup line pointer and terminate target
          MOVEQ    #-3,D0              Return null source completion code
          RTS

******************************** ParsNm *******************************ok
*                                                                     *
*  Parse a number.                                                    *
*                                                                     *
*         Entry conditions : D1.L range specification, lower bound    *
*                            D2.L range specification, upper bound    *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*         Exit  conditions : D0.L parsed number (if any)              *
*                            D1.B completion code                     *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*                            -3 nothing to parse (source was null)    *
*                            -2 number out of range                   *
*                            -1 illegal number specification          *
*                             0 all ok, number in D0.L                *
*                                                                     *
***********************************************************************
ParsNm:   MOVEM.L   D3-D6,-(A7)        Save working registers
          LEA       DataBuf(A6),A1     Pointer to temporary buffer
          MOVEA.L   A1,A0              Put here the parsed word
          BSR       ParsWrd            Get a word from the source line
          TST.B     D0                 Null source ?
          BLT       ParsNm12           Yes, return this condition code
          MOVEA.L   A1,A0              Set up for addressing
          CLR.L     D0                 Clear the number register
          CLR.L     D3                 Clear the character register
          MOVE.B    (A0)+,D3           Get the first character
          CMPI.B    #'$',D3            Hexadecimal ?
          BEQ.S     ParsNm1            Yes, set base register
          CMPI.B    #'\',D3            Octal ?
          BEQ.S     ParsNm2            Yes, set base register
          CMPI.B    #'%',D3            Binary ?
          BEQ.S     ParsNm3            Yes, set base register to binary
          MOVEQ     #10,D4             No, set base register to decimal
          BRA.S     ParsNm5
ParsNm1   MOVEQ     #16,D4             Set base register to hexadecimal
          BRA.S     ParsNm4
ParsNm2   MOVEQ     #8,D4              Set base register to octal
          BRA.S     ParsNm4
ParsNm3   MOVEQ     #2,D4              Set base register to binary
ParsNm4   MOVE.B    (A0)+,D3           Got a base specification, get next
          BEQ.S     ParsNm10           End of word, invalid number
ParsNm5   CMPI.B    #'-',D3            Look for a minus sign
          SEQ       D5                 Set a flag accordingly
          BNE.S     ParsNm6            Enter the conversion loop
          MOVE.B    (A0)+,D3           Got a minus sign, get next
          BEQ.S     ParsNm10           End of word, invalid number
ParsNm6   BSR       UppCase
          SUBI.B    #'0',D3            First offset
          BLT.S     ParsNm10           Less than '0', invalid number
          CMPI.B    #9,D3              Above 9 ?
          BLE.S     ParsNm7            No
          SUBQ.B    #7,D3              Yes, second offset
ParsNm7   CMP.B     D4,D3              Above the base value ?
          BGE.S     ParsNm10           Yes, invalid number specification
          MOVE.L    D0,D6              Make some computation
          MULU      D4,D0
          SWAP      D6
          MULU      D4,D6
          SWAP      D6
          CLR.W     D6
          ADD.L     D6,D0
          ADD.L     D3,D0
          MOVE.B    (A0)+,D3           Get the next character, if any
          BNE.S     ParsNm6            Repeat until end of word
          TST.B     D5                 Negative number ?
          BEQ.S     ParsNm8            No
          NEG.L     D0                 Yes, negate it
ParsNm8   CMP.L     D1,D0              Less than lower bound ?
          BLT.S     ParsNm11           Yes, return the proper cc
          CMP.L     D2,D0              Greater than upper bound ?
          BGT.S     ParsNm11           Yes, return the proper cc
          MOVEQ     #0,D1              Provide positive completion code
ParsNm9   MOVEM.L   (A7)+,D3-D6        Restore working registers
          RTS
ParsNm10  MOVEA.L   A1,A0              Pointer to the guilty word
          LEA       PrNmStr1(PC),A1    Pointer to the error message string
          BSR       ParsErr            Give the appropriate message
          MOVEQ     #-1,D1             Return invalid number cc
          BRA.S     ParsNm9
ParsNm11  MOVEA.L   A1,A0              Pointer to the guilty word
          LEA       PrNmStr2(PC),A1    Pointer to the error message string
          BSR       ParsErr            Give the appropriate message
          MOVEQ     #-2,D1             Return number out of range cc
          BRA.S     ParsNm9
ParsNm12  SUBA.L    A0,A0              No guilty word in this case
          LEA       PrNmStr3(PC),A1    Pointer to the error message string
          BSR       ParsErr            Give the appropriate message
          MOVEQ     #-3,D1             Return missing number specification cc
          BRA.S     ParsNm9

******************************** ParsKyW ******************************ok
*                                                                     *
*  Parse a keyword, giving, on error, appropriate messages.           *
*                                                                     *
*         Entry conditions : D1.B flag for mandatory keywords         *
*                            A1.L points to keywords table            *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
*                            -3 nothing to look up (source was null)  *
*                            -2 ambiguous keyword                     *
*                            -1 keyword not found                     *
*                            n >= 0 value associated with keyword     *
*                                                                     *
*                            D2.B destroyed                           *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                            A2.L destroyed                           *
*                                                                     *
***********************************************************************
ParsKyW:  LEA       DataBuf(A6),A2     Pointer to temporary buffer
          MOVEA.L   A2,A0              Put here the parsed word
          BSR       ParsWrd            Get a word from the source line
          MOVEA.L   A2,A0              Set up for addressing
          BSR       Lookup             Search the keyword in the given table
          TST.B     D0                 Some error condition reported ?
          BGE.S     ParsKyW5           No, return value in D0.B
          MOVE.B    D0,D2              Yes, save the completion code
          ADDQ.B    #1,D0              Unrecognized keyword ?
          BEQ.S     ParsKyW1           Yes, give error message
          ADDQ.B    #1,D0              Ambiguous keyword ?
          BEQ.S     ParsKyW2           Yes, give error message
          TST.B     D1                 No, missing keyword, was it mandatory ?
          BEQ.S     ParsKyW4           No, no message, return bad cc
          LEA       PrKyStr3(PC),A0    Yes, give missing keyword error message
          BSR       ConWrite           Write the message
          MOVEA.L   A1,A0              Write the requested object name
          BSR       ConWrite
          BSR       NewLine            Start a new line
          BRA.S     ParsKyW4           Newline and return
ParsKyW1  LEA       PrKyStr1(PC),A0    Give unrecognized keyword error message
          BRA.S     ParsKyW3           Join common part
ParsKyW2  LEA       PrKyStr2(PC),A0    Give ambiguous keyword error message
ParsKyW3  BSR       ConWrite           Write the error type string
          MOVEA.L   A1,A0              Write the requested object name
          BSR       ConWrite
          MOVEA.L   A2,A0              Write the guilty word
          SUBA.L    A1,A1              Error message already given
          BSR       ParsErr
ParsKyW4  MOVE.B    D2,D0              Restore the completion code from LookUp
ParsKyW5  RTS

******************************* ParsInF *******************************ok
*                                                                     *
*  Parse an input file name specification.                            *
*                                                                     *
*         Entry conditions : A0.L point to the target string          *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
*                            -3 nothing to parse (source was null)    *
*                            -2 illegal file name specification       *
*                             0 all ok                                *
*                                                                     *
*                            A1.L destroyed                           *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
***********************************************************************
ParsInF:  MOVEA.L   A0,A1              Save the target pointer
          BSR       ParsWrd            Get a word from the command line
          TST.B     D0                 Null source ?
          BLT.S     ParsInF2           Yes, return this
          MOVEA.L   A1,A0              Reload target pointer
          BSR       ChkWild            Check for wild characters
          TST.B     D0                 Wild filename ?
          BNE.S     ParsInF3           Yes, try to expand it
          BSR       ChkInpF            Check if file exists and is readable
          TST.B     D0                 Inexistent or unreadable file ?
          BLT.S     ParsInF5           Yes, give error message
ParsInF1  MOVEQ     #0,D0              No, all ok, return positive cc
ParsInF2  RTS
ParsInF3  BSR       ExpandFN           Try to expand the wild file name
          TST.L     D0                 Check the result
          BGT.S     ParsInF1           All ok, at least one match
          BLT.S     ParsInF4           Too many matches, give error message
          LEA       PrIFStr4(PC),A0    No matches, error
          BRA.S     ParsInF8           Join common part
ParsInF4  LEA       PrIFStr5(PC),A0    Notify overflow during name expansion
          BRA.S     ParsInF8           Join common part
ParsInF5  ADDQ.B    #1,D0              File not found ?
          BEQ.S     ParsInF6           Yes
          ADDQ.B    #1,D0              File not readable ?
          BEQ.S     ParsInF7           Yes
          LEA       PrIFStr3(PC),A0    No, read permission denied
          BRA.S     ParsInF8           Join common part
ParsInF6  LEA       PrIFStr1(PC),A0    File not found error message
          BRA.S     ParsInF8           Join common part
ParsInF7  LEA       PrIFStr2(PC),A0    File not readable error message
ParsInF8  EXG       A0,A1              Setup pointers
          BSR       ParsErr            Call the error messages routine
          MOVEQ     #-2,D0             Return a negative completion code
          RTS

******************************* ParsOuF *******************************ok
*                                                                     *
*  Parse an output file name specification.                           *
*                                                                     *
*         Entry conditions : A0.L point to the target string          *
*                            A5.L points to the current position      *
*                                 in the source line                  *
*                                                                     *
*         Exit  conditions : A5.L points to the current position      *
*                                 in the source line                  *
*                            D0.B completion code                     *
*                                                                     *
*                            -3 nothing to parse (source was null)    *
*                            -2 illegal output file name              *
*                             0 all ok                                *
*                                                                     *
***********************************************************************
ParsOuF:  MOVEA.L   A0,A1              Save the target pointer
          BSR       ParsWrd            Get a word from the command line
          TST.B     D0                 Null source ?
          BLT.S     ParsOuF1           Yes, return this
          MOVEA.L   A1,A0              Reload target pointer
          BSR       ChkWild            Check for wild characters
          TST.B     D0                 Wild filename ?
          BNE.S     ParsOuF2           Yes, give error message
          BSR       ChkOutF            Check if file can be created
          TST.B     D0                 Permission denied ?
          BLT.S     ParsOuF3           Yes, give error message
          MOVEQ     #0,D0              No, all ok, return positive cc
ParsOuF1  RTS
ParsOuF2  LEA       POuFStr1(PC),A0    Give wildcard not allowed error message
          BRA.S     ParsOuF4           Join common part
ParsOuF3  LEA       POuFStr2(PC),A0    Give permission denied error message
ParsOuF4  EXG       A0,A1              Setup pointers
          BSR       ParsErr            Call the error messages routine
          MOVEQ     #-2,D0             Return negative completion code
          RTS

******************************* ChkWild *******************************ok
*                                                                     *
*  Check a string for wildcard character presence.                    *
*                                                                     *
*         Entry conditions : A0.L points to the string to check       *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L points to the checked string        *
*                                                                     *
***********************************************************************
ChkWild:  MOVE.L    A0,-(A7)           Save the string pointer
ChkWild1  MOVE.B    (A0)+,D0           Get a character
          BEQ.S     ChkWild3           End of string, exit loop, return false
          CMPI.B    #'*',D0            Match-all wildcard character ?
          BEQ.S     ChkWild2           Yes, the file name is wild
          CMPI.B    #'?',D0            Match-one wildcard character ?
          BNE.S     ChkWild1           No, loop until end of string
ChkWild2  ST        D0                 Yes, exit loop, return true
ChkWild3  MOVE.L    (A7)+,A0           Restore the string pointer
          RTS

********************************* Lookup ******************************ok
*                                                                     *
*  Lookup a keyword in the given array of keywords.                   *
*                                                                     *
*         Entry conditions : A0.L points to the source string         *
*                                 null terminated                     *
*                            A1.L points to the keywords table        *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
*                            -3 nothing to look up (target was null)  *
*                            -2 ambiguous keyword                     *
*                            -1 keyword not found                     *
*                            n >= 0 value associated with keyword     *
*                                                                     *
*                            A0.L points to the source string         *
*                                 null terminated                     *
*                            A1.L points to the object name           *
*                                                                     *
***********************************************************************
Lookup    MOVEM.L   A2/D1-D4,-(A7)     Save working registers
          CLR.B     D1                 Clear matchs counter
          TST.B     (A0)               Null keyword ?
          BNE.S     Lookup2            No, continue
Lookup1   MOVE.B    (A1)+,D4           Yes, skip to end of table
          CMPI.B    #-1,D4             End of table ?
          BNE.S     Lookup1            No, loop
          MOVEQ     #-3,D0             Return nothing to look up cc
          BRA.S     Lookup8

Lookup2   MOVE.B    (A1)+,D4           Get the value associated to this word
          CMPI.B    #-1,D4             End of table ?
          BEQ.S     Lookup7            Yes, check if match(s) occurred
          MOVEA.L   A0,A2

Lookup3   MOVE.B    (A2)+,D3           Get next character from command line
          BEQ.S     Lookup4            End of word, match !
          BSR       UppCase            Upper case it for compare
          MOVE.B    (A1)+,D2           Get a character from table
          BEQ.S     Lookup2            End of word, no match, try the next
          CMP.B     D3,D2              Match ?
          BNE.S     Lookup5            No, skip to the next table element
          BRA.S     Lookup3            Yes, look to the next character

Lookup4   TST.B     (A1)               Match found, is a supermatch ?
          BEQ.S     Lookup6            Yes, stop searching
          ADDQ.B    #1,D1              No, increment matchs counter
          MOVE.B    D4,D0              Load the return value
Lookup5   MOVE.B    (A1)+,D2           Skip to next table element
          BNE.S     Lookup5            Skip characters until end of word
          BRA.S     Lookup2            Scan all the table elements

Lookup6   MOVE.B    D4,D0              Supermatch found, load the return value
          BRA.S     Lookup8

Lookup7   CMPI.B    #1,D1              Check matchs counter
          BLT.S     Lookup9            If no match return keyword not found cc
          BGT.S     Lookup10           More than 1, ambiguous keyword cc
Lookup8   MOVEM.L   (A7)+,A2/D1-D4     Restore working registers
          RTS
Lookup9   MOVEQ     #-1,D0             Return the keyword not found cc
          BRA.S     Lookup8
Lookup10  MOVEQ     #-2,D0             Return the ambiguous keyword cc
          BRA.S     Lookup8

********************************* ParsErr *****************************ok
*                                                                     *
*  Give a parsing error message.                                      *
*                                                                     *
*         Entry conditions : A0.L point to the guilty word            *
*                                 null terminated, no guilty word     *
*                                 to print if null pointer passed     *
*                            A1.L point to the error message, no      *
*                                 message to print if null pointer    *
*                                 passed                              *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                                                                     *
***********************************************************************
ParsErr:  EXG       A0,A1              Write the error string first, if any
          MOVE.L    A0,D1              Null pointer passed ?
          BEQ.S     ParsErr1           Yes, no error message
          BSR       ConWrite           No, write it
ParsErr1  MOVE.L    A1,D1              Null pointer passed ?
          BEQ.S     ParsErr4           Yes, no guilty word
          LEA       PrErStr1(PC),A0    No, point to separator string
          BSR       ConWrite           Write it to terminal
          MOVEQ     #'"',D0            Type the leading quotation mark
          BSR       ConOut
ParsErr2  MOVE.B    (A1)+,D0           And then the guilty word
          BEQ.S     ParsErr3           If end of word, exit loop
          BSR       ConOut             Write a character
          BRA.S     ParsErr2           And the next, if any
ParsErr3  MOVEQ     #'"',D0            Type the trailing quotation mark
          BSR       ConOut
ParsErr4  BSR       NewLine            Start a new line
          RTS

******************************* SkipSpr *******************************ok
*                                                                     *
*  Skip leading separators from the command line.                     *
*                                                                     *
*         Entry conditions : A5.L point to the current position       *
*                            in the command line                      *
*                                                                     *
*         Exit  conditions : D0.B destroyed                           *
*                            A5.L point to the current position       *
*                            in the command line                      *
*                                                                     *
***********************************************************************
SkipSpr   MOVE.B    (A5)+,D0           Get a character
          BEQ.S     SkipSpr1           End of buffer, exit
          CMPI.B    #' ',D0            Blank ?
          BEQ.S     SkipSpr            Yes, skip
          CMPI.B    #Asc_HT,D0         Tab ?
          BEQ.S     SkipSpr            Yes, skip
SkipSpr1  SUBQ.L    #1,A5              Backup line pointer
          RTS

          ends
          END
<<< k6opt2.asm >>>
          nam       Kermit68K
          ttl       Low-level protocol subroutines module

*         Kermit68K: source file K68PT2
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68ProtoFuncs2,0,0,Edition,0,0

******************************* TrnsInit ******************************ok
*                                                                     *
*  Initialize a transaction.                                          *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
TrnsInit: MOVE.B    #1,BlChkUs(A6)     Reset block check type to 1
          SF        Bit8Flag(A6)       Reset 8th bit quoting stuff
          MOVE.B    #1,NextPckN(A6)    Reset packet counters
          MOVE.B    #0,PackNum(A6)
          MOVE.B    #-1,PrevPckN(A6)
          SF        MStrFlag(A6)       Reset memory string flag
          CLR.L     MStrgPnt(A6)       Reset memory string pointer
          SF        CtlXSeen(A6)       Reset interrupts flag
          SF        CtlZSeen(A6)
          CLR.B     SendBuf(A6)        Clear send buffer
          CLR.B     FilName(A6)        Clear current file name
          MOVE.B    RtryInit(A6),Retry(A6) Initialize the retry limit
          CLR.L     ChrsSent(A6)       Clear the statistic variables
          CLR.L     ChrsRecd(A6)
          CLR.L     DChsSent(A6)
          CLR.L     DChsRecd(A6)
          CLR.L     PcksSent(A6)
          CLR.L     PcksRecd(A6)
          CLR.L     NAKsSent(A6)
          CLR.L     NAKsRecd(A6)
          RTS

*********************************** SetGCmd ***************************ok
*                                                                     *
*  Setup for generic commands.                                        *
*                                                                     *
*         Entry conditions : D0.B command type                        *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                            A2.L first  argument address, if any     *
*                            A3.L second argument address, if any     *
*                            A4.L third  argument address, if any     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                                                                     *
***********************************************************************
SetGCmd:  LEA       CmdBuf(A6),A1      Load pointer to command buffer
          MOVE.B    D0,(A1)+           Write command type
          CLR.B     (A1)               Terminate it
          MOVE.L    A2,D0              First argument pointer null ?
          BEQ.S     SetGCmd1           Yes, exit
          TST.B     (A2)               No, first argument null ?
          BEQ.S     SetGCmd1           Yes, exit
          MOVEA.L   A2,A0              Load pointer to first argument
          BSR       CpStrLn            Copy it to data buffer
          MOVE.L    A3,D0              Second argument pointer null ?
          BEQ.S     SetGCmd1           Yes, exit
          TST.B     (A3)               No, second argument null ?
          BEQ.S     SetGCmd1           Yes, exit
          MOVEA.L   A3,A0              Load pointer to second argument
          BSR       CpStrLn            Copy it to data buffer
          MOVE.L    A4,D0              Third argument pointer null ?
          BEQ.S     SetGCmd1           Yes, exit
          TST.B     (A4)               No, third argument null ?
          BEQ.S     SetGCmd1           Yes, exit
          MOVEA.L   A4,A0              Load pointer to third argument
          BSR       CpStrLn            Copy it to data buffer
SetGCmd1  MOVE.B    #'G',ServrCmd(A6)  Generic command packet type
          BSR       TrnsInit           Initialize the transaction
          RTS

********************************* Decode ******************************ok
*                                                                     *
*  Kermit packet decoding procedure, decodes from DataBuf and call an *
*  output function at the given address.                              *
*                                                                     *
*         Entry conditions : A0.L address of the output function      *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
Decode:   MOVEM.L   A1/D1-D3,-(A7)     Save working registers
          LEA       DataBuf(A6),A1     Pointer to data buffer
Decode1   MOVEQ     #1,D3              Setup the repeat counter
          MOVE.B    (A1)+,D0           Get a character
          BEQ.S     Decode9            Exit at end of buffer
          TST.B     ReptFlag(A6)       Repeat processing ?
          BEQ.S     Decode2            No
          CMP.B     ReptQuot(A6),D0    Yes, got a repeat prefix ?
          BNE.S     Decode2            No
          MOVE.B    (A1)+,D3           Yes, get the repeat count
          SUBI.B    #32,D3             Convert it ...
          MOVE.B    (A1)+,D0           ... and get the prefixed character
Decode2   MOVEQ     #$00,D1            Clear the 8th bit register
          TST.B     Bit8Flag(A6)       8th bit prefixing ?
          BEQ.S     Decode3            No
          CMP.B     Bit8Quot(A6),D0    Yes, got an 8th bit prefix ?
          BNE.S     Decode3            No
          MOVEQ     #$80,D1            Yes, remember this ...
          MOVE.B    (A1)+,D0           ... and get the prefixed character
Decode3   CMP.B     ICtlQuot(A6),D0    Got a control prefix ?
          BNE.S     Decode6            No
          MOVE.B    (A1)+,D0           Yes, get its operand
          MOVE.B    D0,D2              Make a copy
          ANDI.B    #$7F,D2            Only look at lower 7 bits
          CMPI.B    #$40,D2            Above Null ?
          BLT.S     Decode4            No, look for Delete
          CMPI.B    #$5F,D2            Yes, between Null and US ?
          BLE.S     Decode5            Yes, uncontrollify
Decode4   CMPI.B    #'?',D2            Delete ?
          BNE.S     Decode6            No, character not in control range
Decode5   EORI.B    #64,D0             Uncontrollify
Decode6   OR.B      D1,D0              OR in the 8th bit
          TST.B    Binary(A6)          Are we in binary mode ?
          BNE.S    Decode8             Yes, CRLF-nl mapping not needed
          CMPI.B   #Asc_CR,D0          Carriage Return ?
          BEQ.S    Decode1             Yes, discard it
          CMPI.B   #Asc_LF,D0          No, Line Feed ?
          BNE.S    Decode8             No
          MOVEQ    #NewLinCh,D0        Yes, convert it into newline character
          BRA.S     Decode8            Ok, ready for output
Decode7   JSR       (A0)               Call the output function
          TST.B     D1                 Check completion code
          BNE.S     Decode9            If failure return
          ADDQ.L    #1,DChsRecd(A6)    Increment data chars received this trans
          ADDQ.L    #1,TDChRecd(A6)    Increment total data characters received
Decode8   DBF       D3,Decode7         Output char repeat times (at least 1)
          BRA.S     Decode1
Decode9   MOVEM.L   (A7)+,A1/D1-D3     Restore working registers
          RTS

******************************** CmdBfOut *****************************ok
*                                                                     *
*  Output to command buffer, called by Decode.                        *
*                                                                     *
*         Entry conditions : D0.B character to output                 *
*                                                                     *
*         Exit  conditions : D1.B AllOk completion code (0)           *
*                                                                     *
***********************************************************************
CmdBfOut: MOVE.L    A0,-(A7)           Save register
          LEA       CmdBuf(A6),A0      Point to command buffer start address
          CLR.W     D1                 Clear the index register
          MOVE.B    CmdBfPnt(A6),D1    Load relative pointer to command buffer
          MOVE.B    D0,(A0,D1.W)       Write the character
          ADDQ.B    #1,D1              Increment the index register
          CLR.B     (A0,D1.W)          Make sure buffer is null-terminated
          MOVE.B    D1,CmdBfPnt(A6)    Save the index register
          MOVEQ     #AllOk,D1          Return a positive competion code (0)
          MOVE.L    (A7)+,A0           Restore register
          RTS

********************************* Encode ******************************ok
*                                                                     *
*  Kermit packet encoding procedure, encodes to DataBuf.              *
*                                                                     *
*         Entry conditions : D0.B character to be encoded             *
*                            D2.W current size of output data packet  *
*                                                                     *
*         Exit  conditions : D2.W current size of output data packet  *
*                            D1.L destroyed                           *
*                            D3.B destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
Encode:   LEA       DataBuf(A6),A1     Pointer to data buffer
          TST.B     ReptFlag(A6)       Repeat processing ?
          BEQ.S     Encode5            No, do prefixing
          CMP.B     Next(A6),D0        Current and next character are equal ?
          BNE.S     Encode4            No
          TST.B     First(A6)          Input in progress
          BNE.S     Encode4            No, first time called
          ADDQ.B    #1,ReptCnt(A6)     Increment the repeat counter
          CMPI.B    #94,ReptCnt(A6)    Below max ?
          BEQ.S     Encode2            No, max reached, must dump
          RTS                          Yes, just count and return

Encode1   ADDQ.B    #1,ReptCnt(A6)     More than 2 character to repeat
Encode2   MOVE.B    ReptQuot(A6),(A1,D2.W) Write the repeat quote
          ADDQ.W    #1,D2              Increment the pointer register
          MOVE.B    ReptCnt(A6),D1     Get the repeat count
          ADDI.B    #32,D1             Convert it into a character
          MOVE.B    D1,(A1,D2.W)       Write the repeat count
          ADDQ.W    #1,D2              Increment the pointer register
Encode3   CLR.B     ReptCnt(A6)        Reset the repeat counter
          BRA.S     Encode5            Done repeat processing, do prefixing
Encode4   CMPI.B    #1,ReptCnt(A6)     Run broken, only 2 ?
          BLT.S     Encode5            No, only 1, do it
          BGT.S     Encode1            No, more than 2
          MOVE.B    D0,D3              Yes, do the character twice, save char
          BSR.S     Encode5            Do it the first time
          MOVE.B    D3,D0              Restore the character
          CMP.B     OMPckSiz(A6),D2    Max packet size exceded ?
          BGT.S     Encode3            Yes, do the character again
          MOVE.B    D2,OldSize(A6)     No, update OldSize
          BRA.S     Encode3            Do the character again

Encode5   MOVEQ     #$7F,D1            Isolate ASCII part
          AND.B     D0,D1
          BTST      #7,D0              Do 8th bit prefixing if necessary
          BEQ.S     Encode6
          TST.B     Bit8Flag(A6)
          BEQ.S     Encode6
          MOVE.B    Bit8Quot(A6),(A1,D2.W) Write the 8th bit quote
          ADDQ.W    #1,D2              Increment the pointer register
          MOVE.B    D1,D0

Encode6   CMPI.B    #' ',D1            Do control prefixing if necessary
          BLT.S     Encode7
          CMPI.B    #Asc_Del,D1        Delete ?
          BNE.S     Encode8            No, character not in control range
Encode7   EORI.B    #64,D0             Uncotrollify
          BRA.S     Encode10

Encode8   CMPI.B    #MyCtlQot,D1       Prefix the control prefix
          BEQ.S     Encode10

          CMP.B     ReptQuot(A6),D1    If it's the repeat prefix ...
          BNE.S     Encode9
          TST.B     ReptFlag(A6)       ... quote it if doing repeat counts
          BEQ.S     Encode11
          BRA.S     Encode10

Encode9   CMP.B     Bit8Quot(A6),D1    Prefix the 8th bit prefix ...
          BNE.S     Encode11
          TST.B     Bit8Flag(A6)       ... if doing 8th-bit prefixes
          BEQ.S     Encode11

Encode10  MOVE.B    #MyCtlQot,(A1,D2.W) Write the control quote
          ADDQ.W    #1,D2              Increment the pointer register
Encode11  MOVE.B    D0,(A1,D2.W)       Finally, insert the character
          ADDQ.W    #1,D2              Increment the pointer register
          CLR.B     (A1,D2.W)          Mark the end
          RTS

********************************* SndParm *****************************ok
*                                                                     *
*  Fill the data buffer with my send-init parameters.                 *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L data length                         *
*                            D1.L destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
SndParm:  LEA       DataBuf(A6),A0     Pointer to send buffer
          MOVEQ     #32,D1             Load register for quick addition

          MOVE.B    IMPckSiz(A6),D0    Biggest packet I can receive
          ADD.B     D1,D0              Conversion into a printable character
          MOVE.B    D0,(A0)+           Put it into data buffer

          MOVE.B    OTimInt(A6),D0     When I want to be timed out
          ADD.B     D1,D0              Conversion into a printable character
          MOVE.B    D0,(A0)+           Put it into data buffer

          MOVE.B    IPadNumb(A6),D0    How much padding I need
          ADD.B     D1,D0              Conversion into a printable character
          MOVE.B    D0,(A0)+           Put it into data buffer

          MOVE.B    IPadChar(A6),D0    Padding character I want
          EORI.B    #64,D0             Uncontrollify it
          MOVE.B    D0,(A0)+           Put it into data buffer

          MOVE.B    IEOL(A6),D0        End-Of-Line character I want
          ADD.B     D1,D0              Conversion into a printable character
          MOVE.B    D0,(A0)+           Put it into data buffer

          MOVE.B    OCtlQuot(A6),(A0)+ Control-Quote character I send

          MOVE.B    Parity(A6),D0      Parity is enabled or the ...
          OR.B      Bit8Flag(A6),D0    ... 8th bit processing flag is on ?
          BEQ.S     SndParm1           No, no need for 8th bit quoting
          MOVE.B    #My8BQuot,(A0)+    Send my 8th bit quote character
          MOVE.B    Bit8Quot(A6),D0    Get quote
          CMPI.B    #'Y',D0            If other side say YES to do ...
          SEQ       Bit8Flag(A6)       ... 8th bit quoting
          BEQ.S     SndParm2
          BSR       ChkQuot            If other side specify a valid quote ...
          MOVE.B    D0,Bit8Flag(A6)    ... turn the 8th bit quoting flag on
          BRA.S     SndParm2
SndParm1  MOVE.B    #'Y',(A0)+         Normally just say we're willing
SndParm2  MOVE.B    BlChkRq(A6),D0     Block check type
          ADDI.B    #'0',D0            Conversion into a printable character
          MOVE.B    D0,(A0)+           Send it
          MOVE.B    #MyRptQot,(A0)+    Do repeat counts
          CLR.B     (A0)               Terminator
          MOVEQ     #9,D0              Return length
          RTS

******************************** RdParam ******************************ok
*                                                                     *
*  Get the other host's send-init parameters.                         *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B destroyed                           *
*                            D1.B destroyed                           *
*                            D2.L destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
RdParam:  LEA       DataBuf(A6),A0     Pointer to data buffer
          MOVEQ     #32,D2             Load register for quick subtraction

          MOVE.B    #DefMxPSz,OMPckSiz(A6) Maximum send packet size
          MOVE.B    #DefTmOut,ITimInt(A6)  When I should time out
          MOVE.B    #DefPadNm,OPadNumb(A6) Number of pads to send
          MOVE.B    #DefPadCr,OPadChar(A6) Padding character to send
          MOVE.B    #DefEOL,OEOL(A6)       EOL character I must send
          MOVE.B    #DefCtlQt,ICtlQuot(A6) Incoming data quote character
          MOVE.B    Bit8Flag(A6),D1        Save 8th bit processing flag
          SF        Bit8Flag(A6)           No 8th bit quoting by default
          MOVE.B    #1,BlChkRq(A6)         Block check type requested
          SF        ReptFlag(A6)           No repeat processing by default

          MOVE.B    (A0)+,D0           Maximum send packet size
          BEQ       RdParam9
          SUB.B     D2,D0
          TST.B     SndPSFlg(A6)       Override privilege ?
          BEQ.S     RdParam1           No, continue
          CMPI.B    #10,D0             Yes, less than 10 ?
          BLT.S     RdParam2           Yes, leave unchanged the default value
RdParam1  MOVE.B    D0,OMPckSiz(A6)    No, update

RdParam2  MOVE.B    (A0)+,D0           When I should time out
          BEQ       RdParam9
          SUB.B     D2,D0
          TST.B     TimInFlg(A6)       Override privilege ?
          BEQ.S     RdParam3           No, continue
          TST.B     D0                 Yes, less than 0 ?
          BLT.S     RdParam4           Yes, leave unchanged the default value
RdParam3  MOVE.B    D0,ITimInt(A6)     No, update

RdParam4  MOVE.B    (A0)+,D0           Number of pads to send
          BEQ       RdParam9
          SUB.B     D2,D0
          MOVE.B    D0,OPadNumb(A6)

          MOVE.B    (A0)+,D0           Padding character to send
          BEQ.S     RdParam9
          EORI.B    #64,D0
          MOVE.B    D0,OPadChar(A6)

          MOVE.B    (A0)+,D0           EOL character I must send
          BEQ.S     RdParam9
          SUB.B     D2,D0
          CMPI.B    #Asc_STx,D0        Valid range EOL character ?
          BCS.S     RdParam5           No, leave unchanged the default value
          CMPI.B    #Asc_US,D0         Valid range EOL character ?
          BHI.S     RdParam5           No, leave unchanged the default value
          MOVE.B    D0,OEOL(A6)

RdParam5  MOVE.B    (A0)+,D0           Incoming data quote character
          BEQ.S     RdParam9
          MOVE.B    D0,ICtlQuot(A6)

          MOVE.B    (A0)+,D0           8th bit quote character
          BEQ.S     RdParam9
          MOVE.B    D0,Bit8Quot(A6)
          CMPI.B    #'Y',D0            If flag off, then turn it on ...
          BNE.S     RdParam6           ... if other side has asked us to
          OR.B      Parity(A6),D1      ... or if we need it on
          BEQ.S     RdParam7
          ST        Bit8Flag(A6)
          MOVE.B    #My8BQuot,Bit8Quot(A6)
          BRA.S     RdParam7
RdParam6  BSR       ChkQuot
          MOVE.B    D0,Bit8Flag(A6)

RdParam7  MOVE.B    (A0)+,D0           Block check type
          BEQ.S     RdParam9
          SUBI.B    #'0',D0            Range adjust
          CMPI.B    #1,D0              Less than 1 ?
          BCS.S     RdParam8           Yes, invalid
          CMPI.B    #3,D0              Greater than 3 ?
          BHI.S     RdParam8           Yes, invalid
          MOVE.B    D0,BlChkRq(A6)     Ok, store block check type requested

RdParam8  MOVE.B    (A0)+,D0           Repeat prefix
          BEQ.S     RdParam9
          MOVE.B    D0,ReptQuot(A6)
          BSR       ChkQuot
          MOVE.B    D0,ReptFlag(A6)
RdParam9  RTS

******************************** Check1 *******************************ok
*                                                                     *
*  Perform a type 1 block check.                                      *
*                                                                     *
*         Entry conditions : A0.L pointer to string buffer            *
*                                                                     *
*         Exit  conditions : D0.B type 1 block check                  *
*                                                                     *
***********************************************************************
Check1:   MOVE.W    D1,-(A7)           Save working register
          BSR       Check2             Compute numeric sum
          MOVE.W    D0,D1              Compute a type 1 checksum
          ANDI.W    #192,D1
          LSR.W     #6,D1
          ADD.W     D1,D0
          ANDI.W    #63,D0
          MOVE.W    (A7)+,D1           Restore working register
          RTS

******************************** Check2 *******************************ok
*                                                                     *
*  Perform a type 2 block check.                                      *
*                                                                     *
*         Entry conditions : A0.L pointer to string buffer            *
*                                                                     *
*         Exit  conditions : D0.W type 2 block check (numeric sum).   *
*                                                                     *
***********************************************************************
Check2:   MOVE.W    D1,-(A7)           Save working register
          CLR.W     D1                 Clear the sum register
          CLR.W     D0
Check21   MOVE.B    (A0)+,D0           Get a character
          BEQ.S     Check22            Exit if EOL
          BSR       HndlPar            Handle parity
          ADD.W     D0,D1              Sum
          BRA.S     Check21            Repeat until EOL
Check22   MOVE.W    D1,D0              Return numeric sum
          MOVE.W    (A7)+,D1           Restore working register
          RTS

******************************** Check3 *******************************ok
*                                                                     *
*  Perform a type 3 block check, calculates the 16-bit CRC using a    *
*  byte oriented tableless algorithm invented by Andy Lowry from      *
*  Columbia University. The magic number $1081 is derived from the    *
*  CRC-CCITT polynomial x^16+x^12+x^5+1.                              *
*                                                                     *
*         Entry conditions : A0.L pointer to string buffer            *
*                                                                     *
*         Exit  conditions : D0.L type 3 block check (CRC-CCITT).     *
*                                                                     *
***********************************************************************
Check3:   MOVEM.L   D1-D3,-(A7)        Save working registers
          CLR.L     D1                 Clear character register
          CLR.L     D2                 Clear CRC register
Check31   MOVE.B    (A0)+,D0           Get a character
          BEQ.S     Check32            Null, end of string buffer
          BSR       HndlPar            Remove parity bit if necessary
          MOVE.B    D0,D1              Load the character register
          MOVE.L    D1,D3              Low order nibble
          EOR.L     D2,D3
          MOVEQ     #$0F,D0
          AND.L     D0,D3
          ASR.L     #4,D2
          MULU      #$1081,D3
          EOR.L     D3,D2
          MOVE.L    D1,D3              High order nibble
          LSR.L     #4,D3
          EOR.L     D2,D3
          MOVEQ     #$0F,D0
          AND.L     D0,D3
          ASR.L     #4,D2
          MULU      #$1081,D3
          EOR.L     D3,D2
          BRA.S     Check31            Repeat until end of string buffer
Check32   MOVE.L    D2,D0              Return CRC-CCITT
          MOVEM.L   (A7)+,D1-D3        Restore working registers
          RTS

******************************** BumpPckN *****************************ok
*                                                                     *
*  Bump packet counters.                                              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
BumpPckN: MOVE.B    PackNum(A6),PrevPckN(A6) Save previous packet number
          MOVE.B    NextPckN(A6),PackNum(A6) Update current packet number
          ADDQ.B    #1,NextPckN(A6)    Increment next packet number
          ANDI.B    #63,NextPckN(A6)   Modulo 64
          RTS

*********************************** CpStrLn ***************************ok
*                                                                     *
*  Copy a null terminated string to a buffer adding a leading         *
*  encoded character count.                                           *
*                                                                     *
*         Entry conditions : A0.L source string buffer address        *
*                            A1.L target buffer address               *
*                                                                     *
*         Exit  conditions : A1.L target buffer next char address     *
*                            D0.L destroyed                           *
*                            D1.B destroyed                           *
*                                                                     *
***********************************************************************
CpStrLn:  MOVEQ     #0,D0              Preset the counter/index register
CpStrLn1  MOVE.B    (A0)+,1(A1,D0.W)   Move a character
          BEQ.S     CpStrLn2           Exit on end of string
          ADDQ.W    #1,D0              Increment the counter/index register
          BRA.S     CpStrLn1           Loop for all characters
CpStrLn2  MOVE.B    D0,D1              Get the length
          BEQ.S     CpStrLn3           Return if source was null
          ADDI.B    #32,D1             Encode length
          MOVE.B    D1,(A1)            Write it on the first target buffer byte
          LEA       1(A1,D0.W),A1      Address of next available buffer byte
CpStrLn3  RTS

******************************** ChkQuot ******************************ok
*                                                                     *
*  Check if a character is a valid quote.                             *
*                                                                     *
*         Entry conditions : D0.B character to check                  *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
ChkQuot   CMPI.B    #'!',D0
          BCS.S     ChkQuot2
          CMPI.B    #'>',D0
          BLS.S     ChkQuot1
          CMPI.B    #'`',D0
          BCS.S     ChkQuot2
          CMPI.B    #$7E,D0
ChkQuot1  SLS       D0
          RTS
ChkQuot2  SF        D0
          RTS

          ends
          END
<<< k6optf.asm >>>
          nam       Kermit68K
          ttl       Protocol subroutines module

*         Kermit68K: source file K68PTF
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68ProtoFuncs,0,0,Edition,0,0

******************************** NextFil ******************************ok
*                                                                     *
*  Try to get the next file name copying it to FilName.               *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
NextFil:  TST.B     CtlZSeen(A6)       Interrupt flag setted ?
          BNE.S     NextFil2           Yes, return with bad completion code
NextFil1  LEA       FilName(A6),A0     Points to file name target string
          BSR       GetNxtF            Try to get the next file name
          TST.B     D0                 Check the completion code
          BEQ.S     NextFil2           No files, return with bad cc
          BSR       ChkInpF            Check if file is readable
          TST.B     D0                 Ok ?
          BEQ.S     NextFil3           Yes, return this
          MOVEQ     #FlSkippd,D0       No, notify that we are skipping it
          BSR       Screen
          BRA.S     NextFil1           Try another
NextFil2  SF        D0                 Set a bad completion code
          RTS
NextFil3  ST        D0
          RTS

******************************** SndPack ******************************ok
*                                                                     *
*  Send a packet.                                                     *
*                                                                     *
*         Entry conditions : D1.B packet type                         *
*                            D2.B packet number                       *
*                            D3.B packet length                       *
*                                                                     *
*         Exit  conditions : D4.W destroyed                           *
*                            D5.L destroyed                           *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                                                                     *
***********************************************************************
SndPack:  LEA       SendBuf(A6),A1     Packet buffer start
          MOVEQ     #32,D5             Load register for quick addition

          MOVE.B    OStPckCh(A6),(A1)+ Packet marker

          MOVE.B    D3,D0              Packet length
          ADDQ.B    #2,D0              Add 2 + block_check_type to packet ...
          ADD.B     BlChkUs(A6),D0     length to obtain the character count
          ADD.B     D5,D0              and convert it into a printable character
          MOVE.B    D0,(A1)+           Send the character count

          ADD.B     D5,D2              Make the packet number printable
          MOVE.B    D2,(A1)+           Send the packet number

          MOVE.B    D1,(A1)+           Send the packet type
          MOVE.B    D1,SendType(A6)    And save it for echos removal

          LEA       DataBuf(A6),A0     Pointer to data buffer
          CLR.W     D0                 Clear the counter register
          MOVE.B    D3,D0              Data length
          BRA.S     SndPack2           Loop for all data characters
SndPack1  MOVE.B    (A0)+,(A1)+        Get a character and put it in the packet
SndPack2  DBF       D0,SndPack1        Repeat

          CLR.B     (A1)               Mark end for block check

          LEA       SendBuf+1(A6),A0   First char for checksum computation
          MOVE.B    BlChkUs(A6),D0     Block check type in use
          SUBQ.B    #1,D0              Type 1 block check ?
          BNE.S     SndPack3           No, try another
          BSR       Check1             Yes, compute it
          ADD.B     D5,D0              Convert the checksum into printable
          MOVE.B    D0,(A1)+           Send it
          BRA.S     SndPack5           Join common part

SndPack3  SUBQ.B    #1,D0              Type 2 block check ?
          BNE.S     SndPack4           No, type 3 block check
          BSR       Check2             Yes, compute it
          MOVE.B    D0,D4              Save the lower portion of the result
          LSR.W     #6,D0              Process bits 6 --> 11, right adjusting
          ANDI.B    #$3F,D0            Mask extra bits
          ADD.B     D5,D0              Conversion into a printable character
          MOVE.B    D0,(A1)+           Send the first character
          MOVE.B    D4,D0              Reload the copy
          ANDI.B    #$3F,D0            Now bits 0 --> 5
          ADD.B     D5,D0              Conversion into a printable character
          MOVE.B    D0,(A1)+           Send the second character
          BRA.S     SndPack5           Join common part

SndPack4  BSR       Check3             Compute a type 3 block check
          MOVE.W    D0,D4              Make a copy of the result
          LSR.W     #8,D0              Process bits 12 --> 15, right adjusting
          LSR.W     #4,D0              Right adjusting
          ADD.B     D5,D0              Conversion into a printable character
          MOVE.B    D0,(A1)+           Send the first character
          MOVE.W    D4,D0              Reload the copy
          LSR.W     #6,D0              Now process bits 6 --> 11, right adjust
          ANDI.B    #$3F,D0            Mask extra bits
          ADD.B     D5,D0              Conversion into a printable character
          MOVE.B    D0,(A1)+           Send the second character
          MOVE.B    D4,D0              Reload the lower portion of the result
          ANDI.B    #$3F,D0            Now bits 0 --> 5
          ADD.B     D5,D0              Conversion into a printable character
          MOVE.B    D0,(A1)+           Send the third character

SndPack5  MOVE.B    OEOL(A6),(A1)+     Extra-packet line terminator
          CLR.B     (A1)               End-Of-Buffer marker
          BSR       TxPackt            Transmit the packet now prepared
          MOVEQ     #PackType,D0       Display the packet type on the screen
          BSR       Screen
          RTS

******************************** RdPack *******************************ok
*                                                                     *
*  Attempts to read a packet.                                         *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.B packet type or pseudo-type          *
*                            D2.B packet number                       *
*                            D3.B packet length                       *
*                            D5.L destroyed                           *
*                            D6.L destroyed                           *
*                            A0.L destroyed                           *
*                            A1.L destroyed                           *
*                            A2.L destroyed                           *
*                                                                     *
***********************************************************************
RdPack:   MOVE.L    D4,-(A7)           Save working register
          SUBQ.L    #4,A7              Allocate some space on the stack
          MOVEQ     #3-1,D6            Try 3 times to get a line that has
RdPack1   BSR       InpLine            a start-of-packet char in it
          TST.B     D1                 Check InpLine completion code
          BEQ       RdPack16           Failed, return a timeout pseudo-packet
*                                      Ok, search the start-of-packet char
RdPack2   LEA       RecBuf(A6),A0      Pointer to receive buffer
          CLR.W     D1                 Clear the character counter
RdPack3   MOVE.B    (A0)+,D2           Get a character
          CMP.B     IStPckCh(A6),D2    Start-of-packet char ?
          BEQ.S     RdPack4            Yes, first goal satisfied !
          ADDQ.W    #1,D1              Increment character counter
          CMP.W     D0,D1              Last character ?
          BNE.S     RdPack3            No, try the next
          DBF       D6,RdPack1         Repeat max 3 times
          MOVEQ     #'Q',D1            Failed, return a garbage pseudo-packet
          BRA       RdPack19

RdPack4   MOVEQ     #32,D6             Load for quick addition/subtraction
RdPack5   MOVEA.L   A0,A1              Remember where packet started

          MOVE.B    (A0)+,D0           Get character
          BEQ       RdPack15           EOL, garbled packet
          CMP.B     IStPckCh(A6),D0    Start-of-packet char ?
          BEQ.S     RdPack5            Yes, resynchronize
          MOVE.B    D0,D3              This is the packet length
          SUB.B     D6,D3              Convert it to numeric

          MOVE.B    (A0)+,D0           Get character
          BEQ       RdPack15           EOL, garbled packet
          CMP.B     IStPckCh(A6),D0    Start-of-packet char ?
          BEQ.S     RdPack5            Yes, resynchronize
          MOVE.B    D0,D2              This is the packet number
          SUB.B     D6,D2              Convert it to numeric

          MOVE.B    (A0)+,D0           Get character
          BEQ       RdPack15           EOL, garbled packet
          CMP.B     IStPckCh(A6),D0    Start-of-packet char ?
          BEQ.S     RdPack5            Yes, resynchronize
          MOVE.B    D0,D1              This is the packet type

*                                      Heuristics for syncing block check type

          MOVEQ     #1,D5              Type 1 block check by default
          CMPI.B    #'S',D1            Send-Init packet ?
          BEQ.S     RdPack7            Yes, type 1 block check
          CMPI.B    #'I',D1            Initialize packet ?
          BEQ.S     RdPack7            Yes, type 1 block check
          CMPI.B    #'N',D1            NAK packet ?
          BNE.S     RdPack6            No
          MOVE.B    D3,D5              Yes, block check type is
          SUBQ.B    #2,D5              bct = packet_length - 2
          BRA.S     RdPack7
RdPack6   MOVE.B    BlChkUs(A6),D5     Otherwise block check type in use
RdPack7   SUB.B     D5,D3              Now compute data length by subtracting
          SUBQ.B    #2,D3              (block_check_type + 2)

          LEA       DataBuf(A6),A2     Pointer to data buffer
          CLR.W     D4                 Clear the counter register
          MOVE.B    D3,D4              Data length
          BRA.S     RdPack9            Read data, if any
RdPack8   MOVE.B    (A0)+,D0           Get character
          BEQ       RdPack15           EOL, garbled packet
          CMP.B     IStPckCh(A6),D0    Start-of-packet char ?
          BEQ.S     RdPack5            Yes, resynchronize
          MOVE.B    D0,(A2)+           Write character to data buffer
RdPack9   DBF       D4,RdPack8
          CLR.B     (A2)+              Mark the end of buffer

          MOVEA.L   A7,A2              Point to temporary storage space
          CLR.W     D4                 Clear the counter register
          MOVE.B    D5,D4              Block check type
          BRA.S     RdPack11           Get the block check
RdPack10  MOVE.B    (A0),D0            Get character
          BEQ       RdPack15           EOL, garbled packet
          CMP.B     IStPckCh(A6),D0    Start-of-packet char ?
          BEQ       RdPack5            Yes, resynchronize
          MOVE.B    D0,(A2)+           Store the block check character
          CLR.B     (A0)+              Nullify checksum characters in RecBuf
RdPack11  DBF       D4,RdPack10        Repeat

*                                      Got packet, now check the block check

          MOVEA.L   A1,A0              Pointer to packet start
          MOVEA.L   A7,A1              Point to received block check characters

          SUBQ.B    #1,D5              Type 1 block check ?
          BEQ.S     RdPack13           Yes, compute it
          SUBQ.B    #1,D5              Type 2 block check ?
          BEQ.S     RdPack12           Yes, compute it
          SUBQ.B    #1,D5              Type 3 block check ?
          BNE.S     RdPack15           No, return garbage pseudo-packet
*                                      Yes, compute it, (fall thru)

          BSR       Check3             Compute
          MOVEQ     #$3F,D4            Process bits 0 --> 5
          AND.B     D0,D4              Move and mask extra bits
          ADD.B     D6,D4              Conversion into a printable character
          CMP.B     2(A1),D4           Ok, now compare, third byte
          BNE       RdPack15           Compare fails, garbled packet
          LSR.W     #6,D0              Now process bits 6 --> 11, right adjust
          MOVEQ     #$3F,D4            To mask extra bits
          AND.B     D0,D4              Move and mask extra bits
          ADD.B     D6,D4              Conversion into a printable character
          CMP.B     1(A1),D4           Compare the second byte
          BNE       RdPack15           Compare fails, garbled packet
          LSR.W     #6,D0              Process bits 12 --> 15, right adjusting
          ADD.B     D6,D0              Conversion into a printable character
          CMP.B     (A1),D0            Compare the first byte
          BRA.S     RdPack14           Join common part

RdPack12  BSR       Check2             Compute
          MOVEQ     #$3F,D4            Process bits 0 --> 5
          AND.B     D0,D4              Move and mask extra bits
          ADD.B     D6,D4              Conversion into a printable character
          CMP.B     1(A1),D4           Ok, now compare, second byte
          BNE       RdPack15           Compare fails, garbled packet
          LSR.W     #6,D0              Process bits 6 --> 11, right adjusting
          ANDI.B    #$3F,D0            Mask extra bits
          ADD.B     D6,D0              Conversion into a printable character
          CMP.B     (A1),D0            Compare the first byte
          BRA.S     RdPack14           Join common part

RdPack13  BSR       Check1             Compute
          ADD.B     D6,D0              Convert it to a printable character
          CMP.B     (A1),D0            Compare it with the received block check
*                                      Join common part, (fall thru)

RdPack14  BEQ.S     RdPack17           If compare succeeds return packet type
RdPack15  MOVEQ     #'Q',D1            Return a garbage pseudo-packet
          BRA.S     RdPack18
RdPack16  MOVEQ     #'T',D1            Return a timeout pseudo-packet
          BRA.S     RdPack18
RdPack17  ADDQ.L    #1,PcksRecd(A6)    Increment packets received this trans
          ADDQ.L    #1,TPckRecd(A6)    Increment total packets received
RdPack18  MOVEQ     #PackType,D0       We want display the packet type
          BSR       Screen             Update the screen, if necessary
RdPack19  ADDQ.L    #4,A7              Deallocate space on the stack
          MOVE.L    (A7)+,D4           Restore working register
          RTS

******************************** InpPack ******************************ok
*                                                                     *
*  Loop until the expected packet arrives or the maximum tries number *
*  exceeded. If a packet arrives with the same type of the last       *
*  packet sent, it's treated as an echo and another one is expected.  *
*  If the previous packet arrives again, the last packet is resent    *
*  and a new one is expected to come in.                              *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.B packet type or pseudo-type          *
*                            D2.B packet number                       *
*                            D3.B packet length                       *
*                            D4.B destroyed                           *
*                                                                     *
***********************************************************************
InpPack:  CLR.B     D4                 Clear the retry counter
InpPack1  BSR       ChekInt            Check for console interrupts
          BSR       RdPack             Try to read a packet
          CMP.B     SendType(A6),D1    It's the same just sent ?
          BNE.S     InpPack2           No
          BSR       RdPack             Yes, it's an echo, read another

InpPack2  CMP.B     PrevPckN(A6),D2    Previous packet ?
          BEQ.S     InpPack4           Yes, keep trying
          CMPI.B    #'T',D1            Timeout pseudo-packet ?
          BEQ.S     InpPack4           Yes, keep trying
          CMPI.B    #'Q',D1            Garbage pseudo-packet ?
          BEQ.S     InpPack4           Yes, keep trying
          CMPI.B    #'N',D1            NAK packet ?
          BNE.S     InpPack3           No, return the received packet
          ADDQ.L    #1,NAKsRecd(A6)    Yes, increment NAKs received counter
          ADDQ.L    #1,TNAKRecd(A6)    Increment total NAKs received counter
          CMP.B     NextPckN(A6),D2    It's a NAK for the next packet ?
          BNE.S     InpPack4           No
          MOVEQ     #'Y',D1            Yes, it's like an ACK ...
          MOVE.B    PackNum(A6),D2     ... for current packet
InpPack3  MOVE.B    D1,D4              Save this for parameter passing
          MOVEQ     #ClrInpBf,D0       Clear the input buffer ...
          MOVEQ     #HostLine,D1       ... of the host line
          BSR       ChanCtrl           Call the channel control routine
          MOVE.B    D4,D1              Restore the packet (pseudo) type
          RTS

InpPack4  CMP.B     Retry(A6),D4       Too many tries ?
          BCC.S     InpPack3           Yes, return
          BSR       Resend             No, send last packet again
          ADDQ.B    #1,D4              Increment the retry counter
          BRA.S     InpPack1           Stay in loop

********************************* GetPack *****************************ok
*                                                                     *
*  Gets characters from the current source, file or memory string.    *
*  Encodes the data into the packet, filling the packet optimally.    *
*  Returns TRUE on success with Size containing the number of         *
*  characters in DataBuf, or FALSE if DataBuf is empty (Size = 0,     *
*  EOF for file, end of string for memory string).                    *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
GetPack:  MOVEM.L   A0/D1-D2,-(A7)     Save working registers
          LEA       DataBuf(A6),A0     Pointer to data buffer
          MOVEQ     #0,D2              Clear index register
          TST.B     First(A6)          First time ?
          BLT.S     GetPack1           No, EOF from last time
          BEQ.S     GetPack2           No, input in progress
          CLR.B     First(A6)          Yes, remember
          BSR       GetChx             Get first character of file
          MOVE.B    D0,Current(A6)     Save current character
          TST.B     D1                 Null file ?
          BNE.S     GetPack3           No
GetPack1  MOVE.B    #1,First(A6)       Yes, setup for next time
          SF        D0                 Return negative completion code
          BRA.S     GetPack9

GetPack2  MOVE.B    LeftOver(A6,D2.W),(A0,D2.W) Do any left-overs
          BEQ.S     GetPack3           Exit if null
          ADDQ.W    #1,D2              Increment index
          BRA.S     GetPack2           Repeat

GetPack3  CLR.B     LeftOver(A6)       Nullify the left-overs buffer
          CLR.B     ReptCnt(A6)        Clear out any old repeat count
GetPack4  TST.B     First(A6)          EOF reached ?
          BLT.S     GetPack8           Yes, return partially (?) filled packet
          BSR       GetChx             Get a character from file or memory
          MOVE.B    D0,Next(A6)        Save next character for lookahead
          TST.B     D1                 EOF ?
          BNE.S     GetPack5           No
          MOVE.B    #-1,First(A6)      Yes, flag it for next time
GetPack5  MOVE.B    D2,OldSize(A6)     Remember current position
          MOVE.B    Current(A6),D0     Get the current character
          BSR       Encode             Encode the current character
          MOVE.B    Next(A6),Current(A6) Next is now current
          CMP.B     OMPckSiz(A6),D2    Check packet size
          BLT.S     GetPack4           Keep filling
          BEQ.S     GetPack8           Return exactly full packet
          MOVEQ     #0,D0              Clear for indexing the left-overs buffer
          MOVEQ     #0,D1              Clear for indexing the data buffer
          MOVE.B    OldSize(A6),D1     Set up the data buffer index
GetPack6  MOVE.B    (A0,D1.W),LeftOver(A6,D0.W) Save some for next time
          BEQ.S     GetPack7           Exit if null
          ADDQ.W    #1,D0              Increment the first index
          ADDQ.W    #1,D1              Increment the second index
          BRA.S     GetPack6           Repeat
GetPack7  MOVE.B    OldSize(A6),D2     Size of the truncated packet
GetPack8  ST        D0                 Provide positive completion code
GetPack9  MOVE.B    D2,Size(A6)
          CLR.B     (A0,D2.W)          Write buffer terminator
          MOVEM.L   (A7)+,A0/D1-D2     Restore working registers
          RTS

********************************* EncStrng ****************************ok
*                                                                     *
*  Encode a string from memory.                                       *
*                                                                     *
*         Entry conditions : A0.L memory string start address         *
*                                                                     *
*         Exit  conditions : A0.L memory string start address         *
*                                                                     *
***********************************************************************
EncStrng: MOVE.B    MStrFlag(A6),-(A7) Save the old flag
          MOVE.L    MStrgPnt(A6),-(A7) Save the old pointer
          ST        MStrFlag(A6)       Say input from memory string
          MOVE.L    A0,MStrgPnt(A6)    Point to the memory string
          MOVE.B    #1,First(A6)       Initialize character lookahead
          BSR       GetPack            Get a packet from the string
          MOVE.L    (A7)+,MStrgPnt(A6) Restore the old pointer
          MOVE.B    (A7)+,MStrFlag(A6) Restore the old flag
          MOVE.B    #1,First(A6)       Re-initialize character lookahead
          RTS

********************************* GetChx ******************************ok
*                                                                     *
*  Try to get the next character from file or memory string.          *
*  Returns TRUE on success with D0.B set to the character, or FALSE   *
*  on failure (EOF for file, enf of string for memory string).        *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.B character (if any)                  *
*                            D1.B completion code                     *
*                                                                     *
***********************************************************************
GetChx    MOVE.L    A0,-(A7)           Save working register
          TST.B     LFSave(A6)         Do we have a linefeed saved ?
          BEQ.S     GetChx1            No
          SF        LFSave(A6)         Yes, nullify the flag
          MOVEQ     #Asc_LF,D0         Return the saved LF
          ST        D1                 Also return a positive cc
          BRA.S     GetChx4
GetChx1   TST.B     MStrFlag(A6)       Try to get the next character, memory ?
          BEQ.S     GetChx2            No, get it from current file
          MOVEA.L   MStrgPnt(A6),A0    Load pointer to the memory string
          MOVE.B    (A0)+,D0           Get a character
          SNE       D1                 Set cc to false if end of string reached
          MOVE.L    A0,MStrgPnt(A6)    Save pointer for next time
          BRA.S     GetChx3            Join the common part
GetChx2   MOVEQ     #IOFile,D1         Get a char from the the current file
          BSR       InpChar
          TST.B     D1                 Check the returned completion code
          SEQ       D1                 Set completion code accordingly
GetChx3   TST.B     D1                 Have we got a character ?
          BEQ.S     GetChx4            No, return
          ADDQ.L    #1,DChsSent(A6)    Yes, count it
          ADDQ.L    #1,TDChSent(A6)
          TST.B     Binary(A6)         Are we in binary mode ?
          BNE.S     GetChx4            Yes, nl-CRLF mapping not needed
          CMPI.B    #NewLinCh,D0       No, newline character ?
          BNE.S     GetChx4            No
          ST        LFSave(A6)         Yes, remember a linefeed
          MOVEQ     #Asc_CR,D0         Return a carriage return
GetChx4   MOVE.L    (A7)+,A0           Restore working register
          RTS

********************************* Resend ******************************ok
*                                                                     *
*  Resend the last packet sent (the one in SendBuf), if any, send     *
*  a NAK otherwise.                                                   *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                                                                     *
***********************************************************************
Resend:   MOVEQ     #ClrInpBf,D0       Clear the input buffer
          MOVEQ     #HostLine,D1       Host line channel
          BSR       ChanCtrl           Call the channel control routine
          TST.B     SendBuf(A6)        Send buffer empty ?
          BNE.S     Resend1            No, send last packet again
          BSR       SendNAK            Yes, send a NAK packet
          RTS
Resend1   BSR       TxPackt            Send the previous packet again
          MOVEQ     #PackType,D0       Update the screen
          MOVEQ     #'%',D1            This is the symbol for a resent packet
          BSR       Screen
          RTS

******************************** SndEPack *****************************ok
*                                                                     *
*  Send an Error packet.                                              *
*                                                                     *
*         Entry conditions : A1.L point to the reason string          *
*                                                                     *
*         Exit  conditions : D0.L destroyed                           *
*                            D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.B destroyed                           *
*                            A0.L destroyed                           *
*                                                                     *
***********************************************************************
SndEPack: MOVEA.L   A1,A0              Point to the reason string
          BSR       EncStrng           Encode it
          MOVEQ     #'E',D1            Error packet
          MOVE.B    PackNum(A6),D2     Packet number
          MOVE.B    Size(A6),D3        Packet length
          BSR       SndPack            OK, send now
          BSR       ClsInpF            Close the input file, if open
          ST        CtlZSeen(A6)       This is an interrupted file transfer
          BSR       ClsOutF            Close (and maybe delete) the output file
          MOVEQ     #TranCmpl,D0       Give transaction complete message
          BSR       Screen
          RTS

********************************* SendACK *****************************ok
*                                                                     *
*  Send an empty ACK packet.                                          *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.L destroyed                           *
*                                                                     *
***********************************************************************
SendACK:  MOVEQ     #'Y',D1            ACK
          MOVE.B    PackNum(A6),D2     Packet number
          MOVEQ     #0,D3              Packet length (0, empty packet)
          BSR       SndPack            OK, send now
          BSR       BumpPckN           Bump packet number, modulo 64
          RTS

********************************* SendNAK *****************************ok
*                                                                     *
*  Send a NAK packet (always empty).                                  *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : D1.L destroyed                           *
*                            D2.B destroyed                           *
*                            D3.L destroyed                           *
*                                                                     *
***********************************************************************
SendNAK   MOVEQ     #'N',D1            NAK
          MOVE.B    PackNum(A6),D2     Packet number
          MOVEQ     #0,D3              Packet length (0, empty packet)
          BSR       SndPack            OK, send now
          ADDQ.L    #1,NAKsSent(A6)    Increment NAKs sent this transaction
          ADDQ.L    #1,TNAKSent(A6)    Increment total NAKs sent
          RTS

          ends
          END
<<< k6ostr.asm >>>
          nam       Kermit68K
          ttl       Character strings module

*         Kermit68K: source file K68STR
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68Strings,0,0,Edition,0,0

*** Strings from the K68SystemPart module ***

ConLinNm: DC.B      "/Term",Asc_Nul         Console line name
DefLinNm: DC.B      "/T1",Asc_Nul           Default line name for connect
DefPrmpt: DC.B      "Kermit68K> ",Asc_Nul   Default prompt string
InitFile: DC.B      "Kermit.ini",Asc_Nul    Init file name

*** Strings from the K68Commands module ***

StLnFStr: DC.B      "You must 'set line' before issuing this command"
          DC.B      Asc_CR,Asc_LF,Asc_Nul

NoCopStr: DC.B      "Can't copy file(s)",Asc_Nul
NoCWDStr: DC.B      "Can't change working directory",Asc_Nul
NoDelStr: DC.B      "Can't delete file(s)",Asc_Nul
NoDirStr: DC.B      "Can't list directory",Asc_Nul
NoPriStr: DC.B      "Can't print file(s)",Asc_Nul
NoRenStr: DC.B      "Can't rename file(s)",Asc_Nul
NoSpaStr: DC.B      "Can't show disk usage",Asc_Nul
NoTypStr: DC.B      "Can't type file(s)",Asc_Nul
NoSyCStr: DC.B      "Can't forward command to system",Asc_Nul

TFNDpStr: DC.B      "?Take files nested too deeply",Asc_Nul
MsFSpStr: DC.B      "?Missing file specification",Asc_Nul

KerCmStr: DC.B      Asc_LF,"Kermit68K commands:"
          DC.B      Asc_CR,Asc_LF,Asc_LF,Asc_Nul
MacCmStr: DC.B      Asc_LF,"User defined macros:"
          DC.B      Asc_CR,Asc_LF,Asc_LF,Asc_Nul
NoMacStr: DC.B      Asc_LF,"There are no user defined macros."
          DC.B      Asc_CR,Asc_LF,Asc_LF,Asc_Nul

MNstAStr: DC.B      "?Can't nest macro definitions",Asc_Nul
MsMcNStr: DC.B      "?Missing macro name",Asc_Nul
UnkMcStr: DC.B      "?Unknown macro",Asc_Nul

ConnStr1: DC.B      Asc_CR,Asc_LF
          DC.B      "Connecting thru ",Asc_Nul
ConnStr2: DC.B      Asc_CR,Asc_LF
          DC.B      "Connected thru ",Asc_Nul
ConnStr3: DC.B      ", speed ",Asc_Nul
ConnStr5: DC.B      Asc_CR,Asc_LF
          DC.B      "The escape character is ",Asc_Nul
ConnStr6: DC.B      ")",Asc_CR,Asc_LF
          DC.B      "Type the escape character followed by C to get"
          DC.B      Asc_CR,Asc_LF
          DC.B      "back, or followed by ? to see other options."
          DC.B      Asc_CR,Asc_LF,Asc_LF,Asc_Nul
ConnStr7: DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      "Kermit68K disconnected."
          DC.B      Asc_CR,Asc_LF,Asc_Nul
ConnStr8: DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      "C to close the connection, or:"
          DC.B      Asc_CR,Asc_LF
          DC.B      "  0 (zero) to send a NULL"
          DC.B      Asc_CR,Asc_LF
          DC.B      "  B to send a BREAK"
          DC.B      Asc_CR,Asc_LF
          DC.B      "  H to hangup and close connection"
          DC.B      Asc_CR,Asc_LF
          DC.B      "  S for status"
          DC.B      Asc_CR,Asc_LF
          DC.B      "  ? for help"
          DC.B      Asc_CR,Asc_LF
          DC.B      " escape character twice to send the escape character."
          DC.B      Asc_CR,Asc_LF,Asc_LF,Asc_Nul

StatStr1: DC.B      "Statistics                Transaction       Total"
          DC.B      Asc_CR,Asc_LF
          DC.B      " Characters sent         ",Asc_Nul
StatStr2: DC.B      " Data characters sent    ",Asc_Nul
StatStr3: DC.B      " NAKs received           ",Asc_Nul
StatStr4: DC.B      " Packets sent            ",Asc_Nul
StatStr5: DC.B      " Characters received     ",Asc_Nul
StatStr6: DC.B      " Data characters received",Asc_Nul
StatStr7: DC.B      " NAKs sent               ",Asc_Nul
StatStr8: DC.B      " Packets received        ",Asc_Nul

*** Strings from the K68Commands2 module ***

OpLnEStr: DC.B      "Can't open line",Asc_Nul
UnsBRStr: DC.B      "?Unsupported baud rate",Asc_Nul
SetCtStr: DC.B      "?Not in ASCII control range",Asc_Nul

*** Strings from the K68Commands3 module ***

Rm1FOStr: DC.B      "?A file specification is required"
          DC.B      Asc_CR,Asc_LF,Asc_Nul
Rm2FOStr: DC.B      "?Two file specifications are required"
          DC.B      Asc_CR,Asc_LF,Asc_Nul

VersStr:  DC.B      Asc_CR,Asc_LF
          DC.B      "Kermit68K version 1.0.00 from 01 July 1987"
          DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      Asc_Nul

ShVerStr: DC.B      "Warning, this is a preliminary version, for any"
          DC.B      Asc_CR,Asc_LF
          DC.B      "problem or suggestion please contact the author:"
          DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      "Roberto Bagnara        Bitnet address Bagnara@Iboinfn"
          DC.B      Asc_CR,Asc_LF
          DC.B      "Physics Department     DECnet address 39937::BAGNARA"
          DC.B      Asc_CR,Asc_LF
          DC.B      "Bologna University"
          DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      "OS-9/68000 Modifications by:"
          DC.B      Asc_CR,Asc_LF
          DC.B      "Steve Williams         Arpanet address "
          DC.B      "stevew@sally.utexas.edu"
          DC.B      Asc_CR,Asc_LF,Asc_LF,Asc_Nul

ShPStr1:  DC.B      Asc_CR,Asc_LF
          DC.B      "Communications Parameters:"
          DC.B      Asc_CR,Asc_LF
          DC.B      " Line: ",Asc_Nul
ShPStr2:  DC.B      ", speed: ",Asc_Nul
ShPStr3:  DC.B      "unknown",Asc_Nul
ShPStr4:  DC.B      ", mode: ",Asc_Nul
ShPStr5:  DC.B      "local",Asc_Nul
ShPStr6:  DC.B      "remote",Asc_Nul
ShPStr7:  DC.B      Asc_CR,Asc_LF
          DC.B      " Parity: ",Asc_Nul
ShPStr8:  DC.B      "even",Asc_Nul
ShPStr9:  DC.B      "odd",Asc_Nul
ShPStr10: DC.B      "mark",Asc_Nul
ShPStr11: DC.B      "space",Asc_Nul
ShPStr12: DC.B      "none",Asc_Nul
ShPStr13: DC.B      ", duplex: ",Asc_Nul
ShPStr14: DC.B      "half, ",Asc_Nul
ShPStr15: DC.B      "full, ",Asc_Nul
ShPStr16: DC.B      "flow: ",Asc_Nul
ShPStr17: DC.B      "xon/xoff",Asc_Nul
ShPStr18: DC.B      ", handshake: ",Asc_Nul
ShPStr19: DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      "Protocol Parameters:   Send    Receive",Asc_Nul
ShPStr20: DC.B      "    (* = override)",Asc_Nul
ShPStr21: DC.B      Asc_CR,Asc_LF," Timeout:      ",Asc_Nul
ShPStr22: DC.B      Asc_CR,Asc_LF," Padding:      ",Asc_Nul
ShPStr23: DC.B      Asc_CR,Asc_LF," Pad Character:",Asc_Nul
ShPStr24: DC.B      Asc_CR,Asc_LF," Packet Start: ",Asc_Nul
ShPStr25: DC.B      Asc_CR,Asc_LF," Packet End:   ",Asc_Nul
ShPStr26: DC.B      Asc_CR,Asc_LF," Packet Length:",Asc_Nul
ShPStr27: DC.B      Asc_CR,Asc_LF
          DC.B      Asc_CR,Asc_LF,"Block Check Type: ",Asc_Nul
ShPStr28: DC.B      ", Delay: ",Asc_Nul
ShPStr29: DC.B      Asc_CR,Asc_LF
          DC.B      "Retry Limits: Initial ",Asc_Nul
ShPStr30: DC.B      ", Normal ",Asc_Nul
ShPStr31: DC.B      Asc_CR,Asc_LF,"8th-Bit Prefix:      ",Asc_Nul
ShPStr32: DC.B      Asc_CR,Asc_LF,"Repeat-Count Prefix: ",Asc_Nul
ShPStr33: DC.B      Asc_CR,Asc_LF,Asc_LF
          DC.B      "File parameters:",Asc_CR,Asc_LF
          DC.B      " File Names:   ",Asc_Nul
ShPStr34: DC.B      "converted",Asc_Nul
ShPStr35: DC.B      "literal",Asc_Nul
ShPStr36: DC.B      Asc_CR,Asc_LF," File Type:    ",Asc_Nul
ShPStr37: DC.B      "binary",Asc_Nul
ShPStr38: DC.B      "text",Asc_Nul
ShPStr39: DC.B      Asc_CR,Asc_LF," File Warning: ",Asc_Nul
ShPStr40: DC.B      "on",Asc_Nul
ShPStr41: DC.B      "off",Asc_Nul
ShPStr42: DC.B      Asc_CR,Asc_LF," File Display: ",Asc_Nul
ShPStr43: DC.B      Asc_CR,Asc_LF,"Incomplete File Disposition: ",Asc_Nul
ShPStr44: DC.B      "keep",Asc_Nul
ShPStr45: DC.B      "discard",Asc_Nul
ShPStr46: DC.B      ", Init file: ",Asc_Nul
ShPStr47: DC.B      "   Packet Log:       ",Asc_Nul

*** Strings from the K68Commands4 module ***

LBReqStr: DC.B      "?-l and -b required",Asc_CR,Asc_LF,Asc_Nul
ABadUStr: DC.B      "?-a without -s, -r, or -g"
CnfAcStr: DC.B      "?Conflicting commands",Asc_CR,Asc_LF,Asc_Nul
MsFlNStr: DC.B      "?Missing file name",Asc_CR,Asc_LF,Asc_Nul
MisLNStr: DC.B      "?Communication line device name missing"
          DC.B      Asc_CR,Asc_LF,Asc_Nul
UnOpLStr: DC.B      "?Unable to open the requested line"
          DC.B      Asc_CR,Asc_LF,Asc_Nul
InvABStr: DC.B      "?Invalid argument bundling",Asc_CR,Asc_LF,Asc_Nul
InvArStr: DC.B      "?Invalid argument, type 'kermit -h' for help"
          DC.B      Asc_CR,Asc_LF,Asc_Nul

UsageStr: DC.B      Asc_CR,Asc_LF
          DC.B      "  Usage: kermit [-x arg [-x arg]...[-yyy]...]]"
          DC.B      Asc_CR,Asc_LF
          DC.B      "   x is an option that requires an argument,"
          DC.B      " y an option with no argument:"
          DC.B      Asc_CR,Asc_LF
          DC.B      "     commands (* options also require -l and -b) --"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -s file(s)   send "
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -r           receive"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -k           receive to terminal"
          DC.B      Asc_CR,Asc_LF
          DC.B      "     * -g file(s)   get remote file(s) from server"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -a name      alternate name, used with -s, -r, -g"
          DC.B      Asc_CR,Asc_LF
          DC.B      "     * -f           finish remote server"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -h           help - type this message"
          DC.B      Asc_CR,Asc_LF
          DC.B      "     settings --"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -l line      communication line device"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -b baud      line speed, e.g. 1200"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -i           binary file"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -p x         parity, x is one of e,o,m,s,n"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -t           line turnaround handshake = xon,"
          DC.B      " half duplex"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -w           don't write over preexisting files"
          DC.B      Asc_CR,Asc_LF
          DC.B      "       -q           be quiet during file transfer"
          DC.B      Asc_CR,Asc_LF
          DC.B      " If no command is included, enter interactive mode"
          DC.B      Asc_CR,Asc_LF,Asc_Nul

*** Strings from the K68IOFunctions module ***

FlCmdStr: DC.B      "Error reading take file",Asc_CR,Asc_LF,Asc_Nul

CnBchStr: DC.B      "^Z - Cancelling Batch ",Asc_Nul
CnFilStr: DC.B      "^X - Cancelling File ",Asc_Nul
ReSndStr: DC.B      "^R - Resending ",Asc_Nul

ScrnStr1: DC.B      "Sending ",Asc_Nul
ScrnStr2: DC.B      "Receiving ",Asc_Nul
ScrnStr3: DC.B      "as ",Asc_Nul
ScrnStr4: DC.B      " [OK]",Asc_CR,Asc_LF,Asc_Nul
ScrnStr5: DC.B      " [discarded]",Asc_CR,Asc_LF,Asc_Nul
ScrnStr6: DC.B      " [interrupted]",Asc_CR,Asc_LF,Asc_Nul
ScrnStr7: DC.B      "Skipping ",Asc_Nul

*** Strings from the K68Protocol module ***

CCndLStr: DC.B      "Can't condition line",Asc_Nul
StSpeStr: DC.B      "Sorry, you must 'set speed' first",Asc_Nul

ErFRHStr: DC.B      "Error from remote host :",Asc_CR,Asc_LF,Asc_Nul
TooMTStr: DC.B      "Too many tries, last error is ",Asc_Nul
NAKRcStr: DC.B      "'NAK packet received'",Asc_Nul
TimLEStr: DC.B      "'timeout limit expired'",Asc_Nul
GbPRcStr: DC.B      "'garbled packet received'",Asc_Nul
POuOSStr: DC.B      "'packet out of sequence'",Asc_Nul
UkUxPStr: DC.B      "Unknown or unexpected packet type",Asc_Nul

FNFStr:   DC.B      "File not found",Asc_Nul
TMFStr:   DC.B      "Too many files",Asc_Nul
NRFStr:   DC.B      "No readable file to send",Asc_Nul

FlOErStr: DC.B      "Can't open file",Asc_Nul

NoNamStr: DC.B      "NONAME",Asc_Nul
FlCrEStr: DC.B      "Can't create file",Asc_Nul

*** Strings from the K68ParserSubs module ***

PrNmStr1: DC.B      "?Invalid number specification",Asc_Nul
PrNmStr2: DC.B      "?Number out of range",Asc_Nul
PrNmStr3: DC.B      "?Number specification expected",Asc_Nul

PrKyStr1: DC.B      "?Unrecognized ",Asc_Nul
PrKyStr2: DC.B      "?Ambiguous ",Asc_Nul
PrKyStr3: DC.B      "?Missing ",Asc_Nul

PrIFStr1: DC.B     "?File not found",Asc_Nul
PrIFStr2: DC.B     "?File not readable",Asc_Nul
PrIFStr3: DC.B     "?Read permission denied",Asc_Nul
PrIFStr4: DC.B     "?No files match",Asc_Nul
PrIFStr5: DC.B     "?Too many files match",Asc_Nul

POuFStr1: DC.B     "?Wildcards not allowed",Asc_Nul
POuFStr2: DC.B     "?Write permission denied",Asc_Nul

PrErStr1: DC.B      " - ",Asc_Nul

          align                        Following code aligned on word boundary
          ends
          END
<<< k6osys.asm >>>
          nam       Kermit68K
          ttl       OS-9/68000 Dependent module (part 1)

*         Kermit68K: source file K68SYS.A
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, May 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* OS9/68000 Modifications performed by Steve Williams
* University of Texas at Austin, March 1987
*
*  Revision History:
*    Edition  Date      Author  Description
*       0     87/03/25  spw     Initial implementation for OS-9/68K
*       1     87/04/22  spw     Added code for ChanCtrl
*       2     87/04/23  spw     Modifications to SysInit to handle command line
*       3     87/05/05  spw     Changes to ChanCtrl and SysInit
*       4     87/06/05  spw     Stripped parity bit on OutChar to Terminal
*       5     87/06/20  spw     Added line-feed stripping to Terminal output
*       6     87/07/02  spw     Rejoined sys, sy2 and sy3 for distribution

          use       DefsFile

Edition   set       6
          psect     K68sys,0,0,Edition,0,0

********************************* InpChar *****************************
*                                                                     *
*  Try to read a character from the specified logical channel.        *
*                                                                     *
*         Entry conditions : D1.B logical channel number              *
*                                                                     *
*         Exit  conditions : D0.B character received, if any          *
*                            D1.B Completion Code (see below)         *
*                                                                     *
*              CC symbol        Meaning                               *
*                                                                     *
*              AllOk            No errors, character in D0            *
*              BadChan          Inexistent channel                    *
*              ResChan          Access reserved, permission denied    *
*              DevNotRd         Device not ready (e.g. unmounted)     *
*              NotInpCh         Input impossible on this channel      *
*              NotOpRd          File not open for read                *
*              UnrInpF          Unrecoverable failure during input    *
*              InChLost         Input character lost                  *
*              InpBreak         Break received on input               *
*              BufEmpty         Input buffer empty                    *
*              BufOvflw         Input buffer overflow                 *
*              EndOfFil         End of file reached on input          *
*                                                                     *
*  NOTES:  This routine uses a0, d0, and d1, and restores a0          *
***********************************************************************
InpChar:  move.l    a0,-(sp)           Save working register.
          clr.w     -(sp)              Make a temporary buffer on the stack
          add.w     d1,d1              Convert to offset in path numbers table
          lea       Pathnums(a6),a0    Base of path numbers table
          move.w    (a0,d1.w),d0       Get the OS-9 path number
          bne.s     InpChar1           Has logical channel been used yet?
          move.b    #NotOpRd,d1        No, complain
          bra.s     InpChar3

InpChar1  move.w    #SS_Ready,d1       Check to see if data available
          os9       I$GetStt
          bcc.s     InpChar2           Data ready, go and read it.
          cmp.w     #E$NotRdy,d1       The not ready code (means no data)
          bne.s     InpChar5           Another OS-9 error code
          move.b    #BufEmpty,d1       Tell caller no data ready
          bra.s     InpChar3

InpChar2  lea       1(sp),a0           pass address of buffer
          moveq     #1,d1              Read one character
          os9       I$Read
          bcs.s     InpChar5           An OS-9 error
          move.b    #AllOk,d1          Everything OK
InpChar3  move.w    (sp)+,d0           Get the character read
          move.l    (sp)+,a0           Restore working register
          rts

InpChar5  cmp.b     #E$FNA,d1          A permission violation?
          bne.s     InpChar6
          move.b    #ResChan,d1
          bra.s     InpChar3
InpChar6  cmp.b     #E$EOF,d1          End of file?
          bne.s     InpChar7
          move.b    #EndOfFil,d1
          bra.s     InpChar3
InpChar7  move.w    #$0707,-(sp)
          moveq     #2,d0
          move.l    sp,a0
          moveq     #1,d1
          os9       I$Write
          addq      #2,sp
          move.b    #UnrInpF,d1
          bra.s     InpChar3

********************************* OutChar *****************************
*                                                                     *
*  Try to write a character to the specified logical channel.         *
*                                                                     *
*         Entry conditions : D0.B character to write                  *
*                            D1.B logical channel number              *
*                                                                     *
*         Exit  conditions : D0.B character just sent                 *
*                            D1.B Completion Code (see below)         *
*                                                                     *
*              CC symbol        Meaning                               *
*                                                                     *
*              AllOk            No errors                             *
*              BadChan          Inexistent channel                    *
*              ResChan          Access reserved, permission denied    *
*              DevNotRd         Device not ready (e.g. unmounted)     *
*              NotOutCh         Output impossible on this channel     *
*              NotOpWr          File not open for write               *
*              UnrOutF          Unrecoverable failure during output   *
*              DevFull          Device full, not enough space         *
*                                                                     *
*  NOTES:  This routine uses a0, d0, and d1, and restores a0          *
***********************************************************************
OutChar:  move.l    a0,-(sp)           Save working pointer reg.
          cmp       #Terminal,d1       Output to terminal?
          seq       TermFlag(a6)
          bne.s     OutChar0
          and.w     #$007f,d0          Strip the parity bit
          cmp.b     #Asc_LF,d0         Is it a linefeed?
          bne.s     OutChar_0
          tst.b     CR_Last(a6)        Did we just do a CR?
          beq.s     OutChar_0          ...no, so go ahead and print it.
          clr.b     CR_Last(a6)        OK for next LF to be printed
          move.l    (sp)+,a0           Restore working reg
          rts

OutChar_0 cmp.b     #Asc_CR,d0         Is carriage return?
          seq       CR_Last(a6)        Set the flag.

OutChar0  move.w    d0,-(sp)           Save the character being written
          lea       Pathnums(a6),a0    Get path number table base address
          add.w     d1,d1              Offset in table for this logical channel
          move.w    (a0,d1.w),d0       Get OS-9 output path for channel
          bne.s     OutChar2           It is open, so go ahead with write
          move.b    #NotOpWr,d1

OutChar1  move.w    (sp)+,d0           get the character written
          move.l    (sp)+,a0           get the old contents of the pointer
          rts

OutChar2  lea       1(sp),a0           Point to character (in memory on stack)
          moveq     #1,d1              ...and get ready
          tst       TermFlag(a6)       Output to terminal?
          beq.s     OutChar21          ...no, use I$Write
          tst.b     CR_Last(a6)        a Carriage return?
          beq.s     OutChar21          ...no, use I$Write
          os9       I$WritLn           Use WritLn to make sure...
          bra.s     OutChar22          ...that CR is handled properly.
OutChar21 os9       I$Write            Just write the character in plain mode
OutChar22 bcs.s     OutChar3           Something went wrong
          move.b    #AllOk,d1
          bra.s     OutChar1           Exit through clean-up routine

OutChar3  cmp.b     #E$Full,d1         Device full?
          bne.s     OutChar4
          move.b    #DevFull,d1
          bra.s     OutChar1

OutChar4  cmp.b     #E$NotRdy,d1       Device not ready?
          bne.s     OutChar5
          move.b    #DevNotRd,d1
          bra.s     OutChar1

OutChar5  cmp.b     #E$FNA,d1          Permission violation?
          bne.s     OutChar6
          move.b    #ResChan,d1
          bra.s     OutChar1

OutChar6  move.b    #UnrOutF,d1
          bra.s     OutChar1

********************************* ChanCtrl ****************************
*                                                                     *
*  Performs control operations on logical channels.                   *
*                                                                     *
*         Entry conditions : D0.B Request Code (see below)            *
*                                                                     *
*              RC symbol        Meaning                               *
*                                                                     *
*              SetBaud          Set baud rate on port                 *
*              RawMode          Enable raw mode                       *
*              TextMode         Enable text mode                      *
*              DoXCntrl         Enable XON/XOFF protocol              *
*              NoXCntrl         Disable XON/XOFF protocol             *
*              SndBreak         Send a break over RS 232 C line       *
*              ClrInpBf         Clear input buffer                    *
*              ClrOutBf         Clear output buffer                   *
*                                                                     *
*                            D1.B channel number                      *
*                            D2.L additional data (only requested     *
*                                 baud rate now)                      *
*                                                                     *
*         Exit  conditions : D0.B Completion Code (see below)         *
*                                                                     *
*              CC symbol        Meaning                               *
*                                                                     *
*              AllOk            No errors                             *
*              BadChan          Inexistent channel                    *
*              ResChan          Access reserved, permission denied    *
*              DevNotRd         Device not ready (e.g. unmounted)     *
*              BadCtReq         I/O control request code invalid      *
*                                                                     *
***********************************************************************
ChanCtrl: add.w     d0,d0              Get offset into jump table
          move.w    ChanRCLk(pc,d0.w),d0 Get offset to start of routine
          jmp       ChanRCLk(pc,d0.w)  Jump into it.

ChanRCLk  dc.w      CCSetBaud-ChanRCLk
          dc.w      CCRawMode-ChanRCLk
          dc.w      CCTxtMode-ChanRCLk
          dc.w      CCDoXON-ChanRCLk
          dc.w      CCNoXON-ChanRCLk
          dc.w      CCSndBrk-ChanRCLk
          dc.w      CCClrBuf-ChanRCLk

*  Set Baud rate
*
*  This routine simply changes the PD_BAU parameter in the path descriptor of
*  the designated logical channel.  Standard OS-9 baud rates are supported,
*  as per the table listed below and in the SCF section of the OS-9/68000
*  Technical Manual.
*
*  Note:  although many OS9 serial port drivers support software selectable
*  baud rates, many will only set the baud rate when they are first INIZed.
*  The standard 6850 ACIA driver falls in this class.  It is a relatively
*  simple procedure to add on-the-fly baud rate selection to the Read and
*  Write routines of most drivers, if source code is available, and if the
*  hardware supports baud rate selection.

CCSetBaud move.l    a0,-(sp)
          lea       BaudRates(pc),a0   Point to baud rate table.
SetBaud2  move.l    (a0)+,d0           Get a baud rate/code number pair
          bmi       CCError            Past end of table
          cmp.w     d0,d2              Baud rates match?
          bne.s     SetBaud2           No, check another

          swap      d0                 Get the baud rate code number
          move      d0,d2              Save it around the I$GetStt call

          add       d1,d1              Offset to path number table
          lea       Pathnums(a6),a0
          move      (a0,d1),d0         Get the path number
          lea       OptBuff(a6),a0     Point to the options buffer
          moveq     #SS_Opt,d1
          os9       I$GetStt
          bcs       CCError

          move.b    d2,PD_BAU-PD_OPT(a0) Set the baud rate

          moveq     #SS_Opt,d1
          os9       I$SetStt
          bcs       CCError
          move.l    (sp)+,a0           Restore working register.
          moveq     #AllOk,d0
          rts

BaudRates dc.w      0,50      These are the OS-9 baud rate numbers/buad rates
          dc.w      1,75      Found in the Technical Manual section on SCF
          dc.w      2,110
          dc.w      3,134     NOTE:  Not all device drivers support baud rate
          dc.w      4,150     selection after the device has been INIZed!!
          dc.w      5,300
          dc.w      6,600
          dc.w      7,1200
          dc.w      8,1800
          dc.w      9,2000
          dc.w      10,2400
          dc.w      11,3600
          dc.w      12,4800
          dc.w      13,7200
          dc.w      14,9600
          dc.w      15,19200
          dc.w      -1,-1     Mark end of table.

*  Send break out RS232 line
*
*  This routine relies on an undocumented feature of the I$GetStt call
*  It may not (and probably won't) work on very many serial drivers.

CCSndBrk  move.l    a0,-(sp)
          add       d1,d1              Offset into path table
          lea       Pathnums(a6),a0
          move      (a0,d1),d0         Path number to use
          moveq     #SS_Break,d1       Request a break
          os9       I$SetStt
          bcs       CCError
          move.l    (sp)+,a0
          moveq     #AllOk,d0
          rts

CCError   move.l    (sp)+,a0
          moveq     #BadCtReq,d0
          rts

*  Raw Mode--sets options suitable for raw (binary) data transfer mode

CCRawMode move.l    a0,-(sp)
          add.w     d1,d1              Get offset into path number lookup table
          lea       Pathnums(a6),a0    Get base of input path lookup table
          move.w    (a0,d1.w),d0       Get the OS9 path number
          lea       OptBuff(a6),a0     ...point to a buffer
          move.w    #SS_Opt,d1         ...and read in the option block
          os9       I$GetStt
          bcs       CCError

          clr.b     PD_EKO-PD_OPT(a0)  No echo
          clr.b     PD_PAU-PD_OPT(a0)  No page pause
          clr.b     PD_EOF-PD_OPT(a0)  No end of file character
          clr.b     PD_PSC-PD_OPT(a0)  No pause character
          clr.b     PD_INT-PD_OPT(a0)  No interrupt character
          clr.b     PD_QUT-PD_OPT(a0)  No abort character

          moveq     #SS_Opt,d1         Now, set 'em back
          os9       I$SetStt
          bcs       CCError
          move.l    (sp)+,a0
          moveq     #AllOk,d0          No error
          rts

*  Text Mode--sets options suitable for text transfer mode

CCTxtMode move.l    a0,-(sp)
          add.w     d1,d1              Get offset into path number lookup table
          lea       Pathnums(a6),a0
          move.w    (a0,d1.w),d0       Get the OS9 path number

          moveq     #255,d1
          os9       I$GetStt

          lea       OptBuff(a6),a0     Restore the text mode options
          move.w    #SS_Opt,d1         ...and read in the option block
          os9       I$GetStt
          bcs       CCError

          clr.b     PD_EKO-PD_OPT(a0)  No echo
          clr.b     PD_PAU-PD_OPT(a0)  No page pause
          clr.b     PD_EOF-PD_OPT(a0)  No end of file character
          clr.b     PD_PSC-PD_OPT(a0)  No pause character
          clr.b     PD_INT-PD_OPT(a0)  No interrupt character
          clr.b     PD_QUT-PD_OPT(a0)  No abort character

          move.w    #SS_Opt,d1
          os9       I$SetStt           Set to raw mode
          bcs       CCError
          move.l    (sp)+,a0
          moveq     #AllOk,d0          No error
          rts

*  DoXON--turns on XON/XOFF processing

CCDoXON   move.l    a0,-(sp)
          add.w     d1,d1
          lea       Pathnums(a6),a0
          move.w    (a0,d1.w),d0       Get the OS9 path number
          lea       OptBuff(a6),a0
          move.w    #SS_Opt,d1         ...and read in the option block
          os9       I$GetStt
          bcs       CCError

          move.b    #Asc_DC1,PD_XON-PD_OPT(a0)
          move.b    #Asc_DC3,PD_XOFF-PD_OPT(a0)

          move.w    #SS_Opt,d1
          os9       I$SetStt           Set to XON/XOFF mode
          bcs       CCError
          move.l    (sp)+,a0
          moveq     #AllOk,d0          No error
          rts

*  NoXON--This turns XON/XOFF processing off for the selected path.

CCNoXON   move.l    a0,-(sp)
          add.w     d1,d1
          lea       Pathnums(a6),a0
          move.w    (a0,d1.w),d0       Get the OS9 path number
          lea       OptBuff(a6),a0
          move.w    #SS_Opt,d1         ...and read in the option block
          os9       I$GetStt
          bcs       CCError

          clr.b     PD_XON-PD_OPT(a0)
          clr.b     PD_XOFF-PD_OPT(a0)

          move.w    #SS_Opt,d1
          os9       I$SetStt           Set to XON/XOFF mode
          bcs       CCError
          move.l    (sp)+,a0
          moveq     #AllOk,d0          No error
          rts

*  Clear out the input buffer.
*
*  This routine uses the OS-9 I$GetStt call with the SS_Ready function request
*  to determine how much data is available.  Most OS-9 drivers implement the
*  SS_Ready function code, but some of them incorrectly return 0 or 1 instead
*  the true number of characters in the buffer.  Due to this the routine will
*  check multiple times.

CCClrBuf  move.l    a0,-(sp)
          add.w     d1,d1              Offset into path number lookup table
          lea       Pathnums(a6),a0
          move      (a0,d1.w),d0       Get the actual OS-9 path number

CCClrB2   moveq     #SS_Ready,d1
          os9       I$GetStt           Check for data available
          bcs.s     CCClrB3            D1 SHOULD return number of chars in buff

          lea       ShellCmd(a6),a0    An unused buffer for reading
          os9       I$Read             Try to read the characters in the buffer
          bcc.s     CCClrB2            Check one more time for data.

CCClrB3   cmp.w     #E$NotRdy,d1       Is the error data not ready?
          beq.s     CCClrB4            ...yes, we've flushed the buffer

          cmp.w     #E$Read,d1         Was it a buffer over-run?
          beq.s     CCClrB2            Go back and empty some more.

CCClrB4   move.l    (sp)+,a0
          moveq     #AllOk,d0
          rts

********************************* SysInit *****************************
*                                                                     *
*  Initialize any system dependent thing.                             *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
*  OS-9/68000 Notes:                                                  *
*    This routine grabs the command line parameter list and makes     *
*  sure that it is null-terminated (OS-9 usually puts a carriage      *
*  return or two).  Also, in order to avoid possible problems with    *
*  locking up the user's terminal, the I$GetStt function SS_DevNm     *
*  is used to open an independent path to the user's terminal.        *
*  I$Dup is not used, because any changes made to the option          *
*  section would have to be remembered and un-done before Kermit      *
*  could safely exit.  This was a major problem in debugging since    *
*  crashing Kermit locked up the terminal until this solution was     *
*  used.                                                              *
***********************************************************************
SysInit:  move.l    a5,CmdLinPt(a6)    Save address of command line parms
          move.l    a5,a0
SysInit2  move.b    (a0)+,d0
          beq.s     SysInit3
          cmp.b     #Asc_CR,d0
          bne.s     SysInit2
          clr.b     -(a0)              Make sure it is NULL terminated!!

*  Connect the Terminal channel to the same device as stdin

SysInit3  clr       d0                 Stdin
          moveq     #SS_DevNm,d1       Ask for name of device
          lea       ShellCmd(a6),a0    An empty buffer to retrieve name
          move.b    #'/',(a0)+
          os9       I$GetStt           Find out the name.
          bcs.s     SysInit4

          moveq     #RdWrOp,d0         Want a read/write access
          moveq     #Terminal,d1       ...to the terminal
          lea       ShellCmd(a6),a0
          bsr       FilOpen            open it up.
          tst.b     d0
          beq.s     SysInit4

*  Set proper terminal operating modes

          moveq     #Terminal,d1       Channel number of terminal
          bsr       CCTxtMode          Set text mode I/O parameters.
          rts

*  OS-9 reported an error while we were trying to initialize the terminal

SysInit4  lea       SysInErr(pc),a0
          moveq     #1,d0              Stdout
          moveq     #127,d1            Long length
          os9       I$WritLn
          os9       F$Exit

SysInErr  dc.b      "Can't initialize terminal path properly, exiting."
          dc.b      Asc_CR,Asc_Nul
          align


********************************* SysExod *****************************
*                                                                     *
*  Return control to system.                                          *
*                                                                     *
*         Entry conditions : D0.B completion code, exit status        *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
SysExod:  clr.b     d1                 No error
          os9       F$Exit             Closes all files for us, exits to system


******************************** GetCmdLP *****************************
*                                                                     *
*  Try to return a pointer to the command line, null terminated.      *
*                                                                     *
*         Entry conditions : none                                     *
*                                                                     *
*         Exit  conditions : A0.L pointer to the command line, if any *
*                            D0.B completion code                     *
*                                                                     *
***********************************************************************
GetCmdLP: move.l    CmdLinPt(a6),a0
          tst.b     (a0)               Command line null?
          sne       d0                 Set completion code accordingly
          RTS
          pag
          nam       Kermit68K
          ttl       OS-9/68000 Dependent module (part 2)

*         Kermit68K: source file K68SY2
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, May 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* OS9/68000 Modifications performed by Steve Williams
* University of Texas at Austin, June, 1987
*
*  Revision History:
*    Edition  Date      Author  Description
*       0     87/03/25  spw     Initial implementation for OS-9/68K
*       1     87/04/16  spw     Rough code for ExpandFN (no wildcarding)
*       2     87/04/22  spw     Changes to SysExod
*       3     87/04/24  spw     Added the System services
*       4     87/05/05  spw     Revised FilOpen, FilClose for new path number
*                               handling.  Split ExpandFN, GetNxtF, CRemTLoc,
*                               NewName, and Sleep to k68os9p3.a
*       5     87/06/05  spw     Added SysCommd handling to System function

********************************** System *****************************
*                                                                     *
*  Performs system commands. Called with a request code and 0, 1 or 2 *
*  null terminated argument strings, depending on request code.       *
*                                                                     *
*         Entry conditions : D0.B Request Code (see below)            *
*                                                                     *
*         RC symbol             Meaning                               *
*                                                                     *
*         SysCommd              Forward command to operating system   *
*         Directry              Display a directory listing           *
*         SpacInfo              Display informations about disk usage *
*         DeletFil              Delete file(s)                        *
*         CopyFile              Copy file(s)                          *
*         ChangDir              Change the default directory          *
*         PrntFile              Print file(s)                         *
*         RenamFil              Rename file(s)                        *
*         TypeFile              Type file(s)                          *
*                                                                     *
*                            A0.L pointer to argument 1 (see below)   *
*                            A1.L pointer to argument 2 (see below)   *
*                                                                     *
*         RC symbol             Arguments number and meaning          *
*                                                                     *
*         Directry              0 or 1  directory path                *
*         SpacInfo              0 or 1  device or account name        *
*         DeletFil              1       file name                     *
*         CopyFile              2       source and target file names  *
*         ChangDir              0 or 1  path to new directory         *
*         PrntFile              1       file name                     *
*         RenamFil              2       old and new file names        *
*         TypeFile              1       file name                     *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
*  NOTES:  This routine saves all of the registers that it uses and   *
*    restores all of them on return, except of course, d0             *
***********************************************************************
System:   movem.l   d1-d4/a0-a3,-(sp)      Save the working registers.
          add.w     d0,d0                  Compute offset in...
          move.w    SysCmdTbl(pc,d0.w),d1  ...command routine offset table
          jmp       SysCmdTbl(pc,d1.w)     Jump to the routine.

SysCmdTbl dc.w      SysHandle-SysCmdTbl  for SysCommd
          dc.w      SysFork-SysCmdTbl    for Directry
          dc.w      SysFork-SysCmdTbl    for SpacInfo
          dc.w      FilDel_0-SysCmdTbl   DeletFil
          dc.w      SysFork-SysCmdTbl    CopyFile
          dc.w      SysCWD-SysCmdTbl     ChangDir
          dc.w      SysFork-SysCmdTbl    PrntFile
          dc.w      SysFork-SysCmdTbl    Rename
          dc.w      SysFork-SysCmdTbl    TypeFile

SysHandle lea       ShellCmd(a6),a1
SysHnd_1  move.b    (a0)+,(a1)+        Move the command line to the shell buffer
          bne.s     SysHnd_1
          bra.s     SysFork3
          rts

SysCWD    tst.b     (a0)               Null string?
          beq.s     SysCWD2
          move.w    #Updat_,d0         Change data directory
          os9       I$ChgDir
SysCWD2   scc       d0                 Set condition code
          movem.l   (sp)+,d1-d4/a0-a3
          rts

*  Come here for those commands that we can just fork to a shell

SysFork   move.w    ShellOff(pc,d0.w),d1  Got offset to string in string table
          move.w    ShellOps(pc,d0.w),d2  Get number of operands.
          lea       ShellOff(pc,d1.w),a2  Got address of string.
          lea       ShellCmd(a6),a3       Need to set up the shell command
          bra.s     SysFork2

*  Table of number of command arguments for each command.  For those commands
*  with optional arguments, these are the maximum number of arguments.
*
*  The -1 entries in this table are for the commands that are taken care
*  of directly in Kermit.

ShellOps  dc.w     -1                  SysCmd
          dc.w      1                  Directry
          dc.w      1                  SpacInfo
          dc.w     -1                  DeletFil
          dc.w      2                  CopyFile
          dc.w     -1                  ChangDir
          dc.w      1                  PrntFile
          dc.w      2                  RenamFil
          dc.w      1                  TypeFile

*  Table of offsets to the actual command strings

ShellOff  dc.w     -1                  SysCmd
          dc.w      Directry-ShellOff
          dc.w      SpacInfo-ShellOff
          dc.w     -1
          dc.w      CopyFile-ShellOff
          dc.w     -1
          dc.w      PrntFile-ShellOff
          dc.w      RenamFil-ShellOff
          dc.w      TypeFile-ShellOff

*  Build the shell paramter list in ShellCmd(a6)

SysFork2  move.b    (a2)+,(a3)+        Move byte of the command name
          bne.s     SysFork2
          move.b    #' ',-1(a3)        Put in a space separator

          move.l    a0,a2              Move on-deck to batter's box
          move.l    a1,a0              In the hole -> on-deck
          dbf       d2,SysFork2        Go until the parameters are out.

          move.b    #Asc_CR,-1(a3)     Terminate the command with a CR
          clr.b     (a3)               ...and then a nul

*  Fork a shell to process the newly constructed command line at this point,
*  the registers a0-a3 and d2-d4 have been stacked with a movem instruction.

SysFork3  move.w    #(Prgrm<<8)+Objct,d0
          moveq     #0,d1              No extra memory
          move.l    a3,d2              End of parameter list
          lea       ShellCmd(a6),a1    Beginning of parameter list
          sub.l     a1,d2              Length of parameter list
          lea       ShellNam(pc),a0    Address of shell's name
          move.w    #3,d3              Inherit all my stdio paths.
          clr.w     d4                 Don't care about the priority

          os9       F$Fork
          bcs.s     SysErr             Error, must put terminal back...
*                                      ...to proper mode.

*  Wait for the child process to die.

          os9       F$Wait

SysErr    scc       d0                 If no OS-9 error, return good completion.
          movem.l   (sp)+,d1-d4/a0-a3
          RTS

Directry  dc.b      "dir",Asc_Nul
SpacInfo  dc.b      "free",Asc_Nul
CopyFile  dc.b      "copy",Asc_Nul
PrntFile  dc.b      "list >/p",Asc_Nul
RenamFil  dc.b      "rename",Asc_Nul
TypeFile  dc.b      "list",Asc_Nul

ShellNam: dc.b      "Shell",Asc_Nul
          align

********************************* FilOpen *****************************
*                                                                     *
*  Open a disk file or an I/O channel.                                *
*                                                                     *
*         Entry conditions : D0.B Request Code (see below)            *
*                                                                     *
*              RC symbol        Meaning                               *
*                                                                     *
*              RdWrOp           Open for read/write                   *
*              ReadOp           Open for read                         *
*              WriteOp          Open for write                        *
*              AppendOp         Open for append                       *
*                                                                     *
*                            D1.B logical channel number.             *
*                            A0.L points to file name null terminated *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L still points to the file name       *
*                                                                     *
***********************************************************************
FilOpen:  movem.l   d1-d3/a0-a1,-(sp)   Save the working registers
          move.w    d0,d2               Save a copy of the file access mode
          add.w     d1,d1               Convert channel number to offset...
*                                       ...in OS-9 lookup table
          move.w    d1,d3               Save a copy of the logical...
*                                       ...(Kermit68K) channel number
          add.w     d0,d0               Compute offset into lookup table...
*                                       ...for mode
          lea       OS9OpCd(pc),a1
          move.w    (a1,d0.w),d0        Get the OS-9 open code corresponding

FilOp_1   cmp.w     #WriteOp,d2         Are we going to write to file?
          beq.s     FilOp_6             Yes, handle differently.

          os9       I$Open              No, try to open it
          bcc.s     FilOp_2             No error on the open

          cmp.w     #E$PNNF,d1          Path name not found?
          bne.s     FilOp_5             Other error, get out of here.
          cmp.w     #ReadOp,d2          Trying to read this file?
          beq.s     FilOp_5             Can't read from inexistent files

          move.w    d2,d0               Get the access mode value again
          add.w     d0,d0
          lea       OS9OpCd(pc),a1
          move.w    (a1,d0.w),d0        Get the access mode needed
          move.w    #Updat_,d1          Set read/write permanent permission bits
          move.l    (sp),a0             Restore the file name address
          os9       I$Create            Create the file
          bcs.s     FilOp_5             Can't even come close to open, get out

*  Connect the logical channel to the returned OS-9 path number

FilOp_2   lea       Pathnums(a6),a0     Set the path number
          move.w    d0,(a0,d3.w)
          cmp.b     #AppendOp,d2        Doing an append?
          bne.s     FilOp_4             No, leave the file where it is...
*                                       ...(d0 is non-zero)

*  For an append, find out how big the file is (with I$GetStt)
*  and then seek to end

          move.w    #SS_Ready,d1        Going to find out how big the file is.
          os9       I$GetStt
          bcs.s     FilOp_5
          move.l    d2,d1               Copy the current size
          os9       I$Seek              So we can seek to current end + 1
          bcs.s     FilOp_5

FilOp_4   st        d0                  return good completion
          movem.l   (sp)+,d1-d3/a0-a1
          rts

FilOp_5   sf        d0                  return bad completion code.
          movem.l   (sp)+,d1-d3/a0-a1   restore the working registers
          rts

*  Code to handle opening for write access

FilOp_6   bsr       FilDelet            Try to delete the file
          move.w    #Write_,d0          Write mode access
          move.w    #Updat_,d1          Read and write attributes (permanent)
          os9       I$Create
          bcs.s     FilOp_5             Error, quit now.
          bra       FilOp_2             Go into code to set path number properly

*  Lookup/translation table to convert the open request modes of Kermit68K to
*  the standard modes of OS-9

OS9OpCd   dc.w      Updat_              OS-9 Updat_ mode <--> RdWrOp of Kermit
          dc.w      Read_               <--> ReadOp of Kermit
          dc.w      Write_              <--> WriteOp of Kermit
          dc.w      Write_              <--> AppendOp of Kermit (with seek)

******************************** FilClose *****************************
*                                                                     *
*  Close a disk file or an I/O channel.                               *
*                                                                     *
*         Entry conditions : D1.B logical channel number.             *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
FilClose: movem.l   d1/a0,-(sp)

          add.w     d1,d1               Double channel number for offset
          lea       Pathnums(a6),a0     Base of path number lookup table
          move.w    (a0,d1.w),d0        Get the path number for the channel

          clr.w     (a0,d1.w)           Mark path as unused
          tst.w     d0                  Was the path ever used?
          beq.s     FilCls_1            ...no, don't close it.
          os9       I$Close             Close the path

FilCls_1  movem.l   (sp)+,d1/a0
          st        d0                  return success
          RTS

********************************* FilDelet ****************************
*                                                                     *
*  Delete a file.                                                     *
*                                                                     *
*         Entry conditions : A0.L points to file name null terminated *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                                                                     *
***********************************************************************
FilDel_0  movem.l   (sp)+,d1-d4/a0-a3   Restore regs pushed by System
FilDelet: move.l    a0,-(sp)            I$Delete clobbers a0
          move.w    #Read_,d0           Get the file in current DATA directory
          os9       I$Delete
          scc       d0                  Return success
          move.l    (sp)+,a0            Restore file name pointer
          rts
          align
          pag
          nam       Kermit68K
          ttl       OS-9/68000 Dependent module (part 3)

*         Kermit68K: source file K68SY3
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, February 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* OS9/68000 Modifications performed by Steve Williams
* University of Texas at Austin, June, 1987
*
*  Revision History:
*    Edition  Date      Author  Description
*       0     87/05/05  spw     Separated from k68os9p2.a
*       1     87/05/25  spw     Added code to handle wildcards
*       2     87/06/05  spw     Added CLocTRem for converted file names

********************************* ExpandFN ****************************
*                                                                     *
*  Expand a wildcard file name into an array of file names, returns   *
*  the number of files that match the passed string, with data        *
*  structures set up so that the first file name (if any) will be     *
*  returned by the next GetNxtF call.                                 *
*                                                                     *
*         Entry conditions : A0.L points to file name null terminated *
*                                                                     *
*         Exit  conditions : D0.L number of matches found, negative   *
*                                 if too many matches for user buffer *
*                            A0.L still points to the file name       *
*                                                                     *
***********************************************************************
ExpandFN: movem.l   d1-d4/a0-a3,-(sp)   Save working registers
          moveq     #0,d0               Clear character pointer.
          lea       FNBuffer(a6),a1     Point to first file name in buffer
          move.l    a1,NextFile(a6)     Save address of first file name
ExpFN_1   move.b    (a0,d0.l),d1
          move.b    d1,(a1,d0.l)        Copy the file name.
          beq.s     ExpFN_2             End of string and no wild card
          cmp.b     #'?',d1
          beq.s     ExpandWC            Handle the wildcard case.
          cmp.b     #'*',d1
          beq.s     ExpandWC            Do wildcard expansion.
          addq      #1,d0
          bra.s     ExpFN_1

ExpFN_2   moveq     #1,d0     One match
          move.l    d0,NumFiles(a6)     Set up for GetNxtF
          movem.l   (sp)+,d1-d4/a0-a3
          rts

*  The file name contains wildcards a0 still points to beginning of
*  wild card file name.
*
*  This version will handle wildcards if they are in the current directory.

ExpandWC  move.b    #'/',d0             Going to look for a directory specifier.
          move.l    a0,a1               Copy beginning of string pointer.
          sf        d1                  Haven't found a directory terminator
          moveq     #64,d2              Set a limiting count

ExpWC_1   cmp.b     (a1),d0             Is this a directory separator?
          seq       d3                  Set a flag
          or.b      d3,d1               Keep a permanent indicator
          tst.b     (a1)+               End of string?
          dbeq      d2,ExpWC_1          Go back until we find end of string.

          tst.b     d1                  Was there a directory separator?
          beq.s     ExpWC_2             ...no, do the expansion.

          move.l    a0,-(sp)            Save the file name pointer
          lea       BadWCMsg(pc),a0
          moveq     #1,d0               Stdout
          moveq     #127,d1             Long length
          os9       I$WritLn
          move.l    (sp)+,a0            Restore the file name pointer

          moveq     #0,d0               Signal no matches
          move.l    d0,NumFiles(a6)
          movem.l   (sp)+,d1-d4/a0-a3
          rts

BadWCMsg  dc.b      "Wildcarded filenames must be in current directory."
          dc.b      Asc_CR,Asc_Nul
          align

*  The files should all be in the current directory, so a shell can be forked
*  to execute an 'echo' command which will return a list of matches.

ExpWC_2   lea       EchoOpts(pc),a1     Pointer to the option list needed
          lea       ShellCmd(a6),a2     Point to parameter list

ExpWC_3   move.b    (a1)+,(a2)+         Set up the command options
          bne.s     ExpWC_3

          subq      #1,a2               Backup
          move.l    a0,a1               Copy file name pointer
ExpWC_4   move.b    (a1)+,(a2)+         Set up the wild card name
          bne.s     ExpWC_4

* Set up a pipe to read back the output of the echo command

          moveq     #1,d0               StdOut
          os9       I$Dup               Duplicate current standard output path
          move      d0,-(sp)            Save the duplicated path number
          moveq     #1,d0
          os9       I$Close             close stdout
          lea       PipeName(pc),a0
          move.w    #Updat_,d0          I need to read, he needs to write
          os9       I$Open              Open up the pipe (it will become path 1)

*  Now that the pipe is open, fork a shell to process the command

          move.w    #(Prgrm<<8)+Objct,d0
          moveq     #0,d1               No extra memory
          move.l    a2,d2               End of parameter list
          lea       ShellCmd(a6),a1     Beginning of parameter list
          sub.l     a1,d2               Length of parameter list
          lea       ShellNam(pc),a0     Address of shell command name
          move.w    #3,d3               Inherit all my stdio paths.
          clr.w     d4                  Don't care about the priority
          os9       F$Fork

*  Now, read the lines of output that match the wild card.

          lea       FNBuffer(a6),a0     Pointer to where to put file name
          moveq     #0,d3               Counter for file names.

ExpWC_5   moveq     #1,d0               The path number of the pipe
          moveq     #80,d1              read a line's worth
          os9       I$ReadLn            read a line
          bcs.s     ExpWC_8             End of file?

*  Got a name read in, now, update the pointer and count and go back for more

          move.b    #Asc_CR,d0
ExpWC_6   cmp.b     (a0)+,d0            Is it a Carriage return?
          bne.s     ExpWC_6             ...no, go back.

          clr.b     -1(a0)              Change the CR to a string terminator
          addq      #1,d3               Bump the file name count
          cmp.l     #50,d3              A limit on the number of files
          blo.s     ExpWC_5

*  too many file names matched, so read pipe until empty then quit.

ExpWC_7   lea       FNBuffer(a6),a0
          moveq     #1,d0
          moveq     #80,d1
          os9       I$ReadLn
          bcc.s     ExpWC_7
          moveq     #-1,d3              Signal too many matches

ExpWC_8   os9       F$Wait              Wait for the child to exit.
          moveq     #1,d0               Must close the pipe
          os9       I$Close
          move.w    (sp),d0             Get the saved path number for our stdout
          os9       I$Dup
          move.w    (sp)+,d0            Close the duplicated stdout
          os9       I$Close
          move.l    d3,NumFiles(a6)
          move.l    d3,d0               Return number of files matching.
          movem.l   (sp)+,d1-d4/a0-a3
          rts

PipeName  dc.b      "/pipe",0
EchoOpts  dc.b      "echo -n ",0
          align

********************************* GetNxtF *****************************
*                                                                     *
*  Get the next file name from the list created by ExpandFN, returns  *
*  a true completion code if there's another file, copying its name   *
*  into the target string, or false if no more file names in list.    *
*                                                                     *
*         Entry conditions : A0.L points to the target string         *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L points to the target string         *
*                                                                     *
***********************************************************************
GetNxtF:  move.l    NumFiles(a6),d0     any left to get?
          beq.s     GetNF_2             No, so get on out of here.

          subq      #1,d0
          move.l    d0,NumFiles(a6)     Re-set number of files left
          movem.l   a0-a1,-(sp)
          movea.l   NextFile(a6),a1     Get address of this file name string

GetNF_1   move.b    (a1)+,(a0)+         Move a byte
          bne.s     GetNF_1             Until null encountered
          move.l    a1,NextFile(a6)     Save updated pointer
          movem.l   (sp)+,a0-a1
          st        d0                  true result
          rts

GetNF_2   sf        d0                  false result
          rts


********************************* CRemTLoc ****************************
*                                                                     *
*  Convert filenames from remote system in a form suitable for the    *
*  local system.                                                      *
*                                                                     *
*         Entry conditions : A0.L points to the string to be          *
*                                 converted                           *
*                                                                     *
*         Exit  conditions : A0.L points to the same string suitably  *
*                                 converted                           *
*                                                                     *
*  OS-9/68000 Notes:                                                  *
*    This routine will replace any illegal punctuation characters     *
*  including the directory separator '/' and device raw-mode specifer *
*  '@' with the underline character, which is legal for OS-9 path     *
*  names.                                                             *
***********************************************************************
CRemTLoc: move.l    d1,-(sp)
          clr.w     d0                  Zero out counter
          moveq     #FilNamML-1,d1      File name string maximum length in OS-9
CRTL_1    tst.b     (a0,d0.w)           Find length of string.
          beq.s     CRTL_2              Found the null
          addq      #1,d0               Keep counting
          dbf       d1,CRTL_1           ...until length exceeded
          clr.b     0(a0,d0.w)          Terminate the string properly.

CRTL_2    subq      #1,d0               Backup to last byte of string
CRTL_3    move.b    0(a0,d0.w),d1
          cmp.b     #'/',d1
          beq.s     CRTL_4              A slash foul (means a directory).
          cmp.b     #'.',d1
          beq.s     CRTL_5              A period is ok
          cmp.b     #'_',d1
          beq.s     CRTL_5              An underscore is ok
          cmp.b     #'0',d1
          blo.s     CRTL_4              Other punctuation $20-$2f is foul
          cmp.b     #'9',d1
          bls.s     CRTL_5              Digits are OK
          cmp.b     #'A',d1
          blo.s     CRTL_4              ':;<=>?@' are bad
          cmp.b     #'Z',d1
          bls.s     CRTL_5              Capital letters ok
          cmp.b     #'a',d1
          blo.s     CRTL_4              '[\]^' are bad
          cmp.b     #'z',d1
          bls.s     CRTL_5              Lower case letters OK
CRTL_4    move.b    #'_',0(a0,d0.w)     Replace the illegal character
CRTL_5    dbf       d0,CRTL_3           Loop backwards through the string

          move.b    (a0),d0             Check first character of string...
*                                       ...for alphabetic
          cmp.b     #'A',d0
          blo.s     CRTL_6              Less than 'A' -> not alpha
          cmp.b     #'Z',d0
          bls.s     CRTL_7              In 'A'..'Z' -> alpha
          cmp.b     #'a',d0
          blo.s     CRTL_6              Less than 'a' -> not alpha
          cmp.b     #'z',d0
          bls.s     CRTL_7              In 'a'..'z' -> alpha
CRTL_6    sf        d0                  Invalid file name
          move.l    (sp)+,d1            restore working reg.
          rts
CRTL_7    st        d0                  Valid file name
          move.l    (sp)+,d1            restore working reg.
          rts

********************************* CLocTRem ****************************
*                                                                     *
*  Convert filenames in local system syntax in a form suitable for    *
*  the remote Kermit system. The job that this routine must do is     *
*  explained here in detail.                                          *
*                                                                     *
*  Adapted from the "Kermit Protocol Manual", Sixth Edition, p. 16    *
*                                                                     *
*   1. Delete all pathnames and attributes from the file              *
*      specification. The file name should not contain directory      *
*      or device names  if it does, it may cause the recipient to     *
*      try to store the file in an inaccessible or nonexistent area,  *
*      or it may result in a very strange filename.                   *
*                                                                     *
*   2. After stripping any pathname, convert the remainder of the     *
*      file specification to the form "name.type", with no            *
*      restriction on length (except that it fit in the data field    *
*      of the F packet), and:                                         *
*                                                                     *
*         a. Include no more than one dot.                            *
*         b. Not begin or end with a dot.                             *
*         c. The name and type fields contain digits and uppercase    *
*            letters only.                                            *
*                                                                     *
*         Entry conditions : A0.L points to the string to be          *
*                                 converted                           *
*                                                                     *
*         Exit  conditions : A0.L points to the same string suitably  *
*                                 converted                           *
*                                                                     *
***********************************************************************
CLocTRem: movem.l   d1-d3/a1,-(sp)
          clr.w     d0                  Zero out counter
          moveq     #FilNamML-1,d1      File name string Maximum length in OS-9
CTRL_1    tst.b     (a0,d0.w)           Find length of string.
          beq.s     CTRL_2              Found the null
          addq      #1,d0               Keep counting
          dbf       d1,CTRL_1           ...until length exceeded
          clr.b     0(a0,d0.w)          Terminate the string properly.

CTRL_2    move.l    a0,a1               point to start of string
          move.w    d0,d3               Save string length
          subq      #1,d0               one less for dbf loop.

*  Is there a leading pathname?

          move.b    #'/',d1             Looking for a directory mark.
CTRL_21   cmp.b     (a1,d0.w),d1
          dbeq      d0,CTRL_21          Exit loop when one found.
          bne       CTRL_29             None found

*  Move the simple file name forward in the name buffer.

          lea       1(a1,d0.w),a1       Point to first character of file name
          move.w    d3,d1               Get original length of string.
          sub.w     d0,d1               Get length of simple file name.
          subq      #1,d1               ...minus one for dbf loop
CTRL_22   move.b    (a1,d1.w),(a0,d1.w) Move the simple file name forward
          dbf       d1,CTRL_22

*  Restore the counter and pointer for the next loop

CTRL_29   move.l    a0,a1               Copy start of string address
          move.w    d3,d0               Get count of string length
          subq      #1,d0               ...minus one for the dbf loop.

*  Replace any punctuation with periods.

CTRL_3    move.b    (a1)+,d1
          cmp.b     #'0',d1
          blo.s     CTRL_4              Punctuation $20-$2f is foul
          cmp.b     #'9',d1
          bls.s     CTRL_5              Digits are OK
          cmp.b     #'A',d1
          blo.s     CTRL_4              ':;<=>?@' are bad
          cmp.b     #'Z',d1
          bls.s     CTRL_5              Capital letters ok
          cmp.b     #'a',d1
          blo.s     CTRL_4              '[\]^' are bad
          cmp.b     #'z',d1
          bls.s     CTRL_5              Lower case letters OK
CTRL_4    move.b    #'.',-1(a1)         Replace the illegal character
CTRL_5    dbf       d0,CTRL_3           Loop backwards through the string

*  Make the string all capitals

          move.l    a0,a1               Point to start of string
          move.w    d3,d0               Count of characters.
          subq.w    #1,d0               Account for dbf loop.

CTRL_6    move.b    (a1)+,d1            Get a byte of string.
          cmp.b     #'a',d1
          blo.s     CTRL_7              Less than 'a' -> not lower case alpha
          cmp.b     #'z',d1
          bhi.s     CTRL_7              Not in 'a'..'z' -> not lower case alpha
          sub.b     #'a'-'A',d1
          move.b    d1,-1(a1)           Replace character
CTRL_7    dbf       d0,CTRL_6           Go back for more.

*  Can't begin or end with a '.'

          move.b    #'.',d1
          cmp.b     (a0),d1             Is first character a period?
          bne.s     CTRL_8
          move.b    #'X',(a0)           Replace with an 'X'
CTRL_8    cmp.b     -1(a0,d3),d1        Last character a period?
          bne.s     CTRL_9
          move.b    #'X',-1(a0,d3)


* Replace all but first period with 'X'

CTRL_9    move.l    a0,a1               Point to start of string.
          sf        d2                  Haven't found a period yet.
          move      d3,d0               Counter
          subq      #1,d0               account for dbf loop.

CTRL_10   cmp.b     (a1)+,d1            Get a byte of the string
          bne.s     CTRL_12             Not a period, leave it alone
          tst.b     d2                  Seen a period?
          beq.s     CTRL_11             ...not yet, leave this one alone

          move.b    #'X',-1(a1)         mask out the period
CTRL_11   st        d2                  We've seen a period now.
CTRL_12   dbf       d0,CTRL_10
          st        d0                  Valid file name
          movem.l   (sp)+,d1-d3/a1
          rts

********************************** NewName ****************************
*                                                                     *
*  Make a new name for the given file to avoid file name collisions.  *
*                                                                     *
*         Entry conditions : A0.L points to the file name string      *
*                                                                     *
*         Exit  conditions : A0.L points to the same string suitably  *
*                                 modified                            *
*                                                                     *
*  OS-9 Note:  This routine just places an underscore character at    *
*    beginning of the file name to rename it.                         *
***********************************************************************
NewName:  move.l    a1,-(sp)
          move.l    a0,a1               Copy string pointer
          moveq     #FilNamML-2,d0      Start from the end of longest file name

NewNm_1   move.b    0(a0,d0.w),1(a0,d0.w) Move the current name one byte forward
          dbf       d0,NewNm_1          Keep counting back through string

          move.b    #'_',(a0)           Put an underscore at start of string
          clr.b     FilNamML(a0)        Make sure string is null terminated.
          st        d0                  Set a good completion code
          move.l    (sp)+,a1
          rts

********************************** Sleep ******************************
*                                                                     *
*  Puts the process to sleep.                                         *
*                                                                     *
*         Entry conditions : D0.B time interval to wait (seconds)     *
*                                                                     *
*         Exit  conditions : none                                     *
*                                                                     *
***********************************************************************
Sleep:    move.l    d1,-(sp)
          ext.w     d0                  Need to pass a long tick count
          ext.l     d0                  ...extending some more.
          asl.l     #8,d0               Compute 256ths of second to sleep
          moveq     #31,d1              Need to set the high bit...
          bset      d1,d0               ...of the tick count, in order...
          os9       F$Sleep             ...to achieve system independence.
          move.l    (sp)+,d1
          rts

          align
          ends
          end
<<< k6outf.asm >>>
          nam       Kermit68K
          ttl       Utility subroutines module

*         Kermit68K: source file K68UTF
*
* Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet),
* Bologna University, Physics Department, July 1987.
*
* All rights reserved to Bologna University, Italy.
*
* Permission is granted to any individual or institution
* to use, copy, or redistribute this software so long as
* it  is not  sold for  profit, provided  this copyright
* notice is retained.
*
* Modification History:
*
* Version  Date    Who              Comments
*
* 1.0.00   870701  Roberto Bagnara  First official release

          use       DefsFile

Edition   equ       0
          psect     K68UtilitySubs,0,0,Edition,0,0

********************************* CopyStr *****************************ok
*                                                                     *
*  Null terminated strings copy subroutine.                           *
*                                                                     *
*         Entry conditions : D0.W target string maximum length        *
*                            A0.L pointer to target string            *
*                            A1.L pointer to source string            *
*                                                                     *
*         Exit  conditions : A0.L pointer to target string            *
*                            A1.L pointer to source string            *
*                                                                     *
***********************************************************************
CopyStr:  TST.W     D0                 Null strings ?
          BEQ.S     CopyStr4           Yes, do nothing
          MOVEM.L   A0-A1,-(A7)        Save pointers
CopyStr1  SUBQ.W    #1,D0              Decrement counter
          BNE.S     CopyStr2           Continue copy, if there is room
          MOVE.B    D0,(A0)            End of target string, write terminator
          BRA.S     CopyStr3           Restore pointers and return
CopyStr2  MOVE.B    (A1)+,(A0)+        Copy a character
          BNE.S     CopyStr1           Repeat until end of source string
CopyStr3  MOVEM.L   (A7)+,A0-A1        Restore pointers
CopyStr4  RTS

********************************* CompStr *****************************ok
*                                                                     *
*  Null terminated strings compare subroutine.                        *
*                                                                     *
*         Entry conditions : A0.L pointer to string 1                 *
*                            A1.L pointer to string 2                 *
*                                                                     *
*         Exit  conditions : D0.B completion code                     *
*                            A0.L pointer to string 1                 *
*                            A1.L pointer to string 2                 *
*                                                                     *
***********************************************************************
CompStr:  MOVEM.L   A0-A1,-(A7)        Save pointers
CompStr1  MOVE.B    (A0)+,D0           Get a character from string 1
          CMP.B     (A1)+,D0           Compare whit string 2 correspondent char
          BNE.S     CompStr2           Compare failed, exit loop
          TST.B     D0                 Compare succeed, end of strings ?
          BNE.S     CompStr1           No, stay in loop
CompStr2  SEQ       D0                 Set completion code accordingly
          MOVEM.L   (A7)+,A0-A1        Restore pointers
          RTS

********************************* DoPrity *****************************ok
*                                                                     *
*  Add an appropriate parity bit to a character.                      *
*                                                                     *
*         Entry conditions : D0.B 7-bit character                     *
*                                                                     *
*         Exit  conditions : D0.B character with parity bit added     *
*                                                                     *
***********************************************************************
DoPrity:  MOVEM.L   D1-D2,-(A7)        Save working registers
          MOVE.B    Parity(A6),D1      Some kind of parity enabled ?
          BEQ.S     DoPrity5           No, return
          ANDI.B    #$7F,D0            Clear bit 7
          CMPI.B    #'M',D1            Mark ?
          BNE.S     DoPrity1           No
          ORI.B     #$80,D0            Yes, set bit 7
          BRA.S     DoPrity5           Return
DoPrity1  CMPI.B    #'S',D1            Space ?
          BEQ.S     DoPrity5           Yes, return, bit 7 already cleared
          CLR.B     D2                 Clear the ones counter
          CMPI.B    #'O',D1            Odd ?
          BNE.S     DoPrity2           No
          ADDQ.B    #1,D2              Yes, the ones counter starts from 1
DoPrity2  MOVEQ     #6,D1              Set up for bit addressing
DoPrity3  BTST      D1,D0              Bit setted ?
          BEQ.S     DoPrity4           No, try the next
          ADDQ.B    #1,D2              Yes, increment the counter
DoPrity4  DBF       D1,DoPrity3        Repeat for bits 6-0
          LSL.B     #7,D2              Position the parity bit
          OR.B      D2,D0              Ok, that's all
DoPrity5  MOVEM.L   (A7)+,D1-D2        Restore working registers
          RTS

****************************** HndlPar ********************************ok
*                                                                     *
*  Handle 8-th bit accordingly to parity selected.                    *
*                                                                     *
*         Entry conditions : D0.B character to be processed           *
*                                                                     *
*         Exit  conditions : D0.B processed character                 *
*                                                                     *
***********************************************************************
HndlPar:  TST.B     Parity(A6)         Parity selected ?
          BEQ.S     HndlPar1           No, do nothing
          ANDI.B    #$7F,D0            Yes, mask parity bit
HndlPar1  RTS

********************************* UDiv ********************************ok
*                                                                     *
*  32-bit/16-bit unsigned division.                                   *
*                                                                     *
*         Entry conditions : D2.L dividend                            *
*                            D3.W divisor                             *
*                                                                     *
*         Exit  conditions : D0.L quotient                            *
*                            D1.L remainder                           *
*                                                                     *
***********************************************************************
UDiv:     MOVE.L    D2,D0              Get Dividend
          CLR.W     D0                 Clear lower part
          SWAP      D0                 Upper Dividend
          DIVU      D3,D0              Divide
          MOVE.W    D0,-(A7)           Save upper quotient
          MOVE.W    D2,D0              Remainder and lower Dividend
          DIVU      D3,D0              Divide
          SWAP      D0
          CLR.L     D1
          MOVE.W    D0,D1              Final remainder
          MOVE.W    (A7)+,D0           Lower and upper quotients
          SWAP      D0                 Final quotient
          RTS                          Return

******************************* IntToAs *******************************ok
*                                                                     *
*  Integer to ASCII string conversion routine.                        *
*                                                                     *
*         Entry conditions : A0.L pointer to string buffer end        *
*                            D0.L number to convert                   *
*                            D1.B flag for signed or unsigned number  *
*                            D2.L field length                        *
*                            D3.L number base                         *
*                                                                     *
*         Exit  conditions : A0.L pointer to string buffer start      *
*                                                                     *
***********************************************************************
IntToAs:  MOVEM.W   D4-D6,-(A7)        Save working registers
          MOVE.B    D1,D4              Load our flag for negative numbers
          BEQ.S     IntToAs1           Unsigned number processing wanted
          TST.L     D0                 Signed, negative number ?
          SLT       D4                 Set our flag accordingly
          BGE.S     IntToAs1           If positive number then continue
          NEG.L     D0                 Else negate it
IntToAs1  MOVE.B    D2,D5              Save field length
          CLR.B     -(A0)              Mark the end of string
          CLR.B     D6                 Clear the character counter
IntToAs2  MOVE.L    D0,D2              Dividend
          BSR       UDiv               Divide number by base (in D3)
          CMPI.B    #9,D1              Convert remainder to ascii
          BGT.S     IntToAs3
          ADDI.B    #$30,D1
          BRA.S     IntToAs4
IntToAs3  ADDI.B    #$37,D1
IntToAs4  MOVE.B    D1,-(A0)           Store the obtained character
          ADDQ.B    #1,D6              Increment the character counter
          TST.L     D0                 End of conversion ?
          BNE.S     IntToAs2           No, repeat
          TST.B     D4                 Yes, was a negative number ?
          BEQ.S     IntToAs5           No, continue
          MOVE.B    #'-',-(A0)         Yes, insert the minus sign
          ADDQ.B    #1,D6              Increment the character counter
IntToAs5  CMP.B     D6,D5              Field full ?
          BLE.S     IntToAs6           Yes
          MOVE.B    #' ',-(A0)         No, write a leading blank
          ADDQ.B    #1,D6              Increment the character counter
          BRA.S     IntToAs5           Continue padding until the field is full
IntToAs6  MOVEM.W   (A7)+,D4-D6        Restore working registers
          RTS

******************************* UppCase *******************************ok
*                                                                     *
*  Make a character upper-cased.                                      *
*                                                                     *
*         Entry conditions : D3.B character to be converted           *
*                                                                     *
*         Exit  conditions : D3.B converted character                 *
*                                                                     *
***********************************************************************
UppCase:  CMPI.B    #'a',D3            Below a ?
          BCS.S     UppCase1           Yes, return
          CMPI.B    #'z',D3            Above z ?
          BHI.S     UppCase1           Yes, return
          SUBI.B    #32,D3             No, make the character upper-cased
UppCase1  RTS

******************************* IndxJump ******************************ok
*                                                                     *
*  Indexed jump, extract an address from a relative addresses table   *
*  and jump to it.                                                    *
*                                                                     *
*         Entry conditions : D0.B index to jump table                 *
*                            A1.L jump table start address            *
*                                                                     *
*         Exit  conditions : none, don't return                       *
*                                                                     *
***********************************************************************
IndxJump: ANDI.W    #$FF,D0            Make sure upper byte is cleared
          LSL.W     #1,D0              Scale factor of 2
          MOVE.W    (A1,D0.W),D0       Load relative pointer
          JMP       (A1,D0.W)          Jump to service subroutine

MacFind:  BSR       UppCasS            Make the macro name upper-cased
          LEA       MacroTbl(A6),A1    Load start address of macro table
          CMPA.L    MTNxtChF(A6),A1    The macro table is empty ?
          BEQ.S     MacFind2           Yes, return a bad completion code
MacFind1  BSR       CompStr            Compare the two names
          TST.B     D0                 The two names are equal ?
          BNE.S     MacFind3           Yes, return the macro address
          BSR       MacSkip            No, skip to next macro name
          TST.B     D0                 It was the last macro ?
          BEQ.S     MacFind1           No, so check this one
MacFind2  MOVEA.L   A1,A0              Yes, this points to table end
          SF        D0                 Return a bad completion code
          RTS
MacFind3  MOVEA.L   A1,A0              This is the desired macro address
          ST        D0                 Return a positive completion code
          RTS

MacSkip:  TST.B     (A1)+              Find the end of the macro name
          BNE.S     MacSkip            Loop until end of macro name found
MacSkip1  TST.B     (A1)+              Find the end of the macro body
          BNE.S     MacSkip1           Loop until end of macro body found
          CMPA.L    MTNxtChF(A6),A1    End of macro table ?
          SEQ       D0                 Set the completion code accordingly
          RTS

UppCasS   MOVE.L    A0,-(A7)
UppCasS1  MOVE.B    (A0),D3
          BEQ.S     UppCasS2
          BSR       UppCase
          MOVE.B    D3,(A0)+
          BRA.S     UppCasS1
UppCasS2  MOVE.L    (A7)+,A0
          RTS

          ends
          END
