]> git.sur5r.net Git - cc65/blob - libsrc/atari/open.s
Some Atari runtime library fixes.
[cc65] / libsrc / atari / open.s
1 ;
2 ; Christian Groessler, Jan-2003
3 ;
4 ; int open(const char *name,int flags,...);
5 ;
6
7         .include "atari.inc"
8         .include "fcntl.inc"
9         .include "errno.inc"
10         .include "fd.inc"
11
12         .export _open
13         .destructor     closeallfiles, 5
14
15         .import _close
16         .import clriocb
17         .import fddecusage,newfd
18         .import findfreeiocb
19         .import incsp4
20         .import ldaxysp,addysp
21         .import __oserror
22         .importzp tmp4,tmp2
23 .ifdef  UCASE_FILENAME
24         .importzp tmp3
25         .import ucase_fn
26 .endif
27
28 .proc   _open
29
30         dey                     ; parm count < 4 shouldn't be needed to be checked
31         dey                     ;       (it generates a c compiler warning)
32         dey
33         dey
34         beq     parmok          ; parameter count ok
35         jsr     addysp          ; fix stack, throw away unused parameters
36
37 parmok: jsr     findfreeiocb
38         beq     iocbok          ; we found one
39
40         lda     #<EMFILE        ; "too many open files"
41 seterr: jsr     __directerrno
42         jsr     incsp4          ; clean up stack
43         lda     #$FF
44         tax
45         rts                     ; return -1
46
47         ; process the mode argument
48
49 iocbok: stx     tmp4
50         jsr     clriocb         ; init with zero
51         ldy     #1
52         jsr     ldaxysp         ; get mode
53         ldx     tmp4
54         pha
55         and     #O_APPEND
56         beq     no_app
57         pla
58         and     #15
59         cmp     #O_RDONLY       ; DOS supports append with write-only only
60         beq     invret
61         cmp     #O_RDWR
62         beq     invret
63         lda     #OPNOT|APPEND
64         bne     set
65
66 .ifndef UCASE_FILENAME
67 invret: lda     #<EINVAL        ; file name is too long
68         jmp     seterr
69 .endif
70
71 no_app: pla
72         and     #15
73         cmp     #O_RDONLY
74         bne     l1
75         lda     #OPNIN
76 set:    sta     ICAX1,x
77         bne     cont
78
79 l1:     cmp     #O_WRONLY
80         bne     l2
81         lda     #OPNOT
82         bne     set
83
84 l2:     ; O_RDWR
85         lda     #OPNOT|OPNIN
86         bne     set
87
88         ; process the filename argument
89
90 cont:   ldy     #3
91         jsr     ldaxysp
92
93 .ifdef  UCASE_FILENAME
94 .ifdef  DEFAULT_DEVICE
95         ldy     #$80
96 .else
97         ldy     #$00
98 .endif
99         sty     tmp2            ; set flag for ucase_fn
100         jsr     ucase_fn
101         bcc     ucok1
102 invret: lda     #<EINVAL        ; file name is too long
103         jmp     seterr
104 ucok1:
105
106 .endif  ; defined UCASE_FILENAME
107
108         ldy     tmp4
109
110         ;AX - points to filename
111         ;Y  - iocb to use, if open needed
112         jsr     newfd           ; maybe we don't need to open and can reuse an iocb
113                                 ; returns fd num to use in tmp2, all regs unchanged
114         bcs     doopen          ; C set: open needed
115         lda     #0              ; clears N flag
116         beq     finish
117
118 doopen: sta     ICBAL,y
119         txa
120         sta     ICBAH,y
121         ldx     tmp4
122         lda     #OPEN
123         sta     ICCOM,x
124         jsr     CIOV
125
126         ; clean up the stack
127
128 finish: php
129         txa
130         pha
131         tya
132         pha
133
134 .ifdef  UCASE_FILENAME
135         ldy     tmp3            ; get size
136         jsr     addysp          ; free used space on the stack
137 .endif  ; defined UCASE_FILENAME
138
139         jsr     incsp4          ; clean up stack
140
141         pla
142         tay
143         pla
144         tax
145         plp
146
147         bpl     ok
148         sty     tmp3            ; remember error code
149         lda     #CLOSE
150         sta     ICCOM,x
151         jsr     CIOV            ; close IOCB again since open failed
152         jsr     fddecusage      ; and decrement usage counter of fd
153         lda     tmp3            ; put error code into A
154         jmp     __mappederrno
155
156 ok:     lda     tmp2            ; get fd
157         ldx     #0
158         stx     __oserror
159         rts
160
161 .endproc
162
163
164 ; closeallfiles: Close all files opened by the program.
165
166 .proc   closeallfiles
167
168         lda     #MAX_FD_INDEX-1
169 loop:   ldx     #0
170         pha
171         jsr     _close
172         pla
173         clc
174         sbc     #0
175         bpl     loop
176         rts
177
178 .endproc