.TITLE BOILER .IDENT /01/ ;For History Comments .ENABLE LC ; ; This is a Boilerplate for writing special software of one ; kind or another. The Module Header Comment should go here. ; ; Supplied by:- ; ; Phil Stephensen-Payne, ; c/o Systime Ltd., ; Concourse Computer Centre, ; 432 Dewsbury Road, ; LEEDS LS11 7DF, ; England. ; ; ; History: ; 01 P.A. Stephensen-Payne 11-Jun-80 ; .PAGE .SBTTL Macros .MACRO FERR,X,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14 .IIF NB , MOV P1,ARGBLK ;Arguments for insertion .IIF NB , MOV P2,ARGBLK+2 .IIF NB , MOV P3,ARGBLK+4 .IIF NB , MOV P4,ARGBLK+6 .IIF NB , MOV P5,ARGBLK+8. .IIF NB , MOV P6,ARGBLK+10. .IIF NB , MOV P7,ARGBLK+12. .IIF NB , MOV P8,ARGBLK+14. .IIF NB , MOV P9,ARGBLK+16. .IIF NB , MOV P10,ARGBLK+18. .IIF NB , MOV P11,ARGBLK+20. .IIF NB , MOV P12,ARGBLK+22. .IIF NB , MOV P13,ARGBLK+24. .IIF NB , MOV P14,ARGBLK+26. MOV #I.'X,R1 ;Address of Error String JMP FERR .ENDM .MACRO DIAG,X,P1,P2,P3,P4 .IIF NB , MOV P1,ARGBLK .IIF NB , MOV P2,ARGBLK+2 .IIF NB , MOV P3,ARGBLK+4 .IIF NB , MOV P4,ARGBLK+6 MOV #I.'X,R1 CALL DIAG .ENDM ; .MCALL CSI$,CSI$1,CSI$2,CSI$SW,CSI$SV,CSI$ND ; for CSI .MCALL GCMLB$,GCMLD$,GCML$,SPWN$,DIR$ ; for GCML .MCALL FSRSZ$,FINIT$,FDBDF$,FDOP$A,FDAT$A ; for FILES-11 .MCALL FDRC$A,FDBK$A,FDBF$A,NMBLK$ ; .MCALL OPEN$,CLOSE$,GET$,PUT$,READ$,WRITE$,WAIT$ ; .MCALL QIOW$S,EXIT$S,ALUN$S,WTSE$S,SVTK$S ;general use .PAGE .SBTTL Offset Definitions ; ; If you are going to use symbolic offsets of your own, ; define them here ; ; It is often a good idea to use symbolic names for your luns ; CMDLUN=1 INPLUN=2 OUTLUN=3 ERRLUN=5 .PAGE .SBTTL Data - Error Messages .NLIST BEX ; ; This section should contain the error messages in a format suitable ; for $EDMSG. In particular they should be terminated by a zero byte. ; Key directives for $EDMSG are:- ; %D - Signed Decimal Word ; %M - Unsigned Decimal Word (Zeroes Suppressed) ; %N - CR/LF ; %O - Signed Octal Word ; %P - Unsigned Octal Word ; %R - Three RAD50 characters ; %U - Unsigned Decimal Word (No Zero Suppression) ; OUTBLK: .BLKB 80. ; To build error message in ARGBLK: .BLKW 15. ; Argument block for $EDMSG I.SST: .ASCII /XXX - SST Trap = %D at PC %P/<7><7> .ASCII /%N R0=%P, R1=%P, R2=%P, R3=%P/ .ASCIZ /%N R4=%P, R5=%P, R6=%P, (SP)=%P/ I.NSYM: .ASCIZ /XXX - Symbol %R%R not in RSX11M.STB/<7> I.GIND: .ASCIZ /XXX - Invalid Indirect Command File/<7> I.GCME: .ASCIZ /XXX - Command Read Error = %D/<7> I.CSI1: .ASCIZ /XXX - Command Line Parse Failure at Offset %D/<7> I.CS2O: .ASCIZ /XXX - Invalid Syntax in Output Filespec/<7> I.CS2I: .ASCIZ /XXX - Invalid Syntax in Input Filespec/<7> I.OPNO: .ASCIZ /XXX - Open Error = %D on Output File/<7> I.OPNI: .ASCIZ /XXX - Open Error = %D on Input File/<7> I.MORO: .ASCIZ /XXX - Too Many Output Files Specified/<7> I.MORI: .ASCIZ /XXX - Too Many Input Files Specified/<7> .EVEN .PAGE .SBTTL Data - CSI & GCML Tables ; ; First we define the system buffers for CSI and GCML ; ; ; The GCMLB$ macro must be modified for user requirements. The ; format is:- ; GCMLB$ command-file depth,prompt,lun GCMBLK: GCMLB$ 1,XXX,,CMDLUN CSI$ CSIBLK: .BLKB C.SIZE ; CSI control block .EVEN ; ; First we must define the CSI Switch and data tables, as follows:- ; ; 1. Define any symbolic mask names, ; LISW = 1 ; 2. Define the switch tables themselves. Each entry is of the form:- ; ; CSI$SW sw,mask,maskwd,SET/CLEAR,[NEG],valuetab[,LONG/EXACT] ; ; e.g. CSI$SW LI,LISW,SWMSK$,SET,,LTBL ; HESW=1 OSWTAB: ; Output switches CSI$SW HE,HESW,SWMSK$,SET ; Help CSI$ND ISWTAB: ; Input switches CSI$SW HE,HESW,SWMSK$,SET ; Help CSI$ND ; ; 3. Define any switch value tables. Each entry is of the form:- ; ; CSI$SV ASCII/OCTAL/DECIMAL,address,length (ASCII only) ; ; e.g. LTBL: CSI$SV DECIMAL,LINLEN ; CSI$ND ; ; 4. Define any locations for switch values or mask words. ; SWMSK$: .WORD ; Default mask word HLSPWN: SPWN$ MCR...,,,,,1,,,HELCMD,HELCML HELCMD: .ASCII /HELP XXX/ HELCML=.-HELCMD .EVEN ; .PAGE .SBTTL Data - File Definitions ; ; Obviously the user must set up his own file blocks, as this will ; vary per program. The important macros, which cover most eventualities are:- ; ; FSRSZ$ n - n files with record I/O ; (note that GCML needs one) ; FRED: FDBDF$ - define an FDB ; FDAT$A R.FIX/R.VAR,FD.CR/FD.BLK,record length ; type of recordrd ; FDRC$A FD.RAN/FD.RWM,recbuf add,recbuf len ; type of access ; FDBK$A blkbuf add,blkbuf len ; block buffers ; FDOP$A lun,dspt,dfnb,FO.RD/FO.WRT/FO.UPD ; open type ; ; The following code defines an existing input file and a new, variable-length, ; output file. Both will be referenced by record I/O. ; ; FSRSZ$ 3 ; INPFDB: FDBDF$ FDOP$A INPLUN,,INPDFN,FO.RD INPDFN: NMBLK$ ,,0,SY,0 ; OUTFDB: FDBDF$ FDAT$A R.VAR,FD.CR,80. FDOP$A OUTLUN,,OUTDFN,FO.WRT OUTDFN: NMBLK$ ,,0,SY,0 STBFDB: FDBDF$ FDOP$A INPLUN,STBDSD,,FO.RD STBDSD: .WORD DEVL,DEVN .WORD DIRL,DIRN .WORD FILL,FILN DEVN: .ASCII /LB:/ DEVL=.-DEVN DIRN: .ASCII /[1,54]/ DIRL=.-DIRN FILN: .ASCII /RSX11M.STB/ FILL=.-FILN .EVEN ; .PAGE .SBTTL Data - User's Areas .LIST BEX SSTTAB: .WORD SSTOD ; Odd Address Trap .WORD SSTMP ; Memory Protect .WORD SSTBE ; BPT .WORD SSTIO ; IOT .WORD SSTIL ; Reserved Instruction .WORD SSTEM ; Non-RSX EMT .WORD SSTTE ; TRAP .WORD SSTFP ; Floating Point SSTNUM: .WORD 0 ; Store for SST Number ; BUFF: .BLKB 512. ; File buffer ; ; To use the Privileged Task mechanism without having to rebuild each ; SYSGEN incorporate here a table of names in RAD50 of the symbols you ; wish to reference, and call STBRTN at the beginning of your program. ; Then if you have defined, for instance, ACTHD: .RAD50 /$ACTHD/ then ; a statement which would normally say ; MOV #$ACTHD,R0 ; would be replaced by ; MOV ACTHD,R0 ; and so on. SYMTAB: SYMNUM=<.-SYMTAB>/4 .PAGE .SBTTL Mainline Code ; ; This section of code governs the mainline operation of the program. ; START: SVTK$S #SSTTAB,#8. ; Specify SST Table CALL STBRTN ; Call the STB enquiry routine ALUN$S #CMDLUN,#"TI,#0 ; Assign prompt lun to TI: FINIT$ ; Initialise the file section ; GETCMD: CLR SWMSK$ ; Clear Options Mask GCML$ #GCMBLK ; Get Command Line BCC 20$ ; If CC OK - carry on CMPB #GE.EOF,G.ERR(R0) ; Was it an end-of-file? BEQ 10$ ; If EQ yes - terminate program CMPB #GE.OPR,G.ERR(R0) ; Invalid command file? BNE 5$ ; If NE no - carry on DIAG GIND ; yes - log the message BR GETCMD ; and try again ; 5$: MOVB G.ERR(R0),R0 ; Sign-extend the error FERR GCME,R0 ; Else log error ; 10$: EXIT$S ; That's all ; 20$: MOV G.CMLD+2(R0),R1 ; Command start MOV G.CMLD(R0),R2 ; And length BEQ GETCMD ; If not there, Re-Prompt ; ; Now parse the command - this will depend a lot on whether you ; are allowing multiple input and output files, but the following ; might be a useful guideline. ; PARSE: ; CALL CMDFIX ; You might want a routine here to convert ; the input line to something CSI will allow CSI$1 #CSIBLK,R1,R2 ; Check the syntax BCC 10$ ; If CC OK - carry on MOV CSIBLK+C.FILD+2,R0 ; Get Address of Error SUB R1,R0 ; And hence offset INC R0 ; Starting at 1 DIAG CSI1,R0 ; Log the error BR GETCMD ; And get another command line ; 10$: MOV #OUTDFN,R3 ; Get Address of Default Name Block for Output CLR R2 ; Assume no output name specified MOV #"TI,N.DVNM(R3) ; Default output to TI: if not given CLR R4 ; Set Equals Sign flag BIT #CS.EQU*400,(R0) ; Was an "=" specified? BEQ 40$ ; If EQ no - assumptions were correct INC R4 ; Show there was an equals sign MOV #"SY,N.DVNM(R3) ; Name given - therefore change default to SY: CSI$2 #CSIBLK,OUTPUT,#OSWTAB ; Parse real output name BCC 20$ ; If CC OK - carry on DIAG CS2O ; Output error message BR GETCMD ; And get next command line ; 20$: ; ; You might want to check here to see if there was more than one ; output file specified, as follows. ; BITB #CS.MOR,C.STAT(R0) ; See if more output files BEQ 30$ ; If EQ OK - carry on DIAG MORO ; Else log error BR GETCMD ; And get next line ; 30$: MOV #,R2 ; Get DSD address for filename ; 40$: OPEN$ #OUTFDB,,,R2 ; Open the output file BCC 50$ ; If CC OK - carry on MOVB F.ERR(R0),R0 ; Sign-extend error DIAG OPNO,R0 ; Log error BR 90$ ; Get next command ; 50$: MOVB #CS.INP,CSIBLK+C.TYPR ; Default to input file TST R4 ; Was there an equals sign? BNE 55$ ; If NE yes - carry on MOVB #CS.OUT,CSIBLK+C.TYPR ; No - pretend it's an output file ; 55$: CSI$2 #CSIBLK,,#ISWTAB ; Parse the input file BCC 60$ ; If CC OK - carry on DIAG CS2I ; No - Log Error BR 90$ ; and get next line ; 60$: ; ; You might want to check here to see if there was more than one ; input file specified, as follows. ; BITB #CS.MOR,C.STAT(R0) ; See if more input files BEQ 70$ ; If EQ OK - carry on DIAG MORI ; Else log error BR 90$ ; And get next line ; 70$: OPEN$ #INPFDB,,,#CSIBLK+C.DSDS ; Open the input file BCC 80$ ; If CC OK - carry on MOVB F.ERR(R0),R0 ; Sign-extend error code DIAG OPNI,R0 ; Else log an error BR 90$ ; ; 80$: BIT #HESW,SWMSK$ ; Help switch? BEQ 85$ ; If EQ no - process normally DIR$ #HLSPWN ; Yes - ask for help WTSE$S #1 ; Wait for it to finish BR 90$ ; Get next line ; 85$: CALL PROCESS ; Now process the command ; 90$: CLOSE$ #OUTFDB ; Close the files CLOSE$ #INPFDB ; JMP GETCMD ; Get the next line .PAGE .SBTTL Process Routines PROCESS: RETURN .PAGE .SBTTL SST SST Handling Routines ; ; This routine handles any SSTs by logging an error, closing the file ; and exiting. This should make it easy to track down the error. ; SSTFP: INC SSTNUM ; Floating Point SSTTE: INC SSTNUM ; TRAP SSTEM: INC SSTNUM ; Non-RSX EMT SSTIL: INC SSTNUM ; Reserved Instruction SSTIO: INC SSTNUM ; IOT SSTBE: INC SSTNUM ; BPT SSTMP: INC SSTNUM ; Memory Protect SSTOD: ; Odd Address Trap TST SSTNUM ; Have we been here before? BGE 20$ ; If GE no - carry on CMP SSTNUM,#-1000. ; Yes - twice? BLE 10$ ; If LE yes - don't even try to close the file MOV #-2000.,SSTNUM ; Stop second level of recursion CLOSE$ OUTFDB ; No - close the file ; 10$: EXIT$S ; Exit ; 20$: CMP SSTNUM,#1 ; Memory Protect? BNE 30$ ; If NE no - carry on ADD #6,SP ; Yes - chuck three words off the stack ; 30$: CMP SSTNUM,#5 ; TRAP or EMT? (ignore FP as impossible) BLT 40$ ; If LT no - carry on TST (SP)+ ; Yes - chuck a word off the stack ; 40$: MOV (SP)+,ARGBLK+28. ; Save the old PC TST (SP)+ ; Ignore the PS MOV SSTNUM,ARGBLK+26. ; Save the SST number MOV #-100.,SSTNUM ; And stop recursion FERR SST,ARGBLK+26.,ARGBLK+28.,R0,R1,R2,R3,R4,R5,SP,(SP) .PAGE .SBTTL STBRTN Get Values for Exec Symbols ; ; This is a subroutine to determine various Executive addresses, which does ; not have to be rebuilt for each Executive (I hope!) ; ; STBRTN: MOV #SYMTAB,R4 ; Get address of RAD50 symbol table MOV #SYMNUM,R2 ; And the number of them OPEN$ #STBFDB ; Open the input file BCC 10$ ; If CC OK - carry on MOVB F.ERR(R0),R0 ; Sign-extend error code FERR OPNI,R0 ; Else log an error ; 10$: GET$ #STBFDB,#BUFF,#256. BCS 90$ ; If error exit CMP BUFF,#1 ; Right type? BNE 90$ ; If ne no - exit MOV #BUFF+2,R0 ; Look for symbol MOV #15.,R3 ; ; 20$: CMP (R4),(R0) ; This one BNE 30$ ; If ne no - try next CMP 2(R4),2(R0) ; Sure? BNE 30$ ; No - check next one MOV 6(R0),(R4)+ ; Yes - overwrite with address CLR (R4)+ ; and set to next symbol DEC R2 ; Count the one we had BEQ 40$ ; If EQ we've finished - return ; 30$: ADD #8.,R0 ; Set to next one SOB R3,20$ ; Keep trying BR 10$ ; Get next record ; 40$: CLOSE$ #STBFDB ; RETURN ; Return ; 90$: MOV R2,-(SP) ; Save R2 TST (R4) ; A Forced rewind? BEQ 95$ ; If EQ yes - omit error message DIAG NSYM,(R4),2(R4) ; Output error message ; 95$: MOV #INPFDB,R0 ; Rewind the file CLR R1 ; MOV #1,R2 ; CLR R3 ; CALL .POINT ; MOV (SP)+,R2 ; Restore R2 CLR (R4)+ ; Set the word to zero CLR (R4)+ ; DEC R2 ; Count the one we had BEQ 40$ ; If EQ we've finished - return BR 10$ ; Get the next record .PAGE .SBTTL Output Routines ; FERR: CALL DIAG ; Output the Message CLOSE$ #OUTFDB ; Close any files CLOSE$ #INPFDB ; EXIT$S ; Terminate the program ; DIAG: CALL OUT ; Output QIOW$S #IO.WLB,#ERRLUN,#1,,,,<#OUTBLK,R1,#40> ; Output to TI: RETURN ; Return ; OUT: MOV #OUTBLK,R0 ; Get Buffer for Output MOV #ARGBLK,R2 ; Get Address of any Parameters CALL $EDMSG ; Edit the Message RETURN .END START