From ebca2991a3e69c9b6deb599aba952c56f830db64 Mon Sep 17 00:00:00 2001 From: uz Date: Sat, 2 Jun 2012 22:56:14 +0000 Subject: [PATCH] Moved most of the file type detection from cbm_dir.c into a new function called _cbm_filetype(). Added an assembler include file with the file type definitions from cbm.h. Added a first implementation of readdir() for the CBMs. git-svn-id: svn://svn.cc65.org/cc65/trunk@5669 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- asminc/cbm_ftype.inc | 33 +++++++++++ include/cbm.h | 12 +++- include/dirent.h | 4 +- libsrc/cbm/Makefile | 4 +- libsrc/cbm/cbm_dir.c | 14 +---- libsrc/cbm/cbm_ftype.s | 71 ++++++++++++++++++++++ libsrc/cbm/dir.h | 2 +- libsrc/cbm/opendir.c | 2 +- libsrc/cbm/readdir.c | 131 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 254 insertions(+), 19 deletions(-) create mode 100644 asminc/cbm_ftype.inc create mode 100644 libsrc/cbm/cbm_ftype.s create mode 100644 libsrc/cbm/readdir.c diff --git a/asminc/cbm_ftype.inc b/asminc/cbm_ftype.inc new file mode 100644 index 000000000..c1f1afcf2 --- /dev/null +++ b/asminc/cbm_ftype.inc @@ -0,0 +1,33 @@ +; +; Definitions for CBM file types. From cbm.h +; +; Ullrich von Bassewitz, 2012-06-03 +; + +; Define bitmapped constants for the table entries + +.enum + CBM_T_DEL ; Deleted file + CBM_T_SEQ ; Sequential file + CBM_T_PRG ; Program file + CBM_T_USR ; User file + CBM_T_REL ; Relative file + CBM_T_CBM ; 1581 sub-partition + CBM_T_DIR ; IDE64 and CMD sub-directory + CBM_T_LNK ; IDE64 soft-link + CBM_T_VRP ; Vorpal fast-loadable format + CBM_T_OTHER ; File-type not recognized + CBM_T_HEADER ; Disk header / title +.endenum + + +; The following function maps the start character for a file type to +; one of the file types above. Note: 'd' will always mapped to CBM_T_DEL. +; The calling function has to look at the following character to determine +; if the file type is actually CBM_T_DIR. +; +; unsigned char __fastcall__ _cbm_filetype (unsigned char c); + + .global __cbm_filetype + + diff --git a/include/cbm.h b/include/cbm.h index 34ab106ae..d3c966755 100644 --- a/include/cbm.h +++ b/include/cbm.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2011, Ullrich von Bassewitz */ +/* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -116,7 +116,7 @@ extern char _filetype; /* Defaults to 'u' */ #define CH_LIRA 92 #define CH_ESC 27 - + /*****************************************************************************/ /* Definitions for directory reading functions */ @@ -149,6 +149,14 @@ struct cbm_dirent { unsigned char access; }; +unsigned char __fastcall__ _cbm_filetype (unsigned char c); +/* Map the start character for a file type to one of the file types above. + * Note: 'd' will always mapped to CBM_T_DEL. The calling function has to + * look at the following character to determine if the file type is actually + * CBM_T_DIR. + * This is a function used by the implementation. There is usually no need + * to call it from user code. + */ /*****************************************************************************/ diff --git a/include/dirent.h b/include/dirent.h index 7dd79c144..dc3cfc5f8 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -84,9 +84,9 @@ struct dirent { struct dirent { char d_name[16+1]; unsigned int d_off; - unsigned int d_reclen; + unsigned int d_blocks; unsigned char d_type; - + /* bsd extensions */ unsigned char d_namlen; }; diff --git a/libsrc/cbm/Makefile b/libsrc/cbm/Makefile index a811edac1..66d08522d 100644 --- a/libsrc/cbm/Makefile +++ b/libsrc/cbm/Makefile @@ -32,7 +32,8 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include C_OBJS = cbm_dir.o \ cbm_load.o \ cbm_save.o \ - opendir.o + opendir.o \ + readdir.o S_OBJS = c_acptr.o \ c_basin.o \ @@ -55,6 +56,7 @@ S_OBJS = c_acptr.o \ c_unlsn.o \ c_untlk.o \ cbm_close.o \ + cbm_ftype.o \ cbm_open.o \ cbm_read.o \ cbm_write.o \ diff --git a/libsrc/cbm/cbm_dir.c b/libsrc/cbm/cbm_dir.c index 0b97e9803..79d2c205e 100644 --- a/libsrc/cbm/cbm_dir.c +++ b/libsrc/cbm/cbm_dir.c @@ -51,13 +51,6 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d unsigned char byte, i = 0; unsigned char is_header = 0; unsigned char rv = 1; - static const unsigned char types[] = { - CBM_T_CBM, CBM_T_DEL, CBM_T_OTHER, CBM_T_OTHER, /* c d e f */ - CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, /* g h i j */ - CBM_T_OTHER, CBM_T_LNK, CBM_T_OTHER, CBM_T_OTHER, /* k l m n */ - CBM_T_OTHER, CBM_T_PRG, CBM_T_OTHER, CBM_T_REL, /* o p q r */ - CBM_T_SEQ, CBM_T_OTHER, CBM_T_USR, CBM_T_VRP /* s t u v */ - }; if (!cbm_k_chkin(lfn)) { if (!cbm_k_readst()) { @@ -135,11 +128,8 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d byte = cbm_k_basin(); } - if (byte >= 'c' && byte < 'c' + sizeof types) { - l_dirent->type = types[byte - 'c']; - } else { - l_dirent->type = CBM_T_OTHER; - } + /* Determine the file type */ + l_dirent->type = _cbm_filetype (byte); /* Notice whether it's a directory or a deleted file. */ if (cbm_k_basin() == 'i' && byte == 'd') { diff --git a/libsrc/cbm/cbm_ftype.s b/libsrc/cbm/cbm_ftype.s new file mode 100644 index 000000000..862fb72bf --- /dev/null +++ b/libsrc/cbm/cbm_ftype.s @@ -0,0 +1,71 @@ +; +; Determine the CBM file type. From cbm_dir.c by Josef Soucek. Moved into an +; assembler function by Ullrich von Bassewitz 2012-06-03 +; +; unsigned char __fastcall__ _cbm_filetype (unsigned char c); +; + + .include "cbm_ftype.inc" + + .macpack generic + + +; -------------------------------------------------------------------------- +; Table with types for a list of start characters + +.rodata +.proc TypeTable + .byte CBM_T_CBM ; c + .byte CBM_T_DEL ; d + .byte CBM_T_OTHER ; e + .byte CBM_T_OTHER ; f + .byte CBM_T_OTHER ; g + .byte CBM_T_OTHER ; h + .byte CBM_T_OTHER ; i + .byte CBM_T_OTHER ; j + .byte CBM_T_OTHER ; k + .byte CBM_T_LNK ; l + .byte CBM_T_OTHER ; m + .byte CBM_T_OTHER ; n + .byte CBM_T_OTHER ; o + .byte CBM_T_PRG ; p + .byte CBM_T_OTHER ; q + .byte CBM_T_REL ; r + .byte CBM_T_SEQ ; s + .byte CBM_T_OTHER ; t + .byte CBM_T_USR ; u + .byte CBM_T_VRP ; v +.endproc + + +; -------------------------------------------------------------------------- +; Mapper function + +.code +.proc __cbm_filetype + + ldx #0 ; Clear high byte + +; Check that the given char is in table range + + sec + sbc #'c' + bcc L1 + cmp #.sizeof (TypeTable) + bge L1 + +; Ok, load the type + + tay + lda TypeTable,y + rts + +; Out of table range, return CBM_T_OTHER + +L1: lda #CBM_T_OTHER + rts + +.endproc + + + diff --git a/libsrc/cbm/dir.h b/libsrc/cbm/dir.h index 06081a47c..d7a30518d 100644 --- a/libsrc/cbm/dir.h +++ b/libsrc/cbm/dir.h @@ -18,7 +18,7 @@ struct DIR { int fd; /* File descriptor for directory */ - unsigned offs; /* Current byte offset in directory */ + unsigned off; /* Current byte offset in directory */ char name[16+1]; /* Name passed to opendir */ }; diff --git a/libsrc/cbm/opendir.c b/libsrc/cbm/opendir.c index c3f6f1440..3f6f76e95 100644 --- a/libsrc/cbm/opendir.c +++ b/libsrc/cbm/opendir.c @@ -20,7 +20,7 @@ DIR* __fastcall__ opendir (const char*) /* Setup file name and offset */ d.name[0] = '$'; d.name[1] = '\0'; - d.offs = 0; + d.off = 0; /* Open the directory on disk for reading */ d.fd = open (d.name, O_RDONLY); diff --git a/libsrc/cbm/readdir.c b/libsrc/cbm/readdir.c new file mode 100644 index 000000000..10593e21b --- /dev/null +++ b/libsrc/cbm/readdir.c @@ -0,0 +1,131 @@ +/* + * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include "dir.h" + +#include + + +struct dirent* __fastcall__ readdir (register DIR* dir) +{ + static struct dirent entry; + register unsigned char* b; + register unsigned char i; + unsigned char count; + unsigned char j; + unsigned char s; + unsigned char buffer[0x40]; + + + /* Remember the directory offset for this entry */ + entry.d_off = dir->off; + + /* Skip the basic line-link */ + if (!_dirskip (2, dir)) { + /* errno already set */ + goto exit; + } + dir->off += 2; + + /* Read the number of blocks */ + if (read (dir->fd, &entry.d_blocks, sizeof (entry.d_blocks)) != + sizeof (entry.d_blocks)) { + goto error; + } + + /* Read the next file entry into the buffer */ + for (count = 0, b = buffer; count < sizeof (buffer); ++count, ++b) { + if (read (dir->fd, b, 1) != 1) { + /* ### Check for EOF */ + goto error; + } + if (*b == '\0') { + break; + } + } + + /* End of directory is reached if the buffer contains "blocks free". It is + * sufficient here to check for the leading 'b'. To avoid problems if we're + * called again, read until end of directory. + */ + if (count > 0 && buffer[0] == 'b') { + while (read (dir->fd, buffer, 1) == 1) ; + return 0; + } + + /* Bump the directory offset */ + dir->off += count; + + /* Parse the buffer for the filename and file type */ + i = 0; + j = 0; + s = 0; + b = buffer; + while (i < count) { + switch (s) { + + case 0: + /* Searching for start of file name */ + if (*b == '"') { + s = 1; + } + break; + + case 1: + /* Within file name */ + if (*b == '"') { + entry.d_name[j] = '\0'; + entry.d_namlen = j; + s = 2; + } else if (j < sizeof (entry.d_name) - 1) { + entry.d_name[j] = *b; + ++j; + } + break; + + case 2: + /* Searching for file type */ + if (*b != ' ') { + entry.d_type = _cbm_filetype (*b); + if (*b == 'd') { + /* May be DEL or DIR, check next char */ + s = 3; + } else { + /* Done */ + return &entry; + } + } + break; + + case 3: + /* Distinguish DEL or DIR file type entries */ + switch (*b) { + case 'e': break; + case 'i': entry.d_type = CBM_T_DIR; break; + default: entry.d_type = CBM_T_OTHER; break; + } + return &entry; + } + ++i; + ++b; + } + + /* Something went wrong - terminating quote not found */ +error: + _errno = EIO; +exit: + return 0; +} + + + -- 2.39.5