]> git.sur5r.net Git - cc65/commitdiff
New function _dirskip that allows to skip an amount of bytes from the
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 1 Jun 2012 19:23:34 +0000 (19:23 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 1 Jun 2012 19:23:34 +0000 (19:23 +0000)
directory with error check.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5668 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/cbm/Makefile
libsrc/cbm/dir.h
libsrc/cbm/dir.inc
libsrc/cbm/dir.s [new file with mode: 0644]
libsrc/cbm/opendir.c

index cc8fc7b17f265929f292a23e259e837fecc2204d..a811edac1afaf7a2a70cffe44aaec1246bff080c 100644 (file)
@@ -65,6 +65,7 @@ S_OBJS =      c_acptr.o       \
                 closedir.o      \
                ctype.o         \
                cvline.o        \
+                dir.o           \
                 diskcmd.o       \
                 exehdr.o        \
                 filedes.o       \
index a1137acfe7eac1f4c60625ffa6c05613ade1f9b0..06081a47ce46ff2db62f3cc62235d6c341e27b95 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Internal include file, do not use directly.
  * Written by Ullrich von Bassewitz. Based on code by Groepaz.
  */
@@ -24,6 +24,22 @@ struct DIR {
 
 
 
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+unsigned char __fastcall__ _dirskip (unsigned char count, struct DIR* dir);
+/* Skip bytes from the directory and make sure, errno is set if this isn't
+ * possible. Return true if anything is ok and false otherwise. For
+ * simplicity we assume that read will never return less than count if there
+ * is no error and end-of-file is not reached.
+ * Note: count must not be more than 254.
+ */
+
+
+
 /* End of dir.h */
 #endif
 
index 447b35c8fcdfda6fb14d64f664811d4b9dae3b03..3536f87f7808e6da6edfaee22952ba0ae59631de 100644 (file)
@@ -23,5 +23,5 @@
         .global _readdir
         .global _telldir
         .global _rewinddir
-
+        .global __dirskip
 
diff --git a/libsrc/cbm/dir.s b/libsrc/cbm/dir.s
new file mode 100644 (file)
index 0000000..903e204
--- /dev/null
@@ -0,0 +1,92 @@
+;
+; Ullrich von Bassewitz, 2012-06-01
+;
+; unsigned char __fastcall__ _dirskip (unsigned char count, struct DIR* dir);
+; /* Skip bytes from the directory and make sure, errno is set if this isn't
+;  * possible. Return true if anything is ok and false otherwise. For
+;  * simplicity we assume that read will never return less than count if there
+;  * is no error and end-of-file is not reached.
+;  * Note: count must not be more than 254.
+;  */
+;
+
+        .include        "dir.inc"
+        .include        "errno.inc"
+        .include        "zeropage.inc"
+
+        .import         _read
+        .import         pushax, pushptr1idx
+        .import         subysp, addysp1
+
+
+.proc   __dirskip
+
+        sta     ptr1
+        stx     ptr1+1          ; Save dir
+
+; Get count and allocate space on the stack
+
+        ldy     #0
+        lda     (sp),y
+        pha
+        tay
+        jsr     subysp
+
+; Save current value of sp
+
+        lda     sp
+        pha
+        lda     sp+1
+        pha
+
+; Push dir->fd
+
+        ldy     #DIR::fd+1
+        jsr     pushptr1idx
+
+; Push pointer to buffer
+
+        pla
+        tax
+        pla
+        jsr     pushax
+
+; Load count and call read
+
+        pla
+        pha
+        ldx     #0
+        jsr     _read
+
+; Check for errors. In case of errors, errno is already set.
+
+        cpx     #$FF
+        bne     L2
+
+; read() returned an error
+
+        pla                     ; Count
+        tay
+        lda     #0
+        tax
+L1:     jmp     addysp1         ; Drop buffer plus count
+
+; read() was successful, check number of bytes read. We assume that read will
+; not return more than count, so X is zero if we come here.
+
+L2:     sta     tmp1
+        pla                     ; count
+        tay
+        cmp     tmp1
+        beq     L1              ; Drop variables, return count
+
+; Didn't read enough bytes. This is an error for us, but errno is not set
+
+        lda     #<EIO
+        sta     __errno
+        stx     __errno+1
+        txa                     ; A=X=0
+        beq     L1              ; Branch always
+
+.endproc
+
index cf8cfb631b645123680e65bff080c08583bf9adc..c3f6f1440567792c59466cfb8951be325a6a16d0 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
+ */
+
 #include <stdlib.h>
 #include <string.h>
 #include <dirent.h>
 
 DIR* __fastcall__ opendir (const char*)
 {
-    unsigned char buffer[8+16+1+7];
-    int count;
-    DIR d;
     DIR* dir = 0;
+    DIR d;
 
     /* Setup file name and offset */
     d.name[0] = '$';
@@ -25,8 +27,7 @@ DIR* __fastcall__ opendir (const char*)
     if (d.fd >= 0) {
 
         /* Skip the disk header */
-        count = read (d.fd, buffer, sizeof (buffer));
-        if (count == sizeof (buffer)) {
+        if (_dirskip (32, &d)) {
 
             /* Allocate memory for the DIR structure returned */
             dir = malloc (sizeof (*dir));
@@ -38,9 +39,6 @@ DIR* __fastcall__ opendir (const char*)
                 /* Set an appropriate error code */
                 errno = ENOMEM;
             }
-        } else if (count >= 0) {
-            /* Short read - need to set an error code */
-            errno = EIO;
         }
     }