PROCEDURE ,010001 ;+ ; abstract: IND ; ; This module has support for the include files for ; RUNOFF. ; ; calling sequence: ; ; MOV #new_file_name,R0 ; MOV #new_file_name_length,R1 ; CALL newfil ; open a new file ; ; CALL pshfil ; push current file on stack ; ; CALL popfil ; attempt to pop old file from ; ; stack. If the stack is now ; ; empty, the carry bit is set. ; ; written: 24-JAN-80, -1.0.0-, Bruce C. Wright ; modified: ; verified: 24-JAN-80, -1.0.0-, Bruce C. Wright ; ; Modified: 5-Dec-80, -1.0.1-, John D. Leonard ; Changed to allow RUNOFF to proceed after reporting error ; on INCLUDE file open failure. Also modified error message. ;- .MCALL OFID$R,OPNS$R,CLOSE$,CSI$,CSI$1,CSI$2,FDBF$R .GLOBL PLIST ; In RNOERR ; ; The include file list is a singly-linked list. Its header is ; in FILHD, and the first word of all of the entries points to ; the next entry. There is no limit on the number of entries ; which may be allocated, except for the amount of dynamic storage ; available. An entry represents a saved file, e. g., the current ; file does NOT have an entry in the include list. On an end-of- ; file, the top entry in the list (which is handled as a LIFO ; list), is restored and processing continues as if no end-of-file ; had occurred. The two reserved words in the list (as shown ; below) are not used and are not anticipated to ever be used, but ; are reserved to make the list entry exactly equal to two index ; entries without the text, hopefully reducing the fragmentation ; of the free space. Note that the length of the allocated block ; precedes a block, so that the actual length of an allocated ; index block is 6. words rather than 5. words as used in the ; index subroutines (the sixth word is invisible to the index ; subroutines). The number of words allocated by an include entry ; is 11. in the declared part and 1. (the length word) in the ; system part, so that it is exactly equal to 12. words or two ; index entries. ; FI.LNK = 0 ; link to next file block FI.FID = FI.LNK+2 ; fid of current file FI.DEV = FI.FID+6 ; device name of current file FI.UNI = FI.DEV+2 ; device unit # of current file FI.BLK = FI.UNI+2 ; block # of saved file FI.BYT = FI.BLK+4 ; byte within block FI.LEN = FI.BYT+6 ; *** two words reserved *** CODE IND POPFIL:: MOV R5,-(SP) ; save r5 MOV FILHD,R5 ; get file list head. BNE 10$ ; it's there -- pop files. MOV (SP)+,R5 ; recover R5 SEC ; show were not able to open file. RETURN ; and return to the caller. 10$: CLOSE$ #TTLDMY ; close the current file. BCS FILERR ; error? MOV (R5),FILHD ; indirect to next element in chain. MOV FI.FID(R5),F.FNB+N.FID(R0) ; move in the fid MOV FI.FID+2(R5),F.FNB+N.FID+2(R0) MOV FI.FID+4(R5),F.FNB+N.FID+4(R0) ; ... MOV FI.DEV(R5),F.FNB+N.DVNM(R0) ; move in the device MOV FI.UNI(R5),F.FNB+N.UNIT(R0) ; move in the unit OFID$R R0 ; open the file by file-id BCS FILERR ; error? MOV R1,-(SP) ; save regs for .POINT MOV R2,-(SP) ; MOV R3,-(SP) ; MOV FI.BLK(R5),R1 ; get high order bits of block MOV FI.BLK+2(R5),R2 ; get low order bits of block # MOV FI.BYT(R5),R3 ; get the byte offset. CALL .POINT ; point back into the file. MOV (SP)+,R3 ; Recover registers MOV (SP)+,R2 ; ... BCC 20$ ; J if no errors CMP F.ERR(R0),# ; Is it end-of-file? BNE FILERR ; J if not, some other error. MOV R5,R1 ; Get the area to free. CALL FREE ; Free it. MOV (SP)+,R1 ; Recover R1 MOV (SP)+,R5 ; Recover R5 BR POPFIL ; And try to pop another level. 20$: MOV R5,R1 ; remember the block address. CALL FREE ; free it up. MOV (SP)+,R1 ; recover r1 MOV (SP)+,R5 ; recover R5 CLC ; show no error. RETURN ; and return to the caller. FILERR: MOV R0,-(SP) ; save R0 DIAG INDERR,FCS ; it's an FCS error! JMP RUNOFF ; and re-start. PSHFIL:: MOV R0,-(SP) ; save registers MOV R1,-(SP) ; ... MOV R2,-(SP) ; ... MOV R3,-(SP) ; ... MOV #FI.LEN,R1 ; try to pick a node. CALL ALLOC ; allocate it. MOV R1,-(SP) ; save it MOV #TTLDMY,R0 ; get input fdb CALL .MARK ; mark current position. BCS FILERR ; error? MOV (SP)+,R0 ; remember picked node. MOV R1,FI.BLK(R0) ; remember high order bits of block # MOV R2,FI.BLK+2(R0) ; remember lower order bits MOV R3,FI.BYT(R0) ; remember current byte offset in block MOV TTLDMY+F.FNB+N.FID,FI.FID(R0) ; save fid MOV TTLDMY+F.FNB+N.FID+2,FI.FID+2(R0) ; ... MOV TTLDMY+F.FNB+N.FID+4,FI.FID+4(R0) ; ... MOV TTLDMY+F.FNB+N.DVNM,FI.DEV(R0) ; save device MOV TTLDMY+F.FNB+N.UNIT,FI.UNI(R0) ; and unit MOV FILHD,FI.LNK(R0) ; link into the chain. MOV R0,FILHD ; and remember the current one. CLOSE$ #TTLDMY ; close the file. BCS FILERR ; error? MOV (SP)+,R3 ; recover registers MOV (SP)+,R2 ; ... MOV (SP)+,R1 ; ... MOV (SP)+,R0 ; ... RETURN ; and return to the caller. NEWFIL:: MOV R2,-(SP) ; save R2 MOV R0,-(SP) ; Save R0 MOV R0,R2 ; remember file name pointer. CSI$1 #CSIBLK,R2,R1 ; perform preliminary parse. BCS SYNERR ; syntax error? BITB #CS.EQU,CSIBLK+C.STAT ; is there an = here? BNE SYNERR ; yes, error. CSI$2 R0,OUTPUT ; get a file name. BCS SYNERR ; syntax error? BITB #CS.EQU!CS.WLD!CS.MOR,CSIBLK+C.STAT ; bad things set? BNE SYNERR ; yes, error. .IF DF I$$AS!R$$11D FDBF$R #TTLDMY,,,#2,#FD.RAH ; Say we want multi-buffering .ENDC .IF DF R$$11M!R$$STS FDBF$R #TTLDMY,,,#1 ; Say no multi-buffering .ENDC OPNS$R R0,,#CSIBLK+C.DSDS ; open the file. .IF NDF A$$RAP BCS FILERR ; error? .IFF BCC 100$ ; No error MOV R1,PLIST+2 ; Report error and file name MOV (SP),PLIST+4 ; MOV R0,-(SP) ; Save FDB address for error processing DIAG IFOERR,FCS ; Include file open error TST (SP)+ ; Clear stack CALL POPFIL ; get back to original level 100$: .ENDC MOV (SP)+,R0 ; Recover R0 MOV (SP)+,R2 ; recover R2 RETURN ; and return to the caller. SYNERR: MOV R0,-(SP) ; save FDB address. DIAG MGCDME,FCS ; report syntax error. JMP RUNOFF ; and restart program. DATA INDD FILHD:: .WORD 0 CSI$ CSIBLK: .BLKB C.SIZE .END