]> git.sur5r.net Git - cc65/blob - libsrc/cbm/open.s
no TGI_ERR_NO_MEM or TGI_ERR_NO_IOCB anymore: replaced by TGI_ERR_NO_RES
[cc65] / libsrc / cbm / open.s
1 ;
2 ; Ullrich von Bassewitz, 16.11.2002
3 ;
4 ; int open (const char* name, int flags, ...);  /* May take a mode argument */
5 ;
6 ; Be sure to keep the value priority of closeallfiles lower than that of
7 ; closeallstreams (which is the high level C file I/O counterpart and must be
8 ; called before closeallfiles).
9
10
11         .export         _open
12         .destructor     closeallfiles, 17
13
14         .import         SETLFS, OPEN, CLOSE
15         .import         addysp, popax
16         .import         scratch, fnparse, fnaddmode, fncomplete, fnset
17         .import         opencmdchannel, closecmdchannel, readdiskerror
18         .import         __oserror
19         .import         fnunit
20         .import         _close
21         .importzp       sp, tmp2, tmp3
22
23         .include        "errno.inc"
24         .include        "fcntl.inc"
25         .include        "filedes.inc"
26
27
28 ;--------------------------------------------------------------------------
29 ; closeallfiles: Close all open files.
30
31 .proc   closeallfiles
32
33         ldx     #MAX_FDS-1
34 loop:   lda     fdtab,x
35         beq     next            ; Skip unused entries
36
37 ; Close this file
38
39         txa
40         pha                     ; Save current value of X
41         ldx     #0
42         jsr     _close
43         pla
44         tax
45
46 ; Next file
47
48 next:   dex
49         bpl     loop
50
51         rts
52
53 .endproc
54
55 ;--------------------------------------------------------------------------
56 ; _open
57
58 .proc   _open
59
60 ; Throw away any additional parameters passed through the ellipsis
61
62         dey                     ; Parm count < 4 shouldn't be needed to be...
63         dey                     ; ...checked (it generates a c compiler warning)
64         dey
65         dey
66         beq     parmok          ; Branch if parameter count ok
67         jsr     addysp          ; Fix stack, throw away unused parameters
68
69 ; Parameters ok. Pop the flags and save them into tmp3
70
71 parmok: jsr     popax           ; Get flags
72         sta     tmp3
73
74 ; Get the filename from stack and parse it. Bail out if is not ok
75
76         jsr     popax           ; Get name
77         jsr     fnparse         ; Parse it
78         cmp     #0
79         bne     error           ; Bail out if problem with name
80
81 ; Get a free file handle and remember it in tmp2
82
83         jsr     freefd
84         bcs     nofile
85         stx     tmp2
86
87 ; Check the flags. We cannot have both, read and write flags set, and we cannot
88 ; open a file for writing without creating it.
89
90         lda     tmp3
91         and     #(O_RDWR | O_CREAT)
92         cmp     #O_RDONLY       ; Open for reading?
93         beq     doread          ; Yes: Branch
94         cmp     #(O_WRONLY | O_CREAT)   ; Open for writing?
95         bne     invflags        ; No: Invalid open mode
96
97 ; If O_TRUNC is set, scratch the file, but ignore any errors
98
99         lda     tmp3
100         and     #O_TRUNC
101         beq     notrunc
102         jsr     scratch
103
104 ; Complete the the file name. Check for append mode here.
105
106 notrunc:
107         lda     tmp3            ; Get the mode again
108         ldx     #'a'
109         and     #O_APPEND       ; Append mode?
110         bne     append          ; Branch if yes
111         ldx     #'w'
112 append: txa
113         jsr     fncomplete      ; Add type and mode to the name
114
115 ; Setup the real open flags
116
117         lda     #LFN_WRITE
118         bne     common
119
120 ; Read bit is set. Add an 'r' to the name
121
122 doread: lda     #'r'
123         jsr     fnaddmode       ; Add the mode to the name
124         lda     #LFN_READ
125
126 ; Common read/write code. Flags in A, handle in tmp2
127
128 common: sta     tmp3
129         jsr     fnset           ; Set the file name
130
131         lda     tmp2
132         clc
133         adc     #LFN_OFFS
134         ldx     fnunit
135         tay                     ; Use the LFN also as SA
136         jsr     SETLFS          ; Set the file params
137
138         jsr     OPEN
139         bcs     error
140
141 ; Open the the drive command channel and read it
142
143         ldx     fnunit
144         jsr     opencmdchannel
145         bne     closeandexit
146         ldx     fnunit
147         jsr     readdiskerror
148         bne     closeandexit    ; Branch on error
149
150 ; File is open. Mark it as open in the table
151
152         ldx     tmp2
153         lda     tmp3
154         sta     fdtab,x
155         lda     fnunit
156         sta     unittab,x       ; Remember
157
158 ; Done. Return the handle in a/x
159
160         txa                     ; Handle
161         ldx     #0
162         rts
163
164 ; Error entry: No more file handles
165
166 nofile: lda     #1              ; Too many open files
167
168 ; Error entry. Error code is in A.
169
170 error:  sta     __oserror
171 errout: lda     #$FF
172         tax                     ; Return -1
173         rts
174
175 ; Error entry: Invalid flag parameter
176
177 invflags:
178         lda     #EINVAL
179         sta     __errno
180         lda     #0
181         sta     __errno+1
182         beq     errout
183
184 ; Error entry: Close the file and exit
185
186 closeandexit:
187         pha
188         lda     tmp2
189         clc
190         adc     #LFN_OFFS
191         jsr     CLOSE
192         ldx     fnunit
193         jsr     closecmdchannel
194         pla
195         bne     error           ; Branch always
196
197 .endproc
198
199