.TITLE PMRLOG - LOG PMR DATA .IDENT /V01.01/ ; ; COPYRIGHT (C) 1980 BY ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ; ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND 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. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ; TRANSFERRED. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ; CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. ; ; ; MODULE DESCRIPTION: ; ; LOG THE DATA PASSED THROUGH PMR INTO A LOG FILE ; ; ; DISTRIBUTED SYSTEMS SOFTWARE ENGINEERING ; ; IDENT HISTORY: ; ; 1.00 11-DEC-80 J. A. SCHRIESHEIM ; ; 1.01 16-DEC-80 ; ADD SUPPORT FOR USING THE PMR TASK AS A TRANSPARENT DATA LOGGER. ; .SBTTL MACRO CALLS AND LOCAL DATA ; ; MACRO LIBRARY CALLS ; .MCALL FCSMC$,GTSK$,GTIM$,DIR$,NETDF$ FCSMC$ ; DEFINE FCS MACROS NETDF$ ; DEFINE NETWORK SYMBOLS ; ; LOCAL DEFINITIONS ; BUFSIZ=132. ; SIZE OF RECORD BUFFER MXLIN=4 ; MAXIMUM AMOUNT OF DATA TO PRINT/16. ; ; LOCAL STORAGE ; .PSECT DATA$I D,RW ; IMPURE DATA ; ; BUFFERS ; BUFF: .BLKB BUFSIZ ; RECORD BUFFER GBUFF: .BLKW 16. ; GET TASK AND TIME BUFFER ; ; FDB ; FDB: FDBDF$ ; ALLOCATE FDB FDOP$A FILUN,,NMBLK ; DEFINE FILE OPEN PARAMETERS NMBLK: NMBLK$ ; SET DEFAULT NAME BLOCK ; ; DATASET DESCRIPTORS ; LOGFIL: .WORD DEVL,DEV,0,0,3,NAM ; DATASET POINTER FOR LOG FILE DATFIL: .WORD DV2L,DV2,UICL,UIC,3,NAM ; DATASET POINTER FOR TARGET TASK ; DESCRIPTOR FILE ; ; NAME OF PARAMETER AND DATA FILES ; .NLIST BEX NAM: .ASCII /PMR / ; FILLED IN WITH LOCAL TASK NAME .EVEN .PSECT DATA$P D,RO ; PURE DATA ; ; MAXIMUM NUMBER OF LINES OF DATA TO WRITE PER MESSAGE ; MAXLIN::.WORD MXLIN ; NUMBER OF LINES ALLOWED PER MESSAGE ; ; LOGGING BLOCK ; PMRLOG:: ; START OF PMR LOGGING BLOCK .WORD LOGINI ; INIT LOGGING .WORD LOGSRC ; LOG SOURCE ROUTINE .WORD LOGDES ; LOG DESTINATION ROUTINE .WORD LOGSTA ; LOG STATUS ROUTINE .WORD LOGDAT ; LOG DATA MESSAGE ROUTINE .WORD LOGINT ; LOG INTERRUPT MESSAGE ROUTINE .WORD LOGDSC ; LOG DISCONNECT ROUTINE .WORD LOGCLS ; CLOSE LOGGING FILE ROUTINE ; ; DPBS ; GTSK: GTSK$ GBUFF ; GET TASK INFO (NAME) GTIM: GTIM$ GBUFF ; GET THE TIME ; ; STRINGS ; .ENABL LC DEV: .ASCII /TR:/ ; LOG FILE = TR:PMR.LOG DEVL=.-DEV ; ... DV2: .ASCII /LB:/ ; TARGET TASK PARAMETER FILE = DV2L=.-DV2 ; ... LB:[1,2]XXXXXX.DAT UIC: .ASCII /[1,2]/ ; ... UICL=.-UIC ; ... FAKNAM::.ASCII <1>/TARGET::"0=TARGET"/ ; DUMMY PMR MESSAGE FOR NAMED OBJECTS NAMSIZ=.-FAKNAM FAKOBJ: .ASCII <1>/TARGET::"200="/ ; DUMMY PMR MESSAGE FOR NUMBERED OBJECTS OBJSIZ=.-FAKOBJ INI1: .ASCIZ /Log from / INI2: .ASCIZ / Source = / DES1: .ASCIZ / Destination = / STA1: .ASCIZ / Connected, path = / STA2: .ASCIZ / Error = / DSC1: .ASCIZ / > Disconnected / DSC2: .ASCIZ / > Aborted by user / DSC3: .ASCIZ / > Aborted by network / DAT1: .ASCIZ / > D(/ DAT2: .ASCIZ /) / DAT3: .ASCIZ /.../ DAT4: .ASCIZ / / INT1: .ASCIZ / > I(/ .EVEN .LIST BEX .SBTTL LOGINI - INITIALIZE PMR LOGGING ;+ ; **-LOGINI-INITIALIZE PMR LOGGING ; ; THIS ROUTINE IS CALLED TO INITIALIZE THE PMR LOGGING. IT DETERMINES IF ; THE TASK IS RUNNING AS A PASSTHROUGH (OBJECT 123.) OR AS A LOGGING TASK. ; IF IT IS A LOGGING TASK, IT ATTEMPTS TO OPEN A FILE NAMED ; "LB:[1,2]XXXXXX.DAT" WHERE XXXXXX IS THIS TASK'S NAME. ; IF SUCCESSFUL, THE FIRST RECORD IS USED AS IF IT WHERE THE RECEIVED ; PMR MESSAGE, IN ORDER TO SPECIFY THE TARGET NODE AND TASK NAME. ; IF THE FILE OR RECORD IS NOT FOUND, THEN A DUMMY PMR RECORD IS CONSTRUCTED. ; ; INPUTS: ; SBUFF = RECEIVED CONNECT INTITIATE ; ; OUTPUTS: ; R0 = ADDRESS OF "FAKE" MESSAGE ; NTSB+2 = LENGTH OF MESSAGE ; $CONB HAS ACCESS CONTROL COPIED FROM CONNECT INITIATE ;- .PSECT CODE$ I,RO ; PURE CODE LOGINI: ; ; DETERMINE IF WE ARE RUNNING AS THE PMR TASK. IF NOT, FORMAT A ; DUMMY PASSTHROUGH MESSAGE. ; DIR$ #GTSK ; GET THE TASK NAME TSTB SBUFF+N.DFM ; CONNECTED TO BY DESCRIPTOR 0 ? BNE 5$ ; IF NE, NO - BY NAME - NOT PMR CMPB SBUFF+N.DOT,#123. ; ELSE, IS THIS OBJECT 123. ? BEQ 90$ ; IF EQ, YES - USE PASSTHROUGH PROTOCOL 5$: CLRB PMRFLG ; ELSE, INDICATE PMR PROTOCOL NOT RUNNING ; ; FORMAT THE LOG AND DATA FILENAME STRING FROM OUR TASKNAME, SQUEEZING OUT ; "." AND "$". ; MOV #NAM,R0 ; POINT TO BUFFER FOR THE TARGET NAME MOV R0,R4 ; SAVE A COPY MOV GBUFF+G.TSTN,R1 ; ... FIRST WORD CALL $C5TA ; FORMAT IT MOV GBUFF+G.TSTN+2,R1 ; ... SECOND WORD CALL $C5TA ; FORMAT IT MOV R4,R0 ; COPY BUFFER POINTER 10$: CMPB (R4),#'. ; SQUEEZE OUT "." BEQ 20$ ; ... CMPB (R4),#'$ ; AND "$" BEQ 20$ ; ... MOVB (R4),(R0)+ ; ... 20$: INC R4 ; ... CMPB (R4),#' ; AT END OF NAME ? BNE 10$ ; IF NE, NO - KEEP SQUEEZING 25$: SUB #NAM,R0 ; CALC LENGTH MOV R0,DATFIL+8. ; SET LENGTH IN DATASET POINTER. MOV R0,LOGFIL+8. ; ... ; ; TRY TO OPEN FILE LB:[1,2]XXXXXX.DAT, WHERE XXXXXX = THE TASK NAME. ; GET THE FIRST RECORD AND USE IT AS A FAKE PMR MESSAGE. ; CLR NTSB+2 ; INDICATE NO RECORD YET MOV #^RDAT,NMBLK+N.FTYP ; SET TYPE TO ".DAT" FDOP$R #FDB,,#DATFIL ; SET FILE OPEN PARAMETERS FDRC$R ,,#BUFF1+1,#BUFSIZ ; SET RECORD ACCESS PARAMETERS OPEN$R ; TRY TO OPEN THE FILE BCS 40$ ; IF CS, ERROR GET$ ; GET A RECORD BCS 30$ ; IF CS, CLOSE FILE MOV F.NRBD(R0),NTSB+2 ; SET THE RECORD LENGTH INC NTSB+2 ; COUNT DUMMY HOP COUNT 30$: CLOSE$ ; CLOSE THE FILE MOV #BUFF1,R0 ; POINT TO RECORD BUFFER TST NTSB+2 ; ANY RECORD FOUND ? BNE 70$ ; IF NE, YES ; ; SET UP A STRING OF TARGET::"0=TARGET" or TARGET::"200=" IF ; FILE COULDN'T BE OPENED. ; 40$: MOV #FAKNAM,R0 ; POINT TO FAKE MESSAGE MOV #NAMSIZ,NTSB+2 ; SET SIZE TSTB SBUFF+N.DFM ; CONNECTED TO BY DESCRIPTOR 0 ? BNE 50$ ; IF NE, NO - USE NAME MOV #FAKOBJ,R0 ; ... SET OBJECT TYPE TO "200" MOV #OBJSIZ,NTSB+2 ; ... AND STRING SIZE 50$: MOV R0,R1 ; COPY PMR MESSAGE POINTER 60$: TSTB (R1)+ ; LOOK FOR END BNE 60$ ; ... DEC R1 ; CALC LENGTH SUB R0,R1 ; ... MOV R1,NTSB+2 ; ... SET FAKE SIZE 70$: TSTB VERSTA ; WAS VERIFICATION PERFORMED ? BNE 90$ ; IF NE, YES - ACCESS INFO IS NOT VALID MOV #SBUFF+N.CIDC,R1 ; POINT TO RECEIVED ACCESS INFO MOV #$CONB+N.RIDC,R2 ; ... AND CONNECT REQUEST FIELDS 80$: MOV (R1)+,(R2)+ ; COPY THE ACCESS CONTROL CMP R1,#SBUFF+N.CDAC ; PAST END OF ACCESS FIELDS ? BLO 80$ ; IF LO, NO 90$: RETURN .SBTTL LOGSRC - OPEN LOG FILE, WRITE SOURCE DESCRIPTOR .SBTTL LOGCLS - DISABLE PMR LOGGING ;+ ; **-LOGSRC-OPEN LOG FILE, WRITE SOURCE DESCRIPTOR ; ; THIS ROUTINE TESTS IF LOGGING IS ENABLED (TR: IS DEFINED), OPENS THE ; LOG FILE, AND INSERTS THE LOCAL NODE INFO, AND THE SOURCE DESCRIPTOR ; INTO THE FILE. ; ; INPUTS: ; LOCNAM = FORMATTED ASCIZ LOCAL NODE NAME ; SBUFF = INCOMING CONNECT BLOCK ; GBUFF = GTSK$ RETURNED PARAMETERS ; ; OUTPUTS: ; FILE OPENED, AND LOCAL DATA RECORD WRITTEN, ELSE ; LOGGING IS DISABLED ; ; REGISTERS: ; ALL REGISTERS ARE PRESERVED ;- .ENABL LSB LOGSRC: CALL $SAVAL ; SAVE ALL REGISTERS MOV #^RLOG,NMBLK+N.FTYP ; SET TYPE TO ".LOG" FDOP$R #FDB,,#LOGFIL ; SET FILE OPEN PARAMETERS FDAT$R ,#R.VAR,#FD.CR ; SET FILE ATTRIBUTES FDRC$R ,,#BUFF,#BUFSIZ ; SET RECORD ACCESS PARAMETERS OPEN$W ; TRY TO OPEN THE FILE BCS LOGCLS ; IF CS, COULDN'T - NEVER MIND ; ; FORMAT THE "LOG FROM NODE::TASK:: DD-MMM-YY HH:MM:SS" LINE ; MOV #BUFF,R0 ; POINT TO BUFFER MOV #INI1,R1 ; ... AND FIRST STRING CALL MOVEZ ; MOVE THE STRING IN MOV #LOCNAM,R1 ; ... AND THE LOCAL NAME CALL MOVEZ ; ... MOV GBUFF+G.TSTN,R1 ; ... FIRST WORD CALL $C5TA ; FORMAT IT MOV GBUFF+G.TSTN+2,R1 ; ... SECOND WORD CALL $C5TA ; FORMAT IT MOVB #' ,(R0)+ ; INSERT A TAB DIR$ #GTIM ; GET THE TIME MOV #GBUFF,R1 ; POINT TO TIME CALL $DAT ; FORMAT THE DATE MOVB #' ,(R0)+ ; INSERT SOME SPACES MOVB #' ,(R0)+ ; ... MOV #3,R2 ; SET FORMAT TO HH:MM:SS CALL $TIM ; FORMAT THE TIME CALL PUTREC ; PUT THE RECORD OUT BCS LOGCLS ; IF CS, DISABLE LOGGING ; ; FORMAT THE " SOURCE = NODE::TASK " LINE ; MOV #BUFF,R0 ; POINT TO THE BUFFER MOV #INI2,R1 ; AND THE SECOND STRING CALL MOVEZ ; MOVE THE ASCIZ STRING MOV #SBUFF+N.SND,R1 ; POINT TO SOURCE NODE NAME MOV #6,R2 ; ASSUME 6 CHAR NAME CALL MOVEC ; MOVE A COUNTED STRING 10$: CMPB -(R0),#' ; TRAILING SPACE ? BEQ 10$ ; IF EQ, YES - LOOK AT PREVIOUS TSTB (R0)+ ; BUMP PAST LAST CHAR OF NAME MOVB #':,(R0)+ ; PUT IN NODE NAME DELIMITER MOVB #':,(R0)+ ; ... MOV #SBUFF+N.SDE,R1 ; POINT TO SOURCE TASK NAME MOV SBUFF+N.SDEC,R2 ; GET LENGTH OF NAME CALL MOVEC ; MOVE IN THE COUNTED FIELD CALL PUTREC ; PUT THE RECORD BCC 100$ ; IF CC, JUST RETURN LOGCLS: CLOSE$ #FDB ; CLOSE LOGGING FILE CLR LOGBLK ; INDICATE LOGGING NOT ACTIVE 100$: RETURN .DSABL LSB .SBTTL LOGDES - LOG DESTINATION STRING ;+ ; **-LOGDES-LOG DESTINATION STRING ; ; THIS ROUTINE WRITES THE DESTINATION STRING RECORD IN THE LOG FILE ; ; INPUTS: ; BUFF3 = RECEIVED PMR MESSAGE (ASCIZ) ; ; OUTPUTS: ; DESTINATION DATA RECORD WRITTEN, IF FAILURE ; LOGGING IS DISABLED ; ; REGISTERS: ; ALL REGISTERS ARE PRESERVED ;- LOGDES: CALL $SAVAL ; SAVE ALL REGISTERS MOV #BUFF,R0 ; POINT TO BUFFER MOV #DES1,R1 ; POINT TO MESSAGE PREFIX CALL MOVEZ ; MOVE THE STRING MOV #BUFF3+1,R1 ; POINT PAST HOP COUNT CALL MOVEZ ; MOVE THE STRING CALL PUTREC ; PUT THE RECORD BCS LOGCLS ; IF CS, DISABLE LOGGING RETURN .SBTTL LOGSTA - LOG CONNECT STATUS ;+ ; **-LOGSTA-LOG CONNECT STATUS ; ; THIS ROUTINE WRITES THE STATUS STRING RECORD IN THE LOG FILE ; ; INPUTS: ; BUFF1 = PMR RETURN STATUS MESSAGE ; ; OUTPUTS: ; CONNECT STATUS DATA RECORD WRITTEN, IF FAILURE ; LOGGING IS DISABLED ; ; REGISTERS: ; ALL REGISTERS ARE PRESERVED ;- LOGSTA: CALL $SAVAL ; SAVE ALL REGISTERS MOV #BUFF,R0 ; POINT TO BUFFER MOV #STA1,R1 ; ASSUME CONNECTED MOV #BUFF1,R2 ; POINT TO PMR RETURN MESSAGE CMPB (R2)+,#1 ; IS AN ACK BEING SENT ? BEQ 10$ ; IF EQ, YES MOV #STA2,R1 ; ELSE, ERROR 10$: CALL MOVEZ ; MOVE THE STRING MOV R2,R1 ; POINT TO BUFFER CALL MOVEZ ; MOVE THE STRING CALL PUTREC ; PUT THE RECORD BCS LOGCLS ; IF CS, DISABLE LOGGING RETURN .SBTTL LOGDSC - LOG DISCONNECT ;+ ; **-LOGDSC-LOG DISCONNECT ; ; THIS ROUTINE WRITES THE DISCONNECT STRING RECORD IN THE LOG FILE ; ; INPUTS: ; NTSB = STATUS BLOCK FROM GND ; ; OUTPUTS: ; DISCONNECT STATUS DATA RECORD WRITTEN, IF FAILURE ; LOGGING IS DISABLED ; ; REGISTERS: ; ALL REGISTERS ARE PRESERVED ;- LOGDSC: CALL $SAVAL ; SAVE ALL REGISTERS MOV #BUFF,R0 ; POINT TO BUFFER MOV #DSC1,R1 ; ASSUME SYNCH DISCONNECT CMPB NTSB+1,#NT.DSC ; DISCONNECT ? BEQ 10$ ; IF EQ, YES MOV #DSC2,R1 ; ELSE ASSUME USER ABORT CMPB NTSB+1,#NT.ABT ; USER ABORT ? BEQ 10$ ; IF EQ, YES MOV #DSC3,R1 ; ELSE ABORTED BY NETWORK 10$: CALL MOVEZ ; MOVE THE STRING DIR$ #GTIM ; GET THE TIME MOV #GBUFF+G.TIHR,R1 ; POINT TO HOUR MOV #3,R2 ; FORMAT "HH:MM:SS" CALL $TIM ; ... CMPB NTSB+3,#INLUN ; DISCONNECT FROM INPUT SIDE ? BEQ 20$ ; IF EQ, YES MOVB #'<,BUFF+1 ; ELSE, INDICATE OUTPUT ABORT 20$: CALL PUTREC ; PUT THE RECORD BCS LOGCLS ; IF CS, DISABLE LOGGING RETURN .SBTTL LOGDAT - LOG DATA MESSAGE .SBTTL LOGDAT - LOG INTERRUPT MESSAGE ;+ ; **-LOGDAT-LOG DATA MESSAGE ; **-LOGINT-LOG INTERRUPT MESSAGE ; ; THESE ROUTINES WRITE DATA AND INTERRUPT MESSAGES INTO THE LOG FILE ; ; INPUTS: ; SND = DPB FOR SEND DATA WITH BUFFER DESCRIPTOR FILLED IN (LOGDAT) ; XMI = DPB FOR XMI INTERRUPT WITH BUFFER DESCRIPTOR FILLE IN (LOGINT) ; ; OUTPUTS: ; RECORDS WRITTEN, IF FAILURE ; LOGGING IS DISABLED ; ; REGISTERS: ; ALL REGISTERS ARE PRESERVED ;- .ENABL LSB LOGDAT: CALL $SAVAL ; SAVE ALL REGISTERS MOV #DAT1,R1 ; SET FORMAT STRING MOV #SND,R4 ; POINT TO SND DPB BR 5$ ; ... ON TO COMMON CODE LOGINT: CALL $SAVAL ; SAVE ALL REGISTERS MOV #INT1,R1 ; SET FORMAT STRING MOV #XMI,R4 ; POINT TO XMI DPB 5$: MOV #BUFF,R0 ; POINT TO BUFFER CALL MOVEZ ; MOVE THE STRING CMPB Q.IOLU(R4),#OULUN ; RECEIVED OVER INPUT LUN ? BEQ 10$ ; IF EQ, YES MOVB #'<,BUFF+1 ; ELSE, INDICATE RECEIVED FROM OUT SIDE 10$: MOV Q.IOPL+2(R4),R5 ; GET THE LENGTH OF THE DATA MOV R5,R1 ; ... CLR R2 ; ZERO SUPPRESS CONVERSION CALL $CBDMG ; CONVERT TO DECIMAL MAGNITUDE MOV #DAT2,R1 ; PUT IN TRAILING ")" CALL MOVEZ ; ... MOV #BUFF+11.,R0 ; PUT DATA STARTING IN COL #12. MOV Q.IOPL(R4),R3 ; GET BUFFER ADDRESS MOV R5,R4 ; COPY BYTE COUNT ADD #15.,R5 ; ROUND UP TO NEXT NUMBER OF LINES ASR R5 ; CALC NUMBER OF LINES ASR R5 ; ... (16 BYTES PER LINE) ASR R5 ; ... ASR R5 ; ... CMP R5,MAXLIN ; TOO MANY LINES ? BLE 20$ ; IF LE, NO - PRINT IT ALL MOV MAXLIN,R5 ; ELSE, PRINT ONLY MAXLIN 20$: MOV #16.,R2 ; ASSUME 16. BYTES ON THIS LINE CMP R4,R2 ; 16. LEFT ? BGE 30$ ; IF GE, YES MOV R4,R2 ; ELSE, SET NUMBER TO CONVERT 30$: SUB R2,R4 ; CALC REMAINING COUNT 40$: CALL CVTBA ; CONVERT TO ASCII DEC R2 ; LOOP FOR LINE BNE 40$ ; ... CMP R5,#1 ; LAST LINE ? BNE 50$ ; IF NE, NO TST R4 ; OVERRUN ? BEQ 50$ ; IF EQ, NO MOV #DAT3,R1 ; ELSE , PUT IN TRAILING "..." CALL MOVEZ ; ... 50$: CALL PUTREC ; PUT THE RECORD BCC 60$ ; IF CC, OK JMP LOGCLS ; IF CS, DISABLE LOGGING 60$: MOV #BUFF,R0 ; POINT TO BUFFER MOV #DAT4,R1 ; PLANT LEADING SPACES CALL MOVEZ ; ... DEC R5 ; DO FOR NEXT LINE BNE 20$ ; ... IF MORE LEFT RETURN .DSABL LSB .SBTTL MOVEZ - MOVE AN ASCIZ STRING .SBTTL MOVEC - MOVE A COUNTED STRING ;+ ; **-MOVEZ-MOVE AN ASCIZ STRING ; **-MOVEC-MOVE A COUNTED STRING ; ; THESE ROUTINES MOVE STRINGS BETWEEN BUFFERS ; ; INPUTS: ; R0 = TARGET BUFFER ADDRESS ; R1 = SOURCE BUFFER ADDRESS ; R2 = STRING COUNT (MOVEC ONLY) ; ; OUTPUTS: ; R0 = ADDRESS OF NEXT FREE BYTE IN TARGET BUFFER ; ; REGISTERS: ; R0, R1, R2 ARE MODIFIED ;- MOVEZ: 10$: MOVB (R1)+,(R0)+ ; MOVE THE STRING BNE 10$ ; ... UNTIL NULL DEC R0 ; BUT DON'T COUNT THE NULL RETURN MOVEC: 10$: MOVB (R1)+,(R0)+ ; MOVE THE STRING DEC R2 ; ... BNE 10$ ; FOR ALL CHARACTERS RETURN .SBTTL PUTREC - PUT A RECORD INTO THE FILE ;+ ; **-PUTREC-PUT A RECORD INTO THE FILE ; ; THIS ROUTINE IS CALLED TO PUT A RECORD ; ; INPUTS: ; BUFF = BUFFER WITH RECORD IN IT ; R0 = ADDRESS OF NEXT FREE BYTE IN BUFFER ; ; OUTPUTS: ; RECORD PUT ; ; REGISTERS: ; R0, R1 ARE MODIFIED ;- PUTREC: MOV R0,R1 ; COPY BUFFER ADDRESS SUB #BUFF,R1 ; CALC STRING LENGTH PUT$ #FDB,#BUFF,R1 ; PUT THE RECORD RETURN .SBTTL CVTBA - CONVERT BYTE TO ASCII ;+ ; **-CVTBA-CONVERT A BYTE TO ASCII ; ; THIS ROUTINE CONVERTS A BYTE TO THREE OCTAL ASCII, WITH A TRAILING ; SPACE. ; ; INTPUTS: ; R0 = ADDRESS OF NEXT FREE BYTE IN BUFFER ; R3 = ADDRESS OF NEXT BYTE TO BE CONVERTED ; ; OUTPUTS: ; R0 = ADDRESS OF NEXT FREE BYTE IN BUFFER ; R3 = ADDRESS OF NEXT BYTE TO BE CONVERTED ; ; REGISTERS: ; R1 IS MODIFIED. ;- CVTBA: MOVB (R3)+,R1 ; GET BYTE TO CONVERT CLRB (R0) ; INIT ASCII BYTE CALL 20$ ; CONVERT FIRST 2 BITS CALL 10$ ; ... NEXT 3 BITS CALL 10$ ; ... LAST 3 BITS MOVB #' ,(R0)+ ; PLANT TRAILING SPACE RETURN 10$: CLRB (R0) ; INIT BYTE ROLB R1 ; ROTATE BITS INTO C ROLB (R0) ; ... AND INTO ASCII BYTE 20$: ROLB R1 ; ... ROLB (R0) ; ... ROLB R1 ; ... ROLB (R0) ; ... BISB #'0,(R0)+ ; ADD IN ASCII 0 BIAS RETURN .END