.MCall .Module .Module KEDCM6 RELEASE=V02 VERSION=23 COMMENT=,IDENT=NO,AUDIT=NO,GLOBAL=.KEDC6 ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ;+ ;COND ; ; $KED$ ; VIRT$C from KEDCPR controls generation of SOBs ;- ; ;MODULE: KEDCM6 ; ;ABSTRACT: ; ; This is an overlay command module. It includes routines to ; manage the learn macro and executable files facilities. ; .Enable LC .Enable GBL .SbTtl Error Definitions ; ;The following code is included as an error section so that it will be ;pulled out and assembled in the error module also. In this module, the ;error macro is defined to print the error message. In the error module, ;the macro is defined to assemble the message text. ; ;+ ;ERROR ; .IIf NDF,$KED$, .Page .IIf NDF,$KED$, .SbTtl Errors from KEDCM6 module ; ; Module: KEDCM6 ; ; Define the error macros for this module ; .MCall ErrDef ErrDef C6,Error ;Invoke macro to define error macro ;- ;+ ;HELPER ; .IIf NDF,$KED$, .Page .IIf NDF,$KED$, .SbTtl Help from KEDCM6 module ; ; Module: KEDCM6 ; ; Define the help macros for this module ; .MCall HlpDef HlpDef C6 ;Invoke macro to define help macro ;- .SbTtl PSect definition ; ; PSect definition ; PSect KEDCMD .SbTtl .SbTtl TTYSet - Setup the macro facility .SbTtl C.AClr - Clear out all macro buffers ; ;TTYSET ;C.AClr ; ;FUNCTIONAL DESCRIPTION: ; ; Initialize the pointers etc for the macro facility ; C.AClr does not reset the nesting "stack" because the "stack" ; may contain RECOVER (or @) entries. ; .Enable LSB TtySet:: ;~x~ Mov #NstStk,N.Cur ;Set the nesting stack to empty Mov LBfTab,X.Cur ;Initialize the "current" macro Tst (PC)+ ;~x~Skip end check ;>>> why not just Br LrnClr? ;~x~ C.AClr:: ;~x~ EndChk ;~x~End check LrnClr:: ;~x~initialize the learn structure Push ;find out if need to Mov TtBfr,R1 ;Get the address of the buffer Mov R1,LrnNxt ;Save its address Add ..MacS,R1 ;Make address of end of buffer Mov R1,TtBufE ;Save address of end of buffer LrnOff ;Set to not learning IsRec ON 10$ ;~x~Are we recovering a file? ;; Bne 10$ ;Yup, allow execution to continue ExIOff ;Turn off execution 10$: Mov LBfTab,R1 ;~x~Point to Learn Buffer ID table Mov LrnLim,R0 ;Loop thru table 20$: Clr (R1)+ ;~x~Initialize it Sob R0,20$ ;~x~*C* Until done Pop ,SAVE=*C* ;*C* ; Clc ;No error 30$: Return ;~x~ ...... .SbTtl IniJou - Initialize journal file to insert mode ; ;INIJOU ; ;FUNCTIONAL DESCRIPTION: ; ;Just make sure the journal file knows that we're going to start in ;insert mode ; IniJou:: ;~x~ IsJou OFF 30$ ;~x~Are we journaling this session? ;; Beq 30$ ;Nope Mov #Jo$Out,R4 ;Yup, get journal file descriptor Mov #J.Ins,R1 ;Want to begin edit session in journal ; buffer with Mov #J.InL,R3 ;Move this many characters 40$: ;~x~ MovB (R1)+,R0 ; into the journal file Call Journl ;~x~ ; MovB (R1)+,@JTPtr ; into the journal file ; Inc JTPtr ; Sob R3,40$ ;~x~Til there's none left CallR RecPos ;~x~Position zero & include in the file .............. .DsAbl LSB .SbTtl ABTCMD - Abort routine for command mode operations .SbTtl PMTCMD - Journal prompt routine for command mode operations .SbTtl CMDREC - Common code for PMTCMD and ABTCMD ;+ ;ABTCMD ; ;This routine is used when a command mode command is aborted. It forces ;the journal into insert mode, writes the abort record, and returns the ;journal to command mode before the aborted command is written to the journal ;file. ;- ;+ ;PMTCMD ; ;This routine is used when a prompt is encountered while in command mode. ;The journal is forced into insert mode, the prompt response record is ;written, and the journal is forced back to command mode before the ;command that may cause the prompt is written to the journal file. ;- .Enable LSB AbtCmd:: ;~x~ Mov #$WrAbt,R2 ;Routine to write abort record Call CmdRec ;~x~Put all the info in the journal CallR Cancel ;~x~And go cancel the command and return .............. ;So that a second abort record won't ; be written PmtCmd:: ;~x~ SavReg Mov #$WrPmt,R2 ;Routine to write prompt record CmdRec:: ;~x~ IsSEr ON 30$ ;~x~Are we /RECOVERing? IsJou OFF 30$ ;~x~Are we even journaling? No, skip it Mov #Jo$Out,R4 ;Yup, get journal file descriptor Mov #J.Ins,R1 ;Want to get out of command mode to ; process the abort record Mov #J.InL,R3 ;Move into the file 10$: MovB (R1)+,R0 ;~x~ Call $PutCh ;~x~ Sob R3,10$ ;~x~Til done Call @R2 ;~x~Write the record into the file Mov #J.Cmd,R1 ;Want to tell the journal file to go ; back to command mode for the ; processing of the aborted command Mov #J.CmL,R3 ;Move <7> into the file 20$: MovB (R1)+,R0 ;~x~ Call $PutCh ;~x~ Sob R3,20$ ;~x~Til there's none left 30$: Return ;~x~ ...... .DsAbl LSB .SbTtl C.LERN - Set learn mode ; ;C.LERN ; ;FUNCTIONAL DESCRIPTION: ; ; Set learn mode for terminal input ; .Enable LSB C.Lern:: ;~x~ NoEChk ;~x~ Tst LrnFlg Beq 10$ ;~x~Not currently learning Call C.LSto ;~x~Terminate current learn 10$: MovB (R1)+,R0 ;~x~Get the macro identifier *JMP* Bne 20$ ;~x~Branch if one is specified MovB DefBuf,R0 ;Give default a name Call SpcClr ;~x~Default should always be available Br 30$ ;~x~ ........... 20$: TstB @R1 ;~x~Are there any extra characters? Bne 80$ ;~x~Yes, error CmpB R0,DefBuf ;Is it the default buffer? Beq 30$ ;~x~Yup, ok Call IsAlph ;~x~Is this an acceptable macro name? Bcs 80$ ;~x~No, error 30$: Call FndLBf ;~x~Yes, see if it's already being used Bcc 70$ ;~x~It exists already, error Call FndBBf ;~x~Find one that isn't used Bcs 60$ ;~x~All used up MovB R0,@R1 ;*C* Put new identifier in table Mov R2,L.Cur ;*C* Establish new current buffer Mov LrnNxt,L.Buf(R2) ;*C* Begin new buffer Mov LrnNxt,R1 ;*C* Point to the command text IsCmd ON 50$ ;~x~*C* Continue command prompt? Mov #J.Ins,R0 ;*C* Begin buffer with "CHANGE" Mov #J.InL,R3 ;*C* Move this many characters 40$: MovB (R0)+,(R1)+ ;~x~*C* into the learn buffer Sob R3,40$ ;~x~*C* Til there's none left 50$: Mov R1,LnPtr ;~x~*C* Next space is after "CHANGE" ;*C* or buffer beginning Mov LnPtr,L.BEnd(R2) ;*C* End of new buffer LrnOn ;*C* Set learn mode Mov SP,LrnFlg ;*C* Flag there's a learn hap'nin' Return ;~x~No error ...... 60$: ;~x~ ;+ ;HELPER HELPER ;~x~ ;There are no learn buffers left to use. Clear one and reuse it ;- 70$: ;~x~ ;+ ;HELPER HELPER ;~x~ ;There is an active learn buffer with this identifier. Choose another ;identifier or Clear this buffer to reuse it. ;- 80$: ;~x~ ;+ ;HELPER HELPER ;~x~ ;Only single alphabetic characters are accepted as learn buffer names ;- .Dsabl LSB .SBTtl C.SAVE - Save Learn Buffer to a File ;+ ;C.SAVE ; ;FUNCTIONAL DESCRIPTION: ; ; Auxiliary output structures are used to save a macro to a file. ; If no filespec is given, the macro is saved to DK:x.KED, where ; 'x' is the macro name. ;- .Enable LSB C.Save:: ;~x~ NoEChk ;~x~ MovB (R1)+,R0 ;Let's get the name of the macro TstB @R1 ;Is it a single char name (at EOS)? Beq 9$ ;~x~Yes CmpB @R1,# ;Is it a single char name? Beq 9$ ;~x~Yes, ok CmpB @R1,# ;Is it a single char name? Bne InvMcN ;No, invalid name 9$: CmpB R0,DefBuf ;Is it the default buffer? Beq 10$ ;~x~Yup, ok Call IsAlph ;~x~Is it legal? Bcs InvMcN ;~x~No - error 10$: Push R1 ;~x~Save R1 across subroutine Call FndLBf ;~x~Yes, find the learn buffer Bcs 80$ ;~x~It doesn't exist, sorry Pop R1 ;Restore R1 Mov L.BEnd(R2),R3 ;Calculate the number of bytes to copy Sub L.Buf(R2),R3 ; Call SpNor ;~x~Ignore spaces on command line TstB @R1 ;Is this the end of line? Bne 20$ ;~x~No - filespec given Dec R1 ;Yes - go back and use the macro ; indicator for the filename 20$: Call Nest ;~x~Nest because we share buffer w/ @ Mov #Ln$Out,R4 ;Use auxiliary output file Mov KedDef,AuxDef ;Make .KED the default extension Call $OpFil ;~x~Open the file Mov #0,AuxDef ;*C* Back to no default for aux. files Bcs 50$ ;~x~No good Mov L.Buf(R2),R1 ;Start at the beginning of the buffer ;to copy to the file 30$: MovB (R1)+,R0 ;~x~Get a character Call $PutCh ;~x~Put it in the auxiliary file Bcs 100$ ;~x~Error ;+*JMP* RT specific? CmpB R0,# ;Was it a carriage return? Bne 40$ ;~x~Nope MovB #,R0 ;Follow it up with a linefeed Call $PutCh ;~x~ in the auxiliary file Bcs 100$ ;~x~Error ;-*JMP* RT specific? 40$: Sob R3,30$ ;~x~Until done Mov #,R0 ;Mark the end of file with ^Z Call $PutCh ;~x~ Call $ClsFl ;~x~Write the last block and close file 50$: Call UnNest ;~x~UnNest previous input mode 60$: Return ;~x~Done ...... 70$: ;~x~ ;+ ;HELPER HELPER ;~x~ ;filespec to write to was not given ;- 80$: Tst (SP)+ ;~x~Fix SP ;+ ;HELPER HELPER ;~x~ ;no macro by that name has been successfully learned or loaded ;- InvMcN: ;+ ;HELPER HELPER ;~x~ ;Only single alphabetic characters are accepted as learn buffer names ;- 100$: ;~x~ Call UnNest ;~x~Unnest input modes ;+ ;HELPER HELPER ;~x~ ; ;- .Dsabl LSB .SbTtl C.LOAD - Load a macro from a file ;+ ;C.LOAD ; ;FUNCTIONAL DESCRIPTION: ; ; A specified file is read into the specified learn buffer to ; be executed as a macro. If no file name is given on the ; command line, it is assumed to be in DK:x.KED, where 'x' is ; the name of the macro specied. ;- .Enable LSB C.Load:: ;~x~ NoEChk ;~x~ Tst LrnFlg ;Are we learning? Bne 130$ ;~x~Yup, error- can only define 1 macro ; at a time Mov R1,R3 ;Save R1 MovB (R1)+,R0 ;Save the buffer name Beq InvMcN ;~x~End of line - error TstB @R1 ;Is it a single char name (at EOS)? Beq 9$ ;~x~Yes CmpB @R1,# ;Is it a single char name? Beq 9$ ;~x~Yes, ok CmpB @R1,# ;Is it a single char name? Bne InvMcN ;No, invalid name 9$: CmpB R0,DefBuf ;Is it the default buffer? Beq 10$ ;~x~Yup, ok Call IsAlph ;~x~Is it a legal macro name? Bcs InvMcN ;~x~No way baby! 10$: Push R1 ;~x~Save R1-> command line Call FndLBf ;~x~Does it already exist? Bcc 100$ ;~x~Yes, error Call FndBBf ;~x~Find an unused buffer Bcs 90$ ;~x~There aren't any- error Mov R0,@R1 ;Put buffer ID in table Pop R1 ;Restore R1-> command line ; Mov R2,L.Cur ;Make note of which buffer is current ;Note: Don't change current because ;this conflicts with TtyIn routine Mov LrnNxt,L.Buf(R2) ;Save the begin address Mov LrnNxt,L.BEnd(R2) ;Zero length indicates empty Call SpNor ;~x~Ignore spaces on the command line TstB @R1 ;Is this the end of line? Bne 20$ ;~x~No - filespec given Mov R3,R1 ;Yes, restore R1 to use macro id ; as file name 20$: Call Nest ;~x~Nest because we share a buffer with @ Bcs 70$ ;~x~Error Mov #Ln$Inp,R4 ;Treat as an auxiliary input file Mov KedDef,AuxDef ;Make .KED the default extension Call $OpFil ;~x~Open file Mov #0,AuxDef ;*C* Back to no default for aux. files Bcs 60$ ;~x~Error Mov LrnNxt,R3 ;Start R3 to insert at the beginning 30$: Call $GetCh ;~x~Get a character from the file Bcs 50$ ;~x~Keep going until error 40$: CmpB R0,# ;~x~Was that the terminator? Beq 50$ ;~x~Yes, we're done MovB R0,@R3 ;No, put it in the learn buffer Inc R3 ;Move along Cmp R3,TtBufE ;Make sure there's still room Bhis 80$ ;~x~There isn't, error ;>>>RT specific? CmpB R0,# ;Was that a carriage return? Bne 30$ ;~x~Nope, get the next one Call $GetCh ;~x~Yup, try to eat the trailing Bcs 50$ ;~x~Keep going until error CmpB R0,# ;~x~Was it a linefeed? Bne 40$ ;~x~Nope, a real character, report it Br 30$ ;~x~Yup, drop it and carry on ........... ;-*JMP* 50$: Mov R3,L.BEnd(R2) ;~x~Save the end of buffer address Mov R3,LrnNxt ;Save pointer to the next available ; byte in the composite learn buffer Call $ClsFl ;~x~Close the output file Call UnNest ;~x~Unnest input modes Clc ;All's well Return ;~x~Done ...... 60$: Call $ClsFl ;~x~Close the output file Call UnNest ;~x~Unnest input modes 70$: Sec ;~x~Set carry Return ;~x~ ...... 80$: Call UnNest ;~x~Unnest input modes ;+ ;HELPER HELPER ;~x~ ;Too many bytes were entered;the capacity of the composite learn buffer was ;exceeded. ;- 90$: Tst (SP)+ ;~x~Fix stack from saving R1 ;+ ;HELPER HELPER ;~x~ ;There are no learn buffers left to use. User must clear one and reuse it. ;- 100$: Tst (SP)+ ;~x~Fix stack from saving R1 ;+ ;HELPER HELPER ;~x~ ;There is an active learn buffer with this identifier. Choose another ;identifier or Clear this buffer to reuse it. ;- 130$: ;~x~ ;+ ;HELPER HELPER ;~x~ ;User is attempting to define 2 macros at the same time. This is invalid. ;- .Dsabl LSB .SbTtl FNDLBF - Find Learn Buffer ;+ ;FNDLBF ; ;FUNCTIONAL DESCRIPTION: ; ; Find a specified learn buffer descriptor ; ;INPUT: R0 = Learn Buffer ID (FndLBf) or ; = 0 = unused buffer ;OUTPUT: ; R1 => correct entry in id table ; R2 => correct entry in buffer descriptor table ; All others preserved. ; Carry Clear if found learn buffer. ; Carry Set if not found. ;- .Enable LSB FndLBf:: ;~x~ Push R3 Mov LBfTab,R2 ;Get top of Buffer descriptor table 10$: Cmp TtBfr,R2 ;~x~Was that the last? ;NOTE: this depends on the buffer being allocated exactly after the directory Beq 30$ ;~x~Yes, not found CmpB @R2,R0 ;Is this the right identifier? Beq 20$ ;~x~Yes, this is the macro we want Add #6,R2 ;Move up the descriptor table Br 10$ ;~x~And try again .......... 20$: Mov R2,R1 ;~x~R1 => buffer id ;R2 => buffer description TstB R0 ;Is this supposed to be an empty buf? Beq 40$ ;~x~*C* Yes, don't test Cmp L.BEnd(R2),L.Buf(R2) ;Is it empty? Bgt 40$ ;~x~*C* No, this is a good one (c clear) Clr @R2 ;Yes, then call it unused and ; say we didn't find it 30$: Sec ;~x~ 40$: Pop R3 ;~x~*C* Return ;~x~ ...... .Dsabl LSB ;+ ; FndBBf - Find Unused Learn Buffer ;- .Enable LSB FndBBf:: ;~x~ Push R0 Clr R0 Call FndLBf ;~x~ Pop R0 Return ;~x~ ...... .Dsabl LSB .SbTtl C.CLR - Clear a specified learn buffer ;+ ;C.CLR ; ;FUNCTIONAL DESCRIPTION: ; ; Clear a specified learn buffer and recover the space it's been ; taking up ;- .Enable LSB C.Clr:: ;~x~ NoEChk ;~x~ MovB (R1)+,R0 ;Which buffer to clear? CmpB R0,DefBuf ;Is it the default buffer? Beq SpcClr ;~x~Yup, ok Call IsAlph ;~x~Is it an alphabetic character? Bcc SpcClr ;~x~No, error 10$: ;~x~ ;+ ;HELPER HELPER ;~x~ ;Only single alphabetic characters are accepted as learn buffer names ;- SpcClr:: ;~x~ Push R3 ;See if we need to *JMP* Call FndLBf ;~x~Find the learn buffer Bcs 70$ ;~x~It doesn't exist, no error- that's what ; we want Clr @R1 ;Mark it unused Mov L.Buf(R2),R3 ;Mark beginning of buffer Mov L.BEnd(R2),TtSlid ;Slide composite buffer up starting ;at end of this buffer Sub R3,TtSlid ;Calculate amount to slide Beq 70$ ;~x~Buffer was empty, don't bother Mov L.BEnd(R2),R4 ;Start sliding 20$: MovB (R4)+,(R3)+ ;~x~ Cmp R4,LrnNxt ;Make sure we got everything Ble 20$ ;~x~Not yet Mov R3,LrnNxt ;Done, fix pointers. Move LrnNxt pointer up Mov L.Buf(R2),L.BEnd(R2) ;Say the buffer's empty (so we can't ; execute it Clr R3 ;Now loop thru buffer id's Mov LBfTab,R4 ; and fix the address references 30$: Cmp R3,..MacN ;~x~It's important to know your limits Bge 50$ ;~x~ and to work within them TstB L.Id(R4) ;Is this buffer being used? Beq 40$ ;~x~No, (the lazy-no-good-son-of-a-buffer *&$%@ ) Cmp L.Buf(R4),L.Buf(R2) ;Did this buffer slide? Ble 40$ ;~x~No leave it's addresses alone Sub TtSlid,L.Buf(R4) ;Adjust pointer to beginning of buffer Sub TtSlid,L.BEnd(R4) ;Adjust pointer to end of buffer 40$: Add #6,R4 ;~x~Next buffer descriptor please Inc R3 ;Count 'em Br 30$ ;~x~Try the next (if any) .......... 50$: Cmp TtPtr,L.Buf(R2) ;~x~Now adjust current macro executn pointer Ble 60$ ;~x~ if necessary Sub TtSlid,TtPtr ;Fix for the buffer's new position 60$: Cmp LnPtr,L.Buf(R2) ;~x~And adjust current learn pointer Ble 70$ ;~x~ if necessary Sub TtSlid,LnPtr ;Fix for the buffer's new position 70$: Pop R3 ;~x~ Clc ; Ret.1: Return ;~x~ ...... .Dsabl LSB .SbTtl C.WrJo - Write what we have to journal file ;+ ;C.WrJo ; ;FUNCTIONAL DESCRIPTION: ; ;Write everything that has been recorded so far into the file with ;an ending ^Z. After this, if the system crashes before the next command ;is typed, all input will have been recorded in the journal file, and user ;will be able to recover the whole session. ;- .Enabl LSB C.WrJo:: ;~x~ EndChk ;~x~ IsSEr ON Ret.1 ;~x~Are we doing a /RECOVER? Tst JouSsn ;Are we even journaling? Beq NoJou ;~x~No CallR $WrtJo ;~x~Write the journal file as is (with control/Z) .............. .DsAbl LSB .SbTtl C.JoSa,C.NJSa - SET JOURNAL [NO]SAVE ; ;C.JOSA ; ;Suppress deletion of the journal at exit/quit ; ;C.NJSA ; ;Delete the journal at exit/quit unless the user give the "SAVE" argument ; .Enabl LSB C.NJSa:: ;~x~ Clr R3 ;clear flag C.JoSa:: ;~x~Assumes R3<>0 EndChk ;~x~ IsSEr ON 10$ ;~x~Are we doing a /RECOVER? Tst JouSsn ;Are we journaling? Beq NoJou ;~x~No 10$: Mov R3,JoSave ;~x~Say not to delete the Journal Return ;~x~ ...... .Dsabl LSB .SbTtl C.Freq - Set frequency of writes to the journal ; ;C.FREQ ; ;Functional Description: ; ;User specifies that maximum number of writes allowed between modifications ;to the journal ; .Enabl LSB C.Freq:: ;~x~ NoEChk ;~x~No command end check IsSEr ON 10$ ;~x~Are we doing a /RECOVER? Tst JouSsn ;Are we journaling? Beq NoJou ;~x~No 10$: Call KnumQ ;~x~Get the number Bcs 20$ ;~x~Not a number Tst KNumbr ;Is this a valid value? Bmi 20$ ;~x~No Cmp KNumbr,#512. ;Is there a chance that this would ; be within the block limit? Bhis 20$ ;~x~No, there must be a mistake Mov KNumbr,JoFreq ;Save number in next word Clc ;No error Return ;~x~No error ...... 20$: ;~x~ ;+ ;HELPER HELPER ;~x~ ; ;Frequency value must be a positive number, or zero to turn off ;frequency limit ;- .Dsabl LSB NoJou: ;~x~ ;+ ;HELPER HELPER ;~x~ ;User entered a command that requires journaling, but journaling is ;on for this session. ;- .End