]> git.sur5r.net Git - cc65/blob - libsrc/cbm/open.s
Added getenv()
[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
34 loop:   lda     fdtab-1,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         bne     loop
50
51         rts
52
53 .endproc
54
55 ;--------------------------------------------------------------------------
56 ; _open
57
58 .proc   _open
59
60         cpy     #4              ; correct # of arguments (bytes)?
61         beq     parmok          ; parameter count ok
62         tya                     ; parm count < 4 shouldn't be needed to be...
63         sec                     ; ...checked (it generates a c compiler warning)
64         sbc     #4
65         tay
66         jsr     addysp          ; fix stack, throw away unused parameters
67
68 ; Parameters ok. Pop the flags and save them into tmp3
69
70 parmok: jsr     popax           ; Get flags
71         sta     tmp3
72
73 ; Get the filename from stack and parse it. Bail out if is not ok
74
75         jsr     popax           ; Get name
76         jsr     fnparse         ; Parse it
77         cmp     #0
78         bne     error           ; Bail out if problem with name
79
80 ; Get a free file handle and remember it in tmp2
81
82         jsr     freefd
83         bcs     nofile
84         stx     tmp2
85
86 ; Check the flags. We cannot have both, read and write flags set, and we cannot
87 ; open a file for writing without creating it.
88
89         lda     tmp3
90         and     #(O_RDWR | O_CREAT)
91         cmp     #O_RDONLY       ; Open for reading?
92         beq     doread          ; Yes: Branch
93         cmp     #(O_WRONLY | O_CREAT)   ; Open for writing?
94         bne     invflags        ; No: Invalid open mode
95
96 ; If O_TRUNC is set, scratch the file, but ignore any errors
97
98         lda     tmp3
99         and     #O_TRUNC
100         beq     notrunc
101         jsr     scratch
102
103 ; Complete the the file name. Check for append mode here.
104
105 notrunc:
106         lda     tmp3            ; Get the mode again
107         ldx     #'a'
108         and     #O_APPEND       ; Append mode?
109         bne     append          ; Branch if yes
110         ldx     #'w'
111 append: txa
112         jsr     fncomplete      ; Add type and mode to the name
113
114 ; Setup the real open flags
115
116         lda     #LFN_WRITE
117         bne     common
118
119 ; Read bit is set. Add an 'r' to the name
120
121 doread: lda     #'r'
122         jsr     fnaddmode       ; Add the mode to the name
123         lda     #LFN_READ
124
125 ; Common read/write code. Flags in A, handle in tmp2
126
127 common: sta     tmp3
128         jsr     fnset           ; Set the file name
129
130         lda     tmp2
131         clc
132         adc     #LFN_OFFS
133         ldx     fnunit
134         tay                     ; Use the LFN also as SA
135         jsr     SETLFS          ; Set the file params
136
137         jsr     OPEN
138         bcs     error
139
140 ; Open the the drive command channel and read it
141
142         ldx     fnunit
143         jsr     opencmdchannel
144         bne     closeandexit
145         ldx     fnunit
146         jsr     readdiskerror
147         bne     closeandexit    ; Branch on error
148
149 ; File is open. Mark it as open in the table
150
151         ldx     tmp2
152         lda     tmp3
153         sta     fdtab,x
154         lda     fnunit
155         sta     unittab,x       ; Remember
156
157 ; Done. Return the handle in a/x
158
159         txa                     ; Handle
160         ldx     #0
161         rts
162
163 ; Error entry: No more file handles
164
165 nofile: lda     #1              ; Too many open files
166
167 ; Error entry. Error code is in A.
168
169 error:  sta     __oserror
170 errout: lda     #$FF
171         tax                     ; Return -1
172         rts
173
174 ; Error entry: Invalid flag parameter
175
176 invflags:
177         lda     #EINVAL
178         sta     __errno
179         lda     #0
180         sta     __errno+1
181         beq     errout
182
183 ; Error entry: Close the file and exit
184
185 closeandexit:
186         pha
187         lda     tmp2
188         clc
189         adc     #LFN_OFFS
190         jsr     CLOSE
191         ldx     fnunit
192         jsr     closecmdchannel
193         pla
194         bne     error           ; Branch always
195
196 .endproc
197
198