mirror of
https://github.com/cc65/cc65.git
synced 2024-07-07 04:29:01 +00:00
169 lines
3.8 KiB
ArmAsm
169 lines
3.8 KiB
ArmAsm
|
;
|
||
|
; Ullrich von Bassewitz, 16.11.2002
|
||
|
;
|
||
|
; int open (const char* name, int flags, ...); /* May take a mode argument */
|
||
|
;
|
||
|
|
||
|
.export _open
|
||
|
|
||
|
.import addysp, popax
|
||
|
.import scratch, fnparse, fncomplete, fnset
|
||
|
.import getdiskerror
|
||
|
.import __errno, __oserror
|
||
|
.import fnunit
|
||
|
.importzp sp, tmp2, tmp3
|
||
|
|
||
|
.include "errno.inc"
|
||
|
.include "fcntl.inc"
|
||
|
.include "cbm.inc"
|
||
|
.include "filedes.inc"
|
||
|
|
||
|
|
||
|
;--------------------------------------------------------------------------
|
||
|
; initstdout: Open the stdout and stderr file descriptors for the screen.
|
||
|
|
||
|
.proc _open
|
||
|
|
||
|
cpy #4 ; correct # of arguments (bytes)?
|
||
|
beq parmok ; parameter count ok
|
||
|
tya ; parm count < 4 shouldn't be needed to be...
|
||
|
sec ; ...checked (it generates a c compiler warning)
|
||
|
sbc #4
|
||
|
tay
|
||
|
jsr addysp ; fix stack, throw away unused parameters
|
||
|
|
||
|
; Parameters ok. Pop the flags and save them into tmp3
|
||
|
|
||
|
parmok: jsr popax ; Get flags
|
||
|
sta tmp3
|
||
|
|
||
|
; Get the filename from stack and parse it. Bail out if is not ok
|
||
|
|
||
|
jsr popax ; Get name
|
||
|
jsr fnparse ; Parse it
|
||
|
cmp #0
|
||
|
bne error ; Bail out if problem with name
|
||
|
|
||
|
; Get a free file handle and remember it in tmp2
|
||
|
|
||
|
jsr freefd
|
||
|
bcs nofile
|
||
|
stx tmp2
|
||
|
|
||
|
; Check the flags. We cannot have:
|
||
|
;
|
||
|
; - both, read and write flags set
|
||
|
; - the append flag set
|
||
|
;
|
||
|
|
||
|
lda tmp3
|
||
|
and #O_RDWR
|
||
|
beq invflags ; Neither read nor write
|
||
|
cmp #O_RDWR
|
||
|
beq invflags ; Jump if both set
|
||
|
cmp #O_RDONLY
|
||
|
beq doread
|
||
|
|
||
|
; Write bit is set. We cannot open a file for writing without creating it,
|
||
|
; so check for the O_CREAT bit.
|
||
|
|
||
|
lda tmp3
|
||
|
and #O_CREAT
|
||
|
beq invflags
|
||
|
|
||
|
; If O_TRUNC is set, scratch the file, but ignore any errors
|
||
|
|
||
|
lda tmp3
|
||
|
and #O_TRUNC
|
||
|
beq notrunc
|
||
|
jsr scratch
|
||
|
|
||
|
; Complete the the file name
|
||
|
|
||
|
notrunc:
|
||
|
lda #'w'
|
||
|
jsr fncomplete
|
||
|
|
||
|
; Setup the real open flags
|
||
|
|
||
|
lda #LFN_WRITE
|
||
|
bne common
|
||
|
|
||
|
; Read bit is set. Add an 'r' to the name
|
||
|
|
||
|
doread: lda #'r'
|
||
|
jsr fncomplete
|
||
|
lda #LFN_READ
|
||
|
|
||
|
; Common read/write code. Flags in A, handle in tmp2
|
||
|
|
||
|
common: sta tmp3
|
||
|
jsr fnset ; Set the file name
|
||
|
|
||
|
lda tmp2
|
||
|
clc
|
||
|
adc #LFN_OFFS
|
||
|
ldx fnunit
|
||
|
tay ; Use the LFN also as SA
|
||
|
jsr SETLFS ; Set the file params
|
||
|
|
||
|
jsr OPEN
|
||
|
bcs error
|
||
|
|
||
|
; Read the error channel
|
||
|
|
||
|
ldx fnunit
|
||
|
jsr getdiskerror
|
||
|
cmp #0
|
||
|
beq isopen ; Branch if no error
|
||
|
|
||
|
; We had an error, close the file
|
||
|
|
||
|
pha
|
||
|
lda tmp2
|
||
|
clc
|
||
|
adc #LFN_OFFS
|
||
|
jsr CLOSE
|
||
|
pla
|
||
|
bne error ; Branch always
|
||
|
|
||
|
; File is open. Mark it as open in the table
|
||
|
|
||
|
isopen: ldx tmp2
|
||
|
lda tmp3
|
||
|
sta fdtab,x
|
||
|
lda fnunit
|
||
|
sta unittab,x ; Remember
|
||
|
|
||
|
; Done. Return the handle in a/x
|
||
|
|
||
|
txa ; Handle
|
||
|
ldx #0
|
||
|
rts
|
||
|
|
||
|
; Error entry: No more file handles
|
||
|
|
||
|
nofile: lda #1 ; Too many open files
|
||
|
|
||
|
; Error entry. Error code is in A.
|
||
|
|
||
|
error: sta __oserror
|
||
|
errout: lda #$FF
|
||
|
tax ; Return -1
|
||
|
rts
|
||
|
|
||
|
; Error entry: Invalid flag parameter
|
||
|
|
||
|
invflags:
|
||
|
lda #EINVAL
|
||
|
sta __errno
|
||
|
lda #0
|
||
|
sta __errno+1
|
||
|
beq errout
|
||
|
|
||
|
|
||
|
|
||
|
.endproc
|
||
|
|
||
|
|