.TITLE MAIL ERROR SUBROUTINES .IDENT /01/ .MCALL GTIM$S,CALLR,CLOSE$,EXIT$S .MCALL FINIT$,GMCR$,GTSK$S,MRKT$ .MCALL OPEN$W,OPEN$A,OPEN$R,OPEN$,DELET$ .MCALL PUT$,GET$,ALUN$,QIO$,QIOW$ .MCALL WTSE$,WTSE$S,DIR$ .MCALL FDBDF$,FDAT$A,FDOP$A,FDRC$A,FDBF$A .MCALL FDBK$A,NMBLK$ .MCALL FSRSZ$ .MCALL READ$,WAIT$ .SBTTL IOERR - I/O ERROR MESSAGE PRINTER ; ; IOERR - PRINTS ERROR MESSAGE FROM FCS FUNCTIONS ; ; ; ; IOERR:: JSR R0,QUTERD ;SAVE REGISTERS AND DSW IOERR0::TSTB F.ERR(R0) ;ERROR IN FDB? BMI 1$ ;YES, PRINT IT JMP TRYDSW ;NO, LOOK IN DSW 1$: PSTR ^*.I/O ERROR .* MOVB F.ERR+1(R0),R2 ;IO OR DIR? BEQ 2$ ;IO PSTR ^*/DR/* ;DIR 2$: MOVB F.ERR(R0),R1 ;GET ERROR IOERR1: PDECB R1,SIGN ;PRINT ERROR NUMBER CALL QUTPC ;AND PC AT TIME OF ERROR PCRLF 4$: PSTR ^*/FILE: /* MOV R0,R2 ADD #N.DVNM+F.FNB,R2 ;COMPUTE ADDR OF DEVICE NAME TTYOUT R2,#2 ;DEVICE NAME POCT N.UNIT+F.FNB(R0) ;AND UNIT NUMBER PSTR /:/ TST N.FNAM+F.FNB(R0) ;IS THERE A FILE NAME BEQ 5$ ;NO, SKIP IT MOV R0,R1 ;COMPUTE ADDRESS OF ADD #N.FNAM+F.FNB,R1 ;FILE NAME PRAD5S R1,#3 ;AND PRINT IT PSTR /./ PRAD50 N.FTYP+F.FNB(R0) PSTR ^*/;/* POCT N.FVER+F.FNB(R0) 5$: PCRLF ;START A NEW LINE JMP DIE ; ; TRYDSW: MOV QUTDSW,R1 ;LOOK IN $DSW FOR ERROR BMI 1$ ;THERE IT IS RETURN 1$: PSTR ^*.I/O ERROR FOUND IN DSW .* MOV #-1,R2 ;FLAG DIR TABLE JMP IOERR1 ;AND DO REST ; ; DIRNAM: .WORD 2$-1$ 1$: .ASCII /DIRERR/ 2$: .EVEN ; IONAM: .WORD 2$-1$ 1$: .ASCII /IOERR/ 2$: .EVEN ; ; .SBTTL QUTCR - NEW LINE ; ; QUTCR - OUTPUT A CARRIAGE RETURN/LINE FEED ; ; ; ; QUTCR:: PSTR ^*<15><12>* ;OUTPUT CARRIAGE RETURN/LINE FEED RETURN ; ; .SBTTL QUTNUM - NUMERIC CONVERSION ROUTINES ; ; QUTDPB - PRINT DECIMAL BYTE ; QUTDPT - PRINT DECIMAL WORD ; QUTOPB - PRINT OCTAL BYTE ; QUTOPT - PRINT OCTAL WORD ; ;CALL: ; MOV N,-(SP) ; CALL QUTDPB OR QUTDPT OR QUTOPB OR QUTOPT ; ..ARGUMENT IS POPPED OFF STACK BY ROUTINE ; ; ; THE FOLLOWING ROUTINE IS CALLED BY ALL ROUTINES ; TO SAVE REGISTERS, SET UP THE TEMPORARY AREA ; ON THE STACK, AND GET THE VALUE TO BE PRINTED INTO ; R5. R3 IS SET TO THE CONTENTS OF THE ; WORD FOLLOWING THE CALL (USED BY CNVT AS RADIX) ; SETUP1: ENTER R1,R2,R3,R4 ;(R5 SAVED BY JSR) MOV (R5)+,R3 ;GET RADIX MOV SP,R1 ;POINT AT TEMPORARY AREA ON STACK MOV R1,R2 ;AND COPY INTO OUTPUT POINTER SUB #6,SP ;AND ADVANCE OVER IT MOV 22(SP),-(SP) ;6+(R1,R2,R3,R4)+(R5)+(PC)+(ARG) RTS R5 ;MANEUVRE ARGUMENT INTO R5 ; ; QUTOPB::CLRB 3(SP) ;CLEAR HIGH BYTE QUTOPT::JSR R5,SETUP1 ;START THINGS UP .WORD 10 ;OCTAL CALL CNVT ;DO CONVERSION PRINT: MOV R2,R4 ;REMEMBER WHERE WE ARE SUB R1,R2 ;COMPUTE LENGTH NEG R2 ;(WE GO THE OTHER WAY) TTYOUT R4,R2 ;DO OUTPUT MOV R1,SP ;RESTORE STACK TO GET RID OF WORK AREA LEAVE ;RESTORE R1 THROUGH R4 MOV (SP)+,R5 ;AND R5 MOV (SP)+,(SP) ;COMPRESS OVER ARGUMENT RETURN ; ; QUTDPB::CLRB 3(SP) ;CLEAR HIGH BYTE QUTDPT::JSR R5,SETUP1 .WORD 12 ;DECIMAL RADIX MOVB #'.,-(R2) ;INDICATE BASE CALL CNVT ;DO CONVERSION BR PRINT ;OUTPUT IT ; ; CNVT: CLR R4 ;SET UP FOR DIVIDE DIV R3,R4 ADD #60,R5 ;CONVERT TO ASCII MOVB R5,-(R2) ;STASH AWAY CHARACTER MOV R4,R5 ;FOR NEXT DIVIDE BEQ 1$ ;IF FINISHED, PRINT IMMEDIATELY CALL CNVT ;GO DO NEXT DIGIT 1$: RETURN ; .SBTTL QUTR5S - PRINT A RADIX 50 STRING ; ; QUTB5S - OUTPUT A MULTIWORD STRING IN RADIX 50 ; QUTR5S - AS ABOVE WITH TRAILING BLANK SUPPRESSION ; ; ; ; ; SETUP2: ENTER R1,R2,R3,R4,R5 MOV SP,R1 ;CREATE TEMPORARY AREA ON STACK MOV 16(SP),R5 ;(R1,R2,R3,R4,R5)+(R0)+(PC)+(LEN) MOV R5,R4 ;COMPUTE LENGTH (MAX)OF OUTPUT STRING ASL R4 ;2*LEN ADD R5,R4 ;3*LEN INC R4 ;ROUND UP TO NEXT WORD BIC #1,R4 ;.. SUB R4,SP ;LEAVE SPACE ON STACK MOV 20(R1),R4 ;(R1,R2,R3,R4,R5)+(R0)+(PC)+(LEN)+(ADDR) MOV R0,-(SP) ;SAVE RETURN ADDRESS MOV R1,R2 ;START OF BUFFER MOV R1,R3 ;FOR NON-BLANK POINTER ; 1$: MOV (R4)+,R0 ;CONVERT ONE WORD CALL QUT5TA ;.. SOB R5,1$ ;AND ON TO NEXT WORD RETURN ; ; QUTB5S::JSR R0,SETUP2 ;DO CONVERSION PRINT1: SUB R1,R2 ;LENGTH OF STRING TTYOUT R1,R2 ;PRINT IT MOV R1,SP ;RESTORE STACK, FLUSHING BUFFER LEAVE ;RESTORE R1 THROUGH R5 MOV (SP)+,R0 ;AND R0 MOV (SP)+,2(SP) ;SQUEEZE ARGS OFF STACK TST (SP)+ ;.. RETURN ; QUTR5S::JSR R0,SETUP2 ;DO CONVERSION MOV R3,R2 ;USE NON BLANK POINTER BR PRINT1 ;AND PRINT STRING ; .SBTTL QUTSTR - OUTPUT A STRING ; ; QUTSTR - OUTPUT STRING FOLLOWING CALLED ; ;CALL: ; JSR R5,QUTSTR ; .WORD LENGTH OF STRING IN BYTES ; .ASCII /STRING/ ; ; ; ; QUTSTR::ENTER R0 MOV (R5)+,R0 ;GET LENGTH OF STRING TTYOUT R5,R0 ;OUTPUT STRING ADD R0,R5 ;UPDATE RETURN ADDRESS OVER STRING INC R5 ;AND ADVANCE TO NEXT FULLWORD BIC #1,R5 ;IF NECESSARY LEAVE RTS R5 ; ; .SBTTL QUTERR - START AN ERROR ROUTINE ; ; QUTERR - SAVE REGISTERS AND CALL ERRPFX ; QUTERD - SAME AS ABOVE, AND ALSO SAVES $DSW IN QUTDSW ; ;CALL: ; JSR R0,QUTERR ; ; ; ; QUTERD::MOV $DSW,QUTDSW QUTERR::ENTER R1,R2,R3,R4,R5 ;SAVE THE REST OF THE REGISTERS ;(R0 SAVED BY CALL) CALL ERRPFX ;AND START OFF ERROR PROCESSING MOV 12(SP),-(SP) ;(R1,R2,R3,R4,R5)+(R0) - RESTORE R0 RTS R0 ;RETURN ; ; .SBTTL QUTPC - OUTPUT PC MESSAGE ; ; QUTPC - OUTPUTS ' AT ', THE CALLED PC, AND A CR/LF ; ;CALL: ; CALL ERROR-ROUTINE ; (PC WHICH WILL BE PRINTED) ; ... ; ERROR ROUTINE: ; ENTER R0,R1,R2,R3,R4,R5 ; ... ; CALL QUTPC ; ; ; QUTPC:: ENTER R0 PSTR ^*/ AT /* MOV 20(SP),R0 ;R0+PC+(R0,R1,R2,R3,R4,R5)+PC POCT R0 ;RETURN PC FOR ERROR ROUTINE PCRLF ;AND OUTPUT CARRIAGE RETURN LEAVE RETURN ; ; .SBTTL QUTR50 - OUTPUT A WORD IN RADIX 50 ; ; QUTB50 - OUTPUT ONE WORD IN RADIX 50 ; QUTR50 - OUTPUT ONE WORD IN RADIX 50 WITH TRAILING BLANKS ELIMINATED ; ;CALL: ; MOV WORD,-(SP) ; CALL QUTR50 OR QUTB50 ; ..ARGUMENT IS POPPED OFF STACK ; ; ; ; ; THE FOLLOWING ROUTINE IS USED TO SAVE REGISTERS ; AND PERFORM THE RADIX 50 CONVERSION. ; RETURN IS MADE WITH R2 AND R3 SET UP AS RETURNED ; BY QUT5TA ; SETUP3: ENTER R1,R2,R3 ;SAVE REGISTERS (R0 SAVED BY CALL) MOV SP,R1 ;CREATE WORKAREA ON STACK SUB #4,SP ;ENOUGH FOR 3 CHARACTERS MOV R0,-(SP) ;SAVE RETURN ADDRESS MOV R1,R2 ;START OF BUFFER MOV R1,R3 ;FOR NON-BLANK POINTER AS WELL MOV 20(SP),R0 ;(PC)+4+(R1,R2,R3)+(R0)+(PC)+(WORD) CALL QUT5TA ;CONVERT TO RADIX 50 RETURN ; ; QUTB50::JSR R0,SETUP3 ;START THINGS GOING PRINT3: SUB R1,R2 ;LENGTH OF CONVERTED STRING TTYOUT R1,R2 ;OUTPUT IT MOV R1,SP ;FLUSH BUFFER FROM STACK LEAVE ;RESTORE REGISTERS MOV (SP)+,R0 ;NOT FORGETTING R0 MOV (SP)+,(SP) ;COMPRESS ARG OUT OF STACK RETURN ; ; QUTR50::JSR R0,SETUP3 ;TRAILING BLANK ELIMINATION MOV R3,R2 ;R3 POINTS AFTER LAST NON-BLANK BR PRINT3 ;AND PRINT IT ; ; .SBTTL QUTSGB - OUTPUT SIGN (BYTE) ; ; QUTSGB - OUTPUT (AND NULLIFY) SIGN OF BYTE ON STACK ; ;CALL: MOVB N,-(SP) ; CALL QUTSGB ; ;OUTPUT: ; TOP OF STACK IS SET TO ABSOLUTE VALUE ; ; QUTSGB::TSTB 2(SP) ;IS IT NEGATIVE? BPL 1$ ;NO, JUST RETURN CALL QUTNEG ;YES, OUTPUT '-' NEGB 2(SP) ;AND SET TO ABSOLUTE VALUE 1$: RETURN ; ; ; .SBTTL QUT5TA - RADIX 50 TO ASCII SUBROUTINE ; ; QUT5TA - SUBROUTINE FOR CONVERTING RADIX 50 TO ASCII ; ;INPUTS: ; R0 WORD TO CONVERT ; R2 POINTER TO OUTPUT STRING ; R3 (SEE OUTPUTS) ; ;OUTPUTS: ; R0 UNCHANGED ; R2 POINTS PAST STRING ; R3 POINTS BEYOND LAST NON-BLANK CHARACTER, IF ANY ; IF ALL BLANK, R3 IS PRESERVED FROM ENTRY ; ; ; QUT5TA::ENTER R0,R4 MOV #3,R4 ;NUMBER OF CHARACTERS IN WORD CALL 1$ ;CONVERT WORD LEAVE RETURN ; 1$: ENTER R1 ;SAVE R1 MOV R0,R1 ;GET NUMBER TO CONVERT CLR R0 ;INTO DOUBLEWORD DIV #50,R0 ;FOR DIVIDE DEC R4 ;FINISHED? BEQ 2$ ;YES CALL 1$ ;NO, RECURSE FOR NEXT CHARACTER 2$: TST R1 ;CONVERT THIS CHARACTER BEQ 5$ ;BLANK MOV R2,R3 ;NOT BLANK, REMEMBER POSITION INC R3 ;POINT BEYOND NON-BLANK CHARACTER CMP #33,R1 ;MIDDLE BGT 4$ ;ALPHA BEQ 3$ ;DOLLAR ADD #22-11,R1 ;DIGIT, . OR / 3$: ADD #11-100,R1 ;DOLLAR 4$: ADD #100-40,R1 ;ALPHA 5$: ADD #40,R1 ;SPACE MOVB R1,(R2)+ ;STORE IT AWAY LEAVE ;RESTORE R1 RETURN ; ; .SBTTL QUTNEG - OUTPUT A DASH ; ; QUTNEG - OUTPUT MINUS SIGN ; ; ; ; QUTNEG::PSTR /-/ RETURN ; ; ; ; ; ; .END