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