File: open.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (196 lines) | stat: -rw-r--r-- 5,042 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
;
; Ullrich von Bassewitz, 16.11.2002
;
; int open (const char* name, int flags, ...);  /* May take a mode argument */


        .export         _open
        .destructor     closeallfiles, 5

        .import         addysp, popax
        .import         scratch, fnparse, fnaddmode, fncomplete, fnset
        .import         opencmdchannel, closecmdchannel, readdiskerror
        .import         fnunit, fnisfile
        .import         _close
        .importzp       sp, tmp2, tmp3

        .include        "errno.inc"
        .include        "fcntl.inc"
        .include        "filedes.inc"
        .include        "cbm.inc"


;--------------------------------------------------------------------------
; closeallfiles: Close all open files.

.proc   closeallfiles

        ldx     #MAX_FDS-1
loop:   lda     fdtab,x
        beq     next            ; Skip unused entries

; Close this file

        txa
        pha                     ; Save current value of X
        ldx     #0
        jsr     _close
        pla
        tax

; Next file

next:   dex
        bpl     loop

        rts

.endproc

;--------------------------------------------------------------------------
; _open

.proc   _open

; Throw away any additional parameters passed through the ellipsis

        dey                     ; Parm count < 4 shouldn't be needed to be...
        dey                     ; ...checked (it generates a c compiler warning)
        dey
        dey
        beq     parmok          ; Branch if parameter count ok
        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
        tax
        bne     oserror         ; Bail out if problem with name

; Get a free file handle and remember it in tmp2

        jsr     freefd
        lda     #EMFILE         ; Load error code
        bcs     seterrno        ; Jump in case of errors
        stx     tmp2

; Check the flags. We cannot have both, read and write flags set, and we cannot
; open a file for writing without creating it.

        lda     tmp3
        and     #(O_RDWR | O_CREAT)
        cmp     #O_RDONLY       ; Open for reading?
        beq     doread          ; Yes: Branch
        cmp     #(O_WRONLY | O_CREAT)   ; Open for writing?
        beq     dowrite

; Invalid open mode

        lda     #EINVAL

; Error entry. Sets _errno, clears _oserror, returns -1

seterrno:
        jmp     __directerrno

; Error entry: Close the file and exit. OS error code is in A on entry

closeandexit:
        pha
        lda     tmp2
        clc
        adc     #LFN_OFFS
        jsr     CLOSE
        ldx     fnunit
        jsr     closecmdchannel
        pla

; Error entry: Set oserror and errno using error code in A and return -1

oserror:jmp     __mappederrno

; Read bit is set. Add an 'r' to the name

doread: lda     #'r'
        jsr     fnaddmode       ; Add the mode to the name
        lda     #LFN_READ
        bne     common          ; Branch always

; If O_TRUNC is set, scratch the file, but ignore any errors

dowrite:
        lda     tmp3
        and     #O_TRUNC
        beq     notrunc
        jsr     scratch

; Complete the the file name. Check for append mode here.

notrunc:
        lda     tmp3            ; Get the mode again
        and     #O_APPEND       ; Append mode?
        bne     append          ; Branch if yes

; Setup the name for create mode

        lda     #'w'
        jsr     fncomplete      ; Add type and mode to the name
        jmp     appendcreate

; Append bit is set. Add an 'a' to the name

append: lda     #'a'
        jsr     fnaddmode       ; Add open mode to file name
appendcreate:
        lda     #LFN_WRITE

; 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
        ldy     fnisfile        ; Is this a standard file on disk?
        beq     nofile          ; Branch if not
        tay                     ; Use the LFN also as SA for files
nofile:                         ; ... else use SA=0 (read)
        jsr     SETLFS          ; Set the file params

        jsr     OPEN
        bcs     oserror

; Open the the drive command channel and read it

        ldx     fnunit
        jsr     opencmdchannel
        bne     closeandexit
        ldx     fnunit
        jsr     readdiskerror
        bne     closeandexit    ; Branch on error

; File is open. Mark it as open in the table

        ldx     tmp2
        lda     tmp3
        sta     fdtab,x
        lda     fnunit
        sta     unittab,x       ; Remember

; Done. Return the handle in a/x

        txa                     ; Handle
        ldx     #0
        stx     __oserror       ; Clear _oserror
        rts

.endproc