+++ /dev/null
-/*
- * _fopen.c
- *
- * Ullrich von bassewitz, 17.06.1997
- */
-
-
-
-#include <fcntl.h>
-#include <errno.h>
-#include "_file.h"
-
-
-
-static unsigned char amode_to_bmode (const char* mode)
-/* Convert ASCII mode (like for fopen) to binary mode (for open) */
-{
- unsigned char binmode;
-
- switch (*mode++) {
- case 'w':
- binmode = O_WRONLY | O_CREAT | O_TRUNC;
- break;
- case 'r':
- binmode = O_RDONLY;
- break;
- case 'a':
- binmode = O_WRONLY | O_CREAT | O_APPEND;
- break;
- default:
- return 0; /* invalid char */
- }
-
- while (1) {
- switch (*mode++) {
- case '+':
- /* always to r/w in addition to anything already set */
- binmode |= O_RDWR;
- break;
- case 'b':
- /* currently ignored */
- break;
- case '\0':
- /* end of mode string reached */
- return binmode;
- default:
- /* invalid char in mode string */
- return 0;
- }
- }
-}
-
-
-
-FILE* _fopen (const char* name, const char* mode, FILE* f)
-/* Open the specified file and fill the descriptor values into f */
-{
- int fd;
- unsigned char binmode;
-
-
- /* Convert ASCII mode to binary mode */
- if ((binmode = amode_to_bmode (mode)) == 0) {
- /* Invalid mode */
- _errno = EINVAL;
- return 0;
- }
-
- /* Open the file */
- fd = open (name, binmode);
- if (fd == -1) {
- /* Error - _oserror is set */
- return 0;
- }
-
- /* Remember fd, mark the file as opened */
- f->f_fd = fd;
- f->f_flags = _FOPEN;
-
- /* Return the file descriptor */
- return f;
-}
-
-
-
--- /dev/null
+;
+; Ullrich von Bassewitz, 22.11.2002
+;
+; FILE* __fastcall__ _fopen (const char* name, const char* mode, FILE* f);
+; /* Open the specified file and fill the descriptor values into f */
+;
+
+ .export __fopen
+
+ .import _open
+ .import pushax, incsp4, return0
+ .importzp sp, ptr1
+
+
+ .include "errno.inc"
+ .include "fcntl.inc"
+ .include "_file.inc"
+
+
+; ------------------------------------------------------------------------
+; Code
+
+.proc __fopen
+
+ sta f
+ stx f+1 ; Save f
+
+; Get a pointer to the mode string
+
+ ldy #1
+ lda (sp),y
+ sta ptr1+1
+ dey
+ lda (sp),y
+ sta ptr1
+
+; Look at the first character in mode
+
+ ldx #$00 ; Mode will be in X
+ lda (ptr1),y ; Get first char from mode
+ cmp #'w'
+ bne @L1
+ ldx #(O_WRONLY | O_CREAT | O_TRUNC)
+ bne @L3
+@L1: cmp #'r'
+ bne @L2
+ ldx #O_RDONLY
+ bne @L3
+@L2: cmp #'a'
+ bne invmode
+ ldx #(O_WRONLY | O_CREAT | O_APPEND)
+
+; Look at more chars from the mode string
+
+@L3: iny ; Next char
+ beq invmode
+ lda (ptr1),y
+ beq modeok ; End of mode string reached
+ cmp #'+'
+ bne @L4
+ txa
+ ora #O_RDWR ; Always do r/w in addition to anything else
+ tax
+ bne @L3
+@L4: cmp #'b'
+ beq @L3 ; Binary mode is ignored
+
+; Invalid mode
+
+invmode:
+ lda #EINVAL
+ sta __errno
+ lda #0
+ sta __errno+1
+ tax
+ jmp incsp4
+
+; Mode string successfully parsed. Store the binary mode onto the stack in
+; the same place where the mode string pointer was before. The call open()
+
+modeok: ldy #$00
+ txa ; Mode -> A
+ sta (sp),y
+ tya
+ iny
+ sta (sp),y
+ ldy #4 ; Size of arguments in bytes
+ jsr _open ; Will cleanup the stack
+
+; Check the result of the open() call
+
+ cpx #$FF
+ bne openok
+ cmp #$FF
+ bne openok
+ jmp return0 ; Failure, errno/_oserror already set
+
+; Open call succeeded
+
+openok: ldy f
+ sty ptr1
+ ldy f+1
+ sty ptr1+1
+ ldy #_FILE_f_fd
+ sta (ptr1),y ; f->f_fd = fd;
+ ldy #_FILE_f_flags
+ lda #_FOPEN
+ sta (ptr1),y ; f->f_flags = _FOPEN;
+
+; Return the pointer to the file structure
+
+ lda ptr1
+ ldx ptr1+1
+ rts
+
+.endproc
+
+; ------------------------------------------------------------------------
+; Data
+
+.bss
+f: .res 2
+
+