mirror of
https://github.com/cc65/cc65.git
synced 2024-09-29 02:55:20 +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:
parent
eab5f250ad
commit
ebca2991a3
33
asminc/cbm_ftype.inc
Normal file
33
asminc/cbm_ftype.inc
Normal 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
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2011, Ullrich von Bassewitz */
|
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@ -149,6 +149,14 @@ struct cbm_dirent {
|
|||||||
unsigned char access;
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -84,7 +84,7 @@ struct dirent {
|
|||||||
struct dirent {
|
struct dirent {
|
||||||
char d_name[16+1];
|
char d_name[16+1];
|
||||||
unsigned int d_off;
|
unsigned int d_off;
|
||||||
unsigned int d_reclen;
|
unsigned int d_blocks;
|
||||||
unsigned char d_type;
|
unsigned char d_type;
|
||||||
|
|
||||||
/* bsd extensions */
|
/* bsd extensions */
|
||||||
|
@ -32,7 +32,8 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include
|
|||||||
C_OBJS = cbm_dir.o \
|
C_OBJS = cbm_dir.o \
|
||||||
cbm_load.o \
|
cbm_load.o \
|
||||||
cbm_save.o \
|
cbm_save.o \
|
||||||
opendir.o
|
opendir.o \
|
||||||
|
readdir.o
|
||||||
|
|
||||||
S_OBJS = c_acptr.o \
|
S_OBJS = c_acptr.o \
|
||||||
c_basin.o \
|
c_basin.o \
|
||||||
@ -55,6 +56,7 @@ S_OBJS = c_acptr.o \
|
|||||||
c_unlsn.o \
|
c_unlsn.o \
|
||||||
c_untlk.o \
|
c_untlk.o \
|
||||||
cbm_close.o \
|
cbm_close.o \
|
||||||
|
cbm_ftype.o \
|
||||||
cbm_open.o \
|
cbm_open.o \
|
||||||
cbm_read.o \
|
cbm_read.o \
|
||||||
cbm_write.o \
|
cbm_write.o \
|
||||||
|
@ -51,13 +51,6 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d
|
|||||||
unsigned char byte, i = 0;
|
unsigned char byte, i = 0;
|
||||||
unsigned char is_header = 0;
|
unsigned char is_header = 0;
|
||||||
unsigned char rv = 1;
|
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_chkin(lfn)) {
|
||||||
if (!cbm_k_readst()) {
|
if (!cbm_k_readst()) {
|
||||||
@ -135,11 +128,8 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d
|
|||||||
byte = cbm_k_basin();
|
byte = cbm_k_basin();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (byte >= 'c' && byte < 'c' + sizeof types) {
|
/* Determine the file type */
|
||||||
l_dirent->type = types[byte - 'c'];
|
l_dirent->type = _cbm_filetype (byte);
|
||||||
} else {
|
|
||||||
l_dirent->type = CBM_T_OTHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notice whether it's a directory or a deleted file. */
|
/* Notice whether it's a directory or a deleted file. */
|
||||||
if (cbm_k_basin() == 'i' && byte == 'd') {
|
if (cbm_k_basin() == 'i' && byte == 'd') {
|
||||||
|
71
libsrc/cbm/cbm_ftype.s
Normal file
71
libsrc/cbm/cbm_ftype.s
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
struct DIR {
|
struct DIR {
|
||||||
int fd; /* File descriptor for directory */
|
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 */
|
char name[16+1]; /* Name passed to opendir */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ DIR* __fastcall__ opendir (const char*)
|
|||||||
/* Setup file name and offset */
|
/* Setup file name and offset */
|
||||||
d.name[0] = '$';
|
d.name[0] = '$';
|
||||||
d.name[1] = '\0';
|
d.name[1] = '\0';
|
||||||
d.offs = 0;
|
d.off = 0;
|
||||||
|
|
||||||
/* Open the directory on disk for reading */
|
/* Open the directory on disk for reading */
|
||||||
d.fd = open (d.name, O_RDONLY);
|
d.fd = open (d.name, O_RDONLY);
|
||||||
|
131
libsrc/cbm/readdir.c
Normal file
131
libsrc/cbm/readdir.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user