.title fopen C library file opener .if df rmsio .ident "RMS046" .library "LB:[1,1]RMSMAC" .iff .ident /000047/ .endc ; ;+ ; ; Index Open or reopen a file ; ; Usage ; ; FILE * ; fopen(name, mode); ; char *name; /* File to open */ ; char *mode; /* Open modes */ ; ; FILE * ; freopen(name, mode, iop); ; char *name; /* File to open */ ; char *mode; /* Open modes */ ; FILE *iop; /* I/O pointer */ ; ; Internal ; ; mov iov,r4 ;r4 -> iov ; jmp $$fopn ;Open the file and return to the ; ;caller via $$fopx or $$fope if error. ; ;On RSX, fixup append mode if the file ; ;wasn't found. ; ; mov iov,r4 ;r4 -> iov ; call $$fopo ;Normal open, then exit via $$fopx ; ;On RSX, $$fopo returns if any error ; ;occurred. On return, r0 := RSX error code. ; ; mov iov,r4 ;r4 -> iov, file is open ; jmp $$fopx ;Normal exit from fopen ; ;On RSX, $$fopx allocates the record ; ;buffer. ; ; mov iov,r4 ;r4 -> iov (or r4 == 0) ; mov code,r0 ;r0 := error code (to go to $$ferr) ; jmp $$fope ;Error exit from fopen ; ;$$fope deallocates buffers ; ; Description ; ; Fopen opens a new or existing file in the indicated mode: ; ; r Read the existing file sequentially ; w Create and write the file sequentially ; a Append to the file ; n Not record oriented ; u RSX-mode "unbuffered i/o" ; RT11-mode: use .ttyin and .ttyout ; ; ; Either "r", "w", or "a" must be given. "n" and "u" are ; optional. "n" should be given for "binary" files. ; Note that "n" mode will create fixed-block records on ; RSX systems. Append mode does not work on native RT11. ; ; Note that "n" and "u" are not compatible with other ; Unix systems. ; ; Implementation Details ; ; On RSX, "u" mode files will be created with the ; "variable-length" attribute. On RSTS/RSX emulation, text ; files (neither "n" nor "u" specified) will be created with ; "stream" attribute. ; ; On RSX, if the record type bits in the record attribute byte ; (F.RATT in the FDB) is zero, the file will be read as if ; the "n" was specified. Note that, if the file contains ; carriage-return line-feed sequences, the entire sequence ; will be passed to the user's program. If record attributes ; are understandable, the carriage-return will be deleted ; from sequences. ; ; On RSX, if the "file" is being opened for write to the same ; device/unit ; as stderr (the user's "command console), the character stream is ; diverted to stderr. This avoids synchronization problems by ; funnelling all output through the same buffer. In ; addition, output to any terminal device is done via QIO's to ; the terminal, IO.WLB for normal mode, IO.WAL for "n" mode. ; ; On RT11, when opening a file for writing, a specific block ; allocation may be included in the Ascii file specification ; following standard RT-11 syntax: "DKn:file.nam[nnn]" where the ; "nnn" specifies the number of blocks to allocate to the file. ; After opening a file successfully, the actual file size (or ; number of blocks allocated) will be found in (FILE *)fd->io_size. ; ; If the RT11 library decides that the file is really the user's ; command terminal, single-character I/O will be performed (by ; calling .ttyin and .ttyout). Note that the "special-mode" ; bits must be set in the Job Status Word by the program if it requires ; true single-character or immediate return input. Output to the ; terminal will be performed without buffering, which is useful ; for screen updating, but otherwise expensive. ; ; Fopen() returns NULL on errors -- $$ferr gets an error code. ; On RT11, this will be a RSTS/E compatible code (described in ; iov), while on RSX, this will be the FCS error code. ; ; On RT11, the file name pointed to by the "io_name" field of ; the iov is either the file name string as passed to fopen() ; or an ascii string reconstructed from the 4-word Rad50 ; device block if the file was opened as part of a fwild/fnext ; sequence. By saving the ascii string, RSTS/E is able to ; re-parse logical device names and PPN's, which are not present ; on native RT11. ; ; On VMS compatibility mode, the device and directory of the ; file name argument are saved in the iov "io_dname" ; field for use by fgetname(). ; ; Note that "no buffer space available" (IE.NBF or E$$NSP) and ; "invalid lun" (IE.ILU or E$$NOC) may be generated by fopen. ; On RT11, if the file cannot be opened because the user's program ; has already opened the channel, an E$$ILU error will be returned. ; ; The same file may not be used for both reading and writing ; except if the program writes a disk file, then repositions ; and reads it using ftell()/fseek(). In this case, the program ; should call rewind() or freopen() to reinitialize the file before ; using fseek(). ; ; Except in the one specific case of the RT11 console terminal ; open in "u" mode, an open file must not be used for reading ; and writing at the same time. ; ; Freopen() substitutes the named file in place of the open ; file -- indicated by iop. The file currently open on ; iop is closed. Freopen returns iop. If the open failed, ; iop will be deallocated. Note that freopen loses any pending ; fwild/fnext status. ; ; ; Internal ; ; The following routines/globals are for use by fopen/fwild. ; If any of these routines detect an error, they return to the ; fopen() caller with an appropriate error code in $$ferr. ; ; $$fope Error exit from fopen ; $$fopn Normal open, hack append ; $$fopx Normal exit from fopen ; ; Warning: fopen() in RSX/RSTS mode uses unpublished information ; to obtain the PPN [UIC] of an open file. This code (in iocsi.mac) ; may require modification for subsequent releases of RSTS/E. ; ; Bugs ; ; Append mode cannot work on native RT11 given the design of the ; RT11 file system. ; ; The RT11 file system does not support files greater than ; 65535 blocks long. ; ; RT11 does not get the actual keyboard name of the console ; terminal, although this isn't too hard to do on RT11/RSTS/E. ; ; Freopen() cannot be used to assign a file to stderr as there ; is code throughout the i/o package for special treatment of ; stderr. For example, it cannot be closed by a user-written ; program. ; ; In RSX modes, the maximum number of files that may be simultaneously ; open is defined at assembly time by a macro (FSRSZ$) which is ; expanded when fopen.mac is assembled. The default FSRSZ$ ; parameter is 4. This may be modified by using the task builder ; /ACTFIL=n option. The default FSRSZ$ value may be specified ; when the RSX library is built by editing assembly parameter ; N$$FIL in RSX.MAC. ; ; Internal ; ; This module contains release-specific code for VMS V3.0 to ; enable Decus C programs to read "Ascii stream" files. ; ;- ; ; Edit history ; 000001 24-Jul-79 MM Initial edit ; 000002 10-Mar-80 MM Conversion for the newer library ; 000003 27-Mar-80 MM Merged libraries ; 000004 23-May-80 MM Added freopen(), changed RT11 stuff ; 000005 10-Jun-80 MM Reorganized for fwild/fnext ; NOTE: because of the reorganization, edit codes ; have been removed from RSX fopen ; 000006 15-Jun-80 MM More reorganization ; 000007 22-Jun-80 MM Reorganized RT11 stuff. NOTE: because of the ; reorganization, edit codes have been removed ; from RT11 fopen. ; 000008 02-Jul-80 MM Fixed dumb bug in $$flun ; 000009 06-Jul-80 MM Added Stream under RSTS/E ; 000010 09-Jul-80 MM Do a handler .fetch on RT11 ; 000011 10-Jul-80 MM Fixed typo in .dstatus call ; 000012 18-Jul-80 MM Fixed up RT11 error status values ; 000013 01-Aug-80 MM Track IOV changes ; 000014 17-Aug-80 RBD Slight mods for RT11 fwild(). Changed stashed file ; spec to the 4 word RAD50 CSI output 'dblk'. This ; is consistent with fwild(), which does the same. ; 000015 22-Aug-80 MM Reverted to storing an ascii file name for RT11. ; This is needed to preserve logical device translation ; for RSTS. There is some unfortunate hackery for ; wild card files, as the 4-word device block must ; be decompiled to ascii. No simple solutions. ; 000016 04-Sep-80 MM Squeeze blanks from RT11 filenames ; 000017 16-Sep-80 MM Get RSX Directory UIC ; 000018 18-Sep-80 MM Bug in .parse call, fixed .psect names, added N$$FIL ; 000019 22-Sep-80 RBD Minor changes (improvements) to uic handling. ; 000020 23-Sep-80 MM Fix to RT11 file scan, removed VF$BAD ; 000021 20-Oct-80 MM Bit by Standard Runoff on VMS -- missing attributes ; 000022 24-Oct-80 MM Bit again. Missing attributes on VMS differnt ; 000023 10-Dec-80 MM Changed vms test -- no functional changes ; 000024 24-Dec-80 MM Use blank-squeezed RT11 filename (change 000016) ; 000025 06-Jan-81 JSL Make append mode work on RT11/RSTS ; 000026 17-Feb-81 MM Another runoff hack (see patch 21,22) This one's sick ; 000027 02-Mar-81 MM $$fopo returns on any error. Needed for fwild() ; 000028 14-Apr-81 MM Added "elephant directive" for VMS ; 000029 02-Jun-81 RBD Enable tkb ACTFIL option ; 000030 05-Aug-81 RBD Allow RT11 filesize, other hacks ; 000031 07-Aug-81 MM "n" mode gives R.FIX output files ; 000032 17-Aug-81 RBD Properly set VF$FIL on RSX. ; 000033 21-Aug-81 MM Fix edit 31 (R.VAR for normal output on RSX or VMS) ; 000034 28-Aug-81 MM Branch becomes a JMP on RT11 ; 000035 14-Oct-81 MM Broken into lots of little modules ; 000036 15-Jun-82 MM Stupendous vms v3.0 patch. ; 000037 27-Jun-82 MM New library stuff: directory name, different offsets. ; 000038 26-Jun-82 MM Terminal frob -- see IOPUT.MAC for the gory details. ; 000039 04-Oct-82 MM Set VF$CMD bit if tty is open on same terminal as stderr ; 000040 27-Oct-82 RBD Unterminal unfrob. See INIT.MAC for additional gore. ; P.S ... Isn't it time for a rewrite of this mess?? (RBD) ; Any volunteers? ; 000041 22-Nov-82 TTC Fix append bug. Must clear read as well as append bit, ; if get no such file error on first try. ; RMS042 13-Dec-83 RBD (TTC also) Add conditional support of RMS-11 ; RMS043 17-Dec-83 RBD Clean up RMS stuff (HUH? CLEAN?? well ...) ; RMS044 11-Jan-84 RBD Fix so "wun" does R.VAR binary files, and RMS flavor ; properly initializes the FAB's MRS field for "n" files ; RMS045 05-Feb-84 RBD Add FB$UPD to requested access. Allows overwriting ; of records when opened for append & repositioned. ; 000046 06-Jul-84 RBD Merge in stream junk & restore RSTS junk ; 000047 17-JAN-87 JMC Change psect types ; .iif ndf rsx rsx = 1 ;Assume RSX11M .iif ndf vms3.0 vms3.0 = 0 ;Don't assume hack. ; ; Note the following tests (set in $$fopt) ;37+ ; ; reading: V$FLAG(r4) & VF$REA ; writing: V$FLAG(r4) & VF$WRT ; append: V$FLAG(r4) & VF$APN ;37- ; .if ne rsx .if ne RMSIO .MCALL $FETCH $STORE $OFF $SET $TESTBITS $COMPARE ;42 .MCALL $OPEN $CREATE $CONNECT ;42 .psect c$data,d ;47 .iff .IIF NDF N$$FIL N$$FIL = 8. ;Number of files ;18 F.BFHD == 20 ;For TKB so ACTFIL option works. ;29+ ;When TKB gets to the psect expansion ;section, if F.BFHD is not defined, ;ACTFIL is ignored (F.BFHD is defined in ;the fortran library). TKB adds the ;value of F.BFHD + 512. (hard-wired), ;multiplies this by ACTFIL, and makes ;$$FSR1 this size. Happy now? ;29- .MCALL FDBDF$, FDAT$R, FDOP$R .MCALL FDBK$R, FDRC$R, FSRSZ$, FDOF$L .MCALL OFNB$A, OFNB$R, OFNB$W FDOF$L R.STM = 4 ;Ascii stream record attribute. ;09 ;NOTE: R.STM is unpublished ;WARNING: This bit has been known to ;be set on VMS "Print format" files. R.STMLF = 5 ;ASCII stream format ;46+ R.STMCR = 6 ;ASCII stream format ;Note: these are unpublished also. ;46- .psect c$data,d ;47 ; ; Since the RSX people do not understand reentrant coding, ; the file system must be defined at assembly time. ; ; Note -- code in subroutine $$falo depends on the undocumented ; fact that a dummy file data block is all zero. ; FSRSZ$ N$$FIL ;Define block buffer area ;18 .endc ; .psect c$code,i ;47 FREOPE:: JSR R5,CSV$ ;C save sequence MOV C$PMTR+4(R5),R4 ;Get IOV pointer MOV R4,R0 ;Make R0 non-zero CALL $$CLOS ;Close file, keep IOV BR FOPEN1 ;Continue with main sequence ; FOPEN:: JSR R5,CSV$ ;C save sequence CLR R4 ;Clear IOV pointer, too FOPEN1: ;Common code for fopen, freopen CALL $$FLUN ;Get a Lun CALL $$FOPT ;Scan options string .if ne RMSIO CALL $$FPAR ;Parse the file spec, set up the FAB ;42 .iff CALL $$FCSI ;Parse the CSI string, setup the FDB .endc ;BR $$FOPN ;And open the file ; ; ** $$FOPN ; ; Open the file. This code is specific to fopen/freopen (and fwild if ; no wildcards were found.) ; ; Note: if append and file-not-found, restart for writing ; $$FOPN:: CALL $$FOPO ;Try to open it BIT #VF$APN,V$FLAG(R4) ;Oops, append mode? ;26+/37 BEQ 10$ ;No, return fatally CMPB R0,#IE.NSF ;Append, no such file? BNE 10$ ;No, sorry. BIC #VF$REA!VF$APN,V$FLAG(R4) ;Clear out the mode bits ;37/41 BIS #VF$WRT,V$FLAG(R4) ;Make it a write open ;37 BR $$FOPN ;And try, try, try. 10$: JMP $$FOPE ;Sorry ;26-;35 ; ; ** $$FOPO ; ; Actually open the file which has been setup by $$FCSI (or fnext()) ; If the file opened correctly, there is no return -- the program ; exits to the fopen/fnext caller via $$fopx. On error, $$FOPO ; returns to the caller with the error code in R0. ; $$FOPO:: MOV R4,R0 ;Get IOV .if ne RMSIO MOV R4,R1 ;R1 --> IOV ;42+ ADD #V$FAB,R0 ;R0 --> FAB ADD #V$RAB,R1 ;R1 --> RAB ;42- .iff ADD #V$FDB,R0 ;R0 -> fdb .endc BIC #VF$NOS,V$FLAG(R4) ;Clear current VF$NOS ;26+/37 BIT #VF$NLH,V$WFLG(R4) ;fopen/fwild (..., "n") ;37 BEQ 4$ ;Br if not BIS #VF$NOS,V$FLAG(R4) ;(re)set the bit ;37 ; ; The above mess is needed if, on vms, the program executes fwild() and ; the first file was a .MEM file (which has no attributes) while the ; second file is a "vanilla" ascii file. (FOO.MEM, FOO.RNO). VF$NOS ; is forced for FOO.MEM, but must be zero for FOO.RNO. Sorry, but it's ; the best I could come up with. ; 4$: ;26- BIT #VF$NBF,V$FLAG(R4) ;User buffered? ;37 BEQ 10$ ;No, continue ; ; User-buffering. (The following may have to change) ; .if ne RMSIO $SET #FB$GET!FB$PUT!FB$UPD,FAC,R0 ;42/45 .iff FDRC$R R0 ;I/O via GET$ and PUT$ FDBK$R R0 ;No block buffers .endc BR DOOPEN ;Continue main sequence ; ; I/O package does buffering (record buffer in V$RBUF). ; 10$: BIT #VF$NOS,V$FLAG(R4) ;No newlines wanted? ;37 BNE 20$ ;Branch if so. .if ne RMSIO $SET #FB$CR,RAT,R0 ;42 20$: $SET #FB$GET!FB$PUT!FB$UPD,FAC,R0 ;42/45 .iff FDAT$R R0,,#FD.CR ;Want them, so ask for it. 20$: FDRC$R R0 ;Setup for GET$ or PUT$ FDOP$R R0 ;Initialize file open section .endc ; ; Now for the fun part (sick is more like it!) ; ; At this point R0 --> FDB (FCS) ; or ; R0 --> FAB (RMS) ; R1 --> RAB (RMS) ; DOOPEN: BIT #VF$WRT!VF$APN,V$FLAG(R4) ;Reading ;37 BNE 10$ ;Nope .if ne RMSIO $OFF #FB$PUT!FB$UPD,FAC,R0 ;Reading ... don't touch file ;42/45 $OPEN R0 ;Open existing ;42 BR 30$ ;Main sequence ;46 .iff OFNB$R R0 ;Yep, try for it .if eq vms3.0 ;36+ BR 30$ ;Main sequence ;46 .iff BCS 40$ ;Error -- just exit ;46+ TST $$VMS ;If not vms, BEQ $$FOPX ;Exit normally. ; ; Check whether the file has stream-Ascii attributes. If so, change ; the attributes to "fixed block, 512 byte records". ; NOTE: init.mac contains code to patch the ".OFNB" (open by file name ; block) routine in the RSX file control services to permit opening ; stream files. This code may require revision for subsequent releases ; of vms. ; .iif ne F.RTYP-0 .error The following is incorrect .iif ne F.RATT-1 .error The following is incorrect CMPB #R.STM,(R0) ;Stream file? BGT $$FOPX ;No problems if small CMPB #R.STMLF,(R0) ;Stream file? BLT $$FOPX ;Bigger (R.STMCR) can't be handled MOV #R.FIX+<0*400>,(R0) ; Fixed length, embedded control. MOV F.VBSZ(R0),F.RSIZ(R0) ; Set the record length, too. CLR R1 ;Rewind the file MOV #1,R2 ;to clear out CLR R3 ;the block buffer CALL .POINT ; BR $$FOPX ;All done at last .endc ;eq vms3.0 .endc ;ne rmsio ;46- 10$: BIT #VF$APN,V$FLAG(R4) ;Append? ;37 BEQ 20$ ;Nope, go open for write ;37 .if ne RMSIO $SET #RB$EOF,ROP,R1 ; Position RAB to EOF ;42 $OPEN R0 ;42 .iff OFNB$A R0 ;Try opening for append .endc BR 30$ ;Onward ;26 ; 20$: .if ne RMSIO BIT #VF$NOS,V$FLAG(R4) ;"n" mode? BEQ 25$ ;(no) BIT #VF$NBF,V$FLAG(R4) ;"u" mode? ;44 BNE 25$ ; "u" always veriable length ;44 $STORE #FB$FIX,RFM,R0 ;"n" -- Fixed length ;42 $STORE #512.,MRS,r0 ; 512-byte "records" ;44 BR 26$ ;42 .iff BIT #VF$NOS!VF$NBF,V$FLAG(R4) ;"Binary" file? ;09+/37 BNE 24$ ;Br if so TST $$RSTS ;Stream, but is it RSTS? BEQ 25$ ;No, do it in RSX style ;33 FDAT$R R0,#R.STM ;It's an ascii file WARNING: unpublished. BR 26$ ;Rejoin mainstream 24$: ;09- BIT #VF$NBF,V$FLAG(R4) ;"u" mode (always variable length) ;31+/37 BNE 25$ ;Yes, do variable length FDAT$R R0,#R.FIX ;"n" mode, do fixed length output BR 26$ ;Continue ;31- .endc 25$: ;True RSX or RSX/VMS stream output or .if ne RMSIO $STORE #FB$VAR,RFM,R0 ;"u" or "un" -- Variable length ;42 .iff FDAT$R R0,#R.VAR ;"u" or "un" -- do variable length .endc 26$: ;09 .if ne RMSIO $CREATE R0 ;42+ 30$: $COMPARE #SU$SUC,STS,R0 BNE 40$ $CONNECT R1 $COMPARE #SU$SUC,STS,R1 BEQ $$FOPX MOV R1,R0 ;42- .iff OFNB$W R0 ;Go for it 30$: BCC $$FOPX ;Any errors -- do final cleanup if not .endc ; 40$: .if ne RMSIO $FETCH R0,STS,R0 ;Error code ;42 .iff MOVB F.ERR(R0),R0 ;Error code (sign extended) .endc RETURN ;And let high-level stuff do it ;26 ; ; ** $$FOPX ; ; Normal exit from fopen(). Enter with r4 -> fdb. Returns to fopen ; caller after allocating buffers and setting flag bits. Note: ; the file has been successfully opened, but record buffers have not ; been allocated. ; ; NOTE: If the file is being opened to the same device/unit as stderr, ; the VF$CMD bit is set, indicating that the "file" is actually ; just another channel to the user's "command console". Elsewhere, ; output is diverted to stderr so all console output uses the ; same buffer, nicely avoiding synchronization problems. Thank ; you, Martin!. ; $$FOPX:: BIS #VF$OPN,V$FLAG(R4) ;Mark opened for $$clos and fnext() ;37 BIC #VF$EOR,V$FLAG(R4) ;Ensure not at end of file ;37 .if ne RMSIO MOV R4,R2 ;42+ ADD #V$FAB,R2 ; R2 --> FAB MOV #512.,V$RBSZ(R4) ; 512-byte max record on RMS ;43 $FETCH R0,DEV,R2 ; R0 = Record flag bits ;42- .iff MOV V$FDB+F.VBSZ(R4),V$RBSZ(R4) ;Get Virtual record size MOVB V$FDB+F.RCTL(R4),R0 ;R0 := Record flag bits TST $$VMS ;On vms? ;22/23 BEQ 5$ ;No, onward ;22/23 BITB #7,V$FDB+F.RATT(R4) ;Any attribute bits ;21+ BNE 5$ ;Yes, continue BIS #VF$NOS,V$FLAG(R4) ;No, not stream ;21-/37 5$: .ift $TESTBITS #,DEV,R2 ;Is it a file? ;42 .iff BITB #FD.DIR,R0 ;Is it a file? .endc BEQ 10$ ;No, onward BIS #VF$FIL,V$FLAG(R4) ;A file, set bits ;37 BR 20$ ;And continue 10$: .if ne RMSIO $TESTBITS #FB$REC,DEV,R2 ;Record-oriented device? ;42 .iff BITB #FD.REC,R0 ;Record oriented device? ;32 .endc BEQ 20$ ;No, onward ;32 BIS #VF$REC,V$FLAG(R4) ;Record, no file. Flag same ;37 .if ne RMSIO $TESTBITS #FB$TRM,DEV,R2 ;Terminal? ;42 .iff BITB #FD.TTY,R0 ;True terminal? .endc BEQ 20$ ;No, continue BIS #VF$TTY,V$FLAG(R4) ;Yes, flag it ;37/38/39+/40 mov stderr,r0 ; R0 --> stderr ; ; Check if the file is being opened to the same device/unit as ; stderr. If so, indicate the file is open to the "console" ; by setting VF$CMD (command terminal). ; .if ne RMSIO ; ;42+ ; The following departs from the RMS macro conventions for ; obvious reasons. The assembler does the dirty work of ; calculating the address. ; cmp V$NAM+O$DVI(r4),V$NAM+O$DVI(r0) ; Same name? bne 20$ ; Branch if different devices cmp V$NAM+O$DVI+2(r4),V$NAM+O$DVI+2(r0); Same unit? bne 20$ ; No, its not the console ;42- .iff cmp V$FDB+F.FNB+N.DVNM(r4),V$FDB+F.FNB+N.DVNM(r0) ; Same name? bne 20$ ; Branch if different devices cmp V$FDB+F.FNB+N.UNIT(r4),V$FDB+F.FNB+N.UNIT(R0) ; Same unit? BNE 20$ ; (nope, not console) .endc BIS #VF$CMD,V$FLAG(r4) ; Mark opening the console in iov ;39- 20$: ;; NOTE: the record buffer is allocated by the first call to getch() ;37+ ;; this allows the user to allocate his own buffer by calling setbuf() ;; BIT #VF$NBF,V$FLAG(R4) ;User doing buffering? ;37 ;; BNE 30$ ;Yep, don't get buffer ;; MOV V$RBSZ(R4),R0 ;Record buffer size ;; INC R0 ;Just in case 'n' given ;; CALL $$FALO ;Go for it -- note: if this fails, $$fcls ;; ;will close the file. ;; MOV R0,V$RBUF(R4) ;Set the first buffer ;; MOV R0,V$BPTR(R4) ;and set free byte pointer ;37- 30$: MOV R4,R0 ;Return iov pointer JMP CRET$ ;And exit C-style .iff ;03+ ; ; RT11 file open ; .even ; .psect c$code,i ;47 ; freope:: jsr r5,csv$ ; Establish linkage mov C$PMTR+4(r5),r4 ; Get IOV pointer mov r4,r0 ; Set r0 non-zero to call $$clos ; close the existing file br fopen1 ; continue at main sequence fopen:: jsr r5,csv$ ; Establish linkage clr r4 ; No buffer yet fopen1: ; Common code for fopen/freopen ;04 call $$flun ; Get a Unit (and IOV) call $$fopt ; Scan options string jmp $$fopa ; And go open the file. .endc ; ; ** $$FOPE ; ; Error exit from fopen routines. If r4 is non-zero, the iov it points ; to will be deallocated. ; ; Calling sequence: ; ; mov #IE.code,r0 ;Error code ; jmp $$fope ;Jump here to die. ; $$FOPE:: MOV R0,$$FERR ;Save error code TST R4 ;Have we allocated an I/O vector? BEQ 10$ ;No, just die. CLR R0 ;Yes, force "full close" CALL $$FCLS ;Clean out buffers 10$: CLR R0 ;Return NULL JMP CRET$ ;Exit. .end