1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-20 20:29:31 +00:00

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
This commit is contained in:
uz 2012-06-02 22:56:14 +00:00
parent eab5f250ad
commit ebca2991a3
9 changed files with 254 additions and 19 deletions

33
asminc/cbm_ftype.inc Normal file
View File

@ -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

View File

@ -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.
*/
/*****************************************************************************/

View File

@ -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;
};

View File

@ -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 \

View File

@ -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') {

71
libsrc/cbm/cbm_ftype.s Normal file
View File

@ -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

View File

@ -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 */
};

View File

@ -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);

131
libsrc/cbm/readdir.c Normal file
View File

@ -0,0 +1,131 @@
/*
* Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
*/
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <cbm.h>
#include "dir.h"
#include <stdio.h>
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;
}