* Openers.asm (of PCQ Pascal runtime library) * Copyright (c) 1989 Patrick Quaid * This file takes care of opening and closing DOS files. In * much the same way as the memory routines, these routines keep a * list of the open files around. Open() puts the files on the list * and Close() takes them off. SECTION ONE XREF _p%DOSBase XREF _LVOOpen XREF _p%new XREF _p%dispose XREF _p%wrapitup XREF _LVORead XREF _LVOClose XDEF filekey * algorithm for open: * * open the file * set the link * store the file handle * if the record size is not 1, 2, or 4 * call _p%new to allocate a buffer * store the address of the buffer * if it's an input file * read the first record * set the eof field accordingly XDEF _p%open _p%open: move.l d2,-(sp) ; save the access mode move.l a0,-(sp) ; save address of file record move.l d0,d1 ; get address of file name string move.l _p%DOSBase,a6 ; d2 already has mode jsr _LVOOpen(a6) tst.l d0 ; opened ok? bne.s 1$ ; if so, skip this add.l #8,sp ; restore stack rts ; and return 1$ move.l (sp)+,a0 ; get address back move.l d0,(a0) ; save file handle in record move.l filekey,14(a0) ; save link move.l a0,filekey ; add to list move.l 8(a0),d0 ; get size cmp.l #1,d0 ; is it 1? beq.s 2$ ; if so, skip this bit here. cmp.l #2,d0 ; ditto if two or four beq.s 2$ cmp.l #4,d0 beq.s 2$ move.l a0,-(sp) ; save address (again) jsr _p%new ; get block of size in d0, left in d0 move.l (sp)+,a0 ; get address back again move.l d0,4(a0) ; store the pointer to the new block bne.s 2$ ; if it's ok, go on. jmp _p%wrapitup ; no memory for file. Abort! 2$ move.b #0,12(a0) ; set eof = false move.l (sp)+,d0 ; retrieve access mode cmp.l #1005,d0 ; is it 1005? bne.s 3$ ; if so, then it's an input file. * at this point, a0 has the address of the file block, which * is set up correctly except for the data direction. Thus we'll * set that, then just call the arbitrary read routine on the file. move.b #0,13(a0) ; set inout = input jsr _p%readarbbuf ; read an arbitrary datum into buffer ; that routine sets the eof flag correctly 3$ move.l #-1,d0 ; regardless of how the read went, the rts ; file IS open, so return true. XDEF _p%readarbbuf _p%readarbbuf * read 'record length' bytes from 'filehandle' into the record's buffer * a0 is the file record * set the eof field accordingly move.l a0,-(sp) move.l (a0),d1 ; get file handle move.l 8(a0),d3 ; get length lea 4(a0),a1 move.l a1,d2 ; get address of buffer. ; this is correct for size = 1,2 or 3. ; figure most will be that size, right? cmp.l #1,d3 ; is it, in fact, 1? beq.s 1$ ; if so, then skip correction cmp.l #2,d3 ; same with 2 beq.s 1$ cmp.l #4,d3 ; and 4 beq.s 1$ move.l 4(a0),d2 ; load ADDRESS of buffer (correct the assumption) 1$ move.l _p%DOSBase,a6 jsr _LVORead(a6) move.l (sp)+,a0 ; retrieve address cmp.l 8(a0),d0 ; did everything go ok? beq.s 2$ ; yes, so just leave move.b #-1,12(a0) ; eof = true 2$ rts XDEF _p%close _p%close: move.l d0,a0 ; get address into a0 1$ cmp.l filekey,a0 ; is this first open file? bne.s 2$ ; if not, go around move.l 14(a0),filekey ; bypass record bra 5$ ; and close file 2$ move.l filekey,a1 move.l 14(a1),a2 ; a1 is trailer, a2 is node 3$ cmp.l a2,a0 ; is this node the original? beq.s 4$ ; if so, go move.l a2,a1 move.l 14(a2),a2 ; set up for next move.l a2,d0 ; is this zero? bne 3$ rts ; wasn't in list! Abort! 4$ move.l 14(a2),a2 ; get next move.l a2,14(a1) ; bypass this node 5$ move.l (a0),d1 move.l a0,-(sp) move.l _p%DOSBase,a6 jsr _LVOClose(a6) move.l (sp)+,a0 move.l 8(a0),d0 cmp.l #1,d0 ; if size = 1 then no buffer beq.s 6$ ; so skip cmp.l #2,d0 ; same for 2 beq.s 6$ cmp.l #4,d0 ; and 4 beq.s 6$ move.l 4(a0),d0 ; get address of block jsr _p%dispose ; free the buffer 6$ rts SECTION TWO filekey dc.l 0 END