.TITLE FCSOPN (FDBADR,LUN%,ACCESS%,FILSPEC$+CHR$(0%),{RECORDSIZE%}) ; .TITLE FCSOPN (FDB(),LUN%,ACCESS%,FILSPEC$+CHR$(0%),BUFFER(),{RECORDSIZE%}) .ENABL LC .MCALL RETURN,OPEN$,.BLK.,.BLKW. .PSECT FCSERR,RW,D,GBL,REL,OVR FCSERR: .BLKW 2 ; error block .PSECT ; argument offsets .BLK. ; FTN standard arg block .BLKW. 1,ARGNUM ; number of arguments .BLKW. 1,FDB ; address of FDB .BLKW. 1,LUN ; .BLKW. 1,ACC ; byte: F.FACC .BLKW. 1,FIL$ ; file specifier string ending with null ; .BLKW. 1,URB ; user record buffer .BLKW. 1,RSZ ; optional record size (bytes) 0=sequential access .PSECT FCSDD.,RW,D,GBL,REL,OVR DD: ; dataset descriptor block DEVL: .BLKW 1 DEVA: .BLKW 1 UICL: .BLKW 1 UICA: .BLKW 1 FXVL: .BLKW 1 FXVA: .BLKW 1 .PSECT FCSOPN:: ; ; find string length MOV FIL$(R5),R4 ; (R4) = [next string byte] MOV R4,R1 ; (R1) = [1st string byte] 11$: TSTB (R4)+ ; BNE 11$ ; scan for 1st null ; (R4) = [null byte] + 1 DEC R4 ; (R4) = [null byte] SUB R1,R4 ; (R4) = # bytes in string (not counting null) ; use R0-R4 to assemble dataset descriptor (6words) ; R0: this char ; R1: [next char] ; R2: [last ']' seen] + 1 ; R3: [last ':' seen] + 1 ; R4: # chars left to scan ; do left -> right scan MOV R1,R3 MOV R1,R2 BEQ 4$ 1$: MOVB (R1)+,R0 CMPB R0,#'] BNE 2$ MOV R1,R2 2$: CMPB R0,#': BNE 3$ MOV R1,R3 MOV R1,R2 3$: SOB R4,1$ 4$: MOV FIL$(R5),R4 ; ; ---:---]--- or ---- or ---:--- or ---]--- or ; ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ; | | | | | | | | | | | | | ; R4 R3 R2 R1 R4 R1 R4 R3 R1 R4 R2 R1 R4 ; R3 R2 R3 R3 ; R2 R2 ; R1 ; MOV #FXVA+2,R0 MOV R2,-(R0) SUB R2,R1 MOV R1,-(R0) MOV R3,-(R0) SUB R3,R2 MOV R2,-(R0) MOV R4,-(R0) SUB R4,R3 MOV R3,-(R0) ; now have set up dataset descriptor (6words) MOV @FDB(R5),R0 ; (R0) = [FDB] ; porno code to set up FDB (saves 6 words) FDxx$R macros are stupid ! F.RTYP==0; MOV #R.FIX,@R0 ; (FDB+F.RTYP) = R.FIX (FBD+F.RATT=0) ; MOV #-1,R1 ; (R1) = -1 ; MOV R1,F.ALOC(R0) ; (FDB+F.ALOC) = -1 ; non-contig ; ; grow by smallest increment ; MOV R1,F.CNTG(R0) ; (FDB+F.CNTG) = -1 ; non-contig ; ; allocate smallest unit if new file ; MOV URB(R5),F.URBD+2(R0) ; user record buffer address copy CMPB @R5,#RSZ/2 ; is there a record size? BLT 21$ ; skip if not MOV @RSZ(R5),F.RSIZ(R0) ; (FDB+F.RSIZ) = given record size BNE 21$ ; record size>0 : random access ; here to fudge sequential access MOVB #FD.INS,F.RACC(R0) ; sequential not random ; PUT$/GET$ not READ$/WRITE$ ; move mode not place mode ; insert not truncate mode MOV #R.VAR+,@R0; sequential access BR 22$ ; have now fudged sequential access 21$: ; here with RSZ handled MOVB #FD.RAN,F.RACC(R0) ; random access mode not sequential ; assumes: PUT$/GET$ not READ$/WRITE$ ; move mode not place mode 22$: ; here when F.RACC set up MOVB @LUN(R5),F.LUN(R0) ; install given logical unit number MOV #DD,F.DSPT(R0) ; in case user didn't preserve this ; use only our dataset descriptor ; of user's given string MOVB @ACC(R5),F.FACC(R0) ; don't check user's access mode ; assume OPEN$ will be OK so zero error fields in error block MOV #FCSERR,R4 ; (R4) = [FCSERR 1st word] CLR (R4)+ ; CLR (R4)+ ; ; (R4) = [FCSERR last word] ; now do something ! OPEN$ ; BCC QUIT ; quit if OK MOVB F.ERR+1(R0),R1 ; (R1) = directive status code MOV R1,-(R4) ; MOVB F.ERR(R0),R1 ; (R1) = error code MOV R1,-(R4) ; QUIT: ; only exit point ; now set record buffer descriptor's length words = to record length MOV F.RSIZ(R0),R1 ; (R1) = logical record size MOV R1,F.URBD(R0) ; in case user does GET$ next MOV R1,F.NRBD(R0) ; in case user does PUT$ next RETURN ; .END