+++ /dev/null
-/*
- * fread.c
- *
- * Ullrich von Bassewitz, 02.06.1998
- */
-
-
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "_file.h"
-
-
-
-size_t fread (void* buf, size_t size, size_t count, FILE* f)
-{
- int bytes;
-
- /* Is the file open? */
- if ((f->f_flags & _FOPEN) == 0) {
- _errno = EINVAL; /* File not open */
- return 0;
- }
-
- /* Did we have an error or EOF? */
- if ((f->f_flags & (_FERROR | _FEOF)) != 0) {
- /* Cannot read from stream */
- return 0;
- }
-
- /* How many bytes to read? */
- bytes = size * count;
-
- if (bytes) {
-
- /* Read the data. */
- bytes = read (f->f_fd, buf, bytes);
-
- switch (bytes) {
-
- case -1:
- /* Read error */
- f->f_flags |= _FERROR;
- return 0;
-
- case 0:
- /* End of file */
- f->f_flags |= _FEOF;
- /* FALLTHROUGH */
-
- default:
- /* Unfortunately, we cannot avoid the divide here... */
- return bytes / size;
- }
-
- } else {
-
- /* 0 bytes read */
- return count;
-
- }
-}
-
-
-
--- /dev/null
+;
+; Ullrich von Bassewitz, 22.11.2002
+;
+; size_t __fastcall__ fread (void* buf, size_t size, size_t count, FILE* f);
+; /* Read from a file */
+;
+
+ .export _fread
+
+ .import _read
+ .import pushax, incsp6, addysp, ldaxysp, pushwysp, return0
+ .import tosumulax, tosudivax
+
+ .importzp ptr1, tmp1
+
+ .include "errno.inc"
+ .include "_file.inc"
+
+
+; ------------------------------------------------------------------------
+; Code
+
+.proc _fread
+
+; Save f and place it into ptr1
+
+ sta f
+ sta ptr1
+ stx f+1
+ stx ptr1+1
+
+; Check if the file is open
+
+ ldy #_FILE_f_flags
+ lda (ptr1),y
+ and #_FOPEN ; Is the file open?
+ bne @L2 ; Branch if yes
+
+; File not open
+
+ lda #EINVAL
+ sta __errno
+ lda #0
+ sta __errno+1
+@L1: jsr incsp6
+ jmp return0
+
+; Check if the stream is in an error state
+
+@L2: lda (ptr1),y ; get f->f_flags again
+ and #_FERROR
+ bne @L1
+
+; Build the stackframe for read()
+
+ ldy #_FILE_f_fd
+ lda (ptr1),y
+ ldx #$00
+ jsr pushax ; f->f_fd
+
+ ldy #9
+ jsr pushwysp ; buf
+
+; Stack is now: buf/size/count/f->fd/buf
+; Calculate the number of bytes to read: count * size
+
+ ldy #7
+ jsr pushwysp ; count
+ ldy #9
+ jsr ldaxysp ; Get size
+ jsr tosumulax ; count * size -> a/x
+
+; Check if the number of bytes is zero. Don't call read in this case
+
+ cpx #0
+ bne @L3
+ cmp #0
+ bne @L3
+
+; The number of bytes to read is zero, just return count
+
+ ldy #5
+ jsr ldaxysp ; Get count
+ ldy #10
+ jmp addysp ; Drop params, return
+
+; Call read(). This will leave the original 3 params on the stack
+
+@L3: jsr pushax
+ jsr _read
+
+; Check for errors in read
+
+ cpx #$FF
+ bne @L5
+ cmp #$FF
+ bne @L5
+
+; Error in read. Set the stream error flag and bail out. _oserror and/or
+; errno are already set by read().
+
+ lda #_FERROR
+@L4: sta tmp1
+ lda f
+ sta ptr1
+ lda f+1
+ sta ptr1+1
+ ldy #_FILE_f_flags
+ lda (ptr1),y
+ ora tmp1
+ sta (ptr1),y
+ bne @L1 ; Return zero
+
+; Read was ok, check for end of file.
+
+@L5: cmp #0 ; Zero bytes read?
+ bne @L6
+ cpx #0
+ bne @L6
+
+; Zero bytes read. Set the EOF flag
+
+ lda #_FEOF
+ bne @L4 ; Set flag and return zero
+
+; Return the number of items successfully read. Since we've checked for
+; bytes == 0 above, size cannot be zero here, so the division is safe.
+
+@L6: jsr pushax ; Push number of bytes read
+ ldy #5
+ jsr ldaxysp ; Get size
+ jsr tosudivax ; bytes / size -> a/x
+ jmp incsp6 ; Drop params, return
+
+.endproc
+
+; ------------------------------------------------------------------------
+; Data
+
+.bss
+f: .res 2
+