1
0
mirror of https://github.com/cc65/cc65.git synced 2024-10-04 18:57:06 +00:00

Merge branch 'master' into c1p

This commit is contained in:
Stephan Mühlstrasser 2013-07-24 22:37:47 +02:00
commit 5824f46244
8 changed files with 616 additions and 9 deletions

View File

@ -91,7 +91,10 @@ cont: ldy #3
jsr ldaxysp
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
sty tmp2 ; set flag for ucase_fn
.endif
jsr ucase_fn
bcc ucok1
invret: lda #<EINVAL ; file name is too long

View File

@ -15,6 +15,9 @@
.importzp tmp3
.import addysp
.import ucase_fn
.ifdef DEFAULT_DEVICE
.importzp tmp2
.endif
.endif
.export __syschdir
@ -40,6 +43,10 @@ iocbok: stx tmp4 ; remember IOCB index
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
sty tmp2 ; set flag for ucase_fn
.endif
jsr ucase_fn
bcc ucok1

View File

@ -15,6 +15,9 @@
.ifdef UCASE_FILENAME
.importzp tmp3
.import ucase_fn
.ifdef DEFAULT_DEVICE
.importzp tmp2
.endif
.endif
.export __sysmkdir
@ -46,6 +49,10 @@ iocbok: stx tmp4 ; remember IOCB index
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
sty tmp2 ; set flag for ucase_fn
.endif
jsr ucase_fn
bcc ucok1

View File

@ -12,6 +12,9 @@
.importzp tmp3
.import addysp
.import ucase_fn
.ifdef DEFAULT_DEVICE
.importzp tmp2
.endif
.endif
.export __sysremove
@ -37,6 +40,10 @@ iocbok: stx tmp4 ; remember IOCB index
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
sty tmp2 ; set flag for ucase_fn
.endif
jsr ucase_fn
bcc ucok1

185
libsrc/atari/sysrename.s Normal file
View File

@ -0,0 +1,185 @@
;
; Christian Groessler, 2013-07-24
;
; unsigned char __fastcall__ _sysrename (const char* oldname, const char* newname);
;
.include "atari.inc"
.import findfreeiocb
.importzp tmp4, sp, ptr2, ptr3
.import incsp2, subysp, addysp, popax
.ifdef UCASE_FILENAME
.importzp tmp3
.import ucase_fn
.ifdef DEFAULT_DEVICE
.importzp tmp2
.endif
.endif
.export __sysrename
.proc __sysrename
pha ; save input parameter
txa
pha
jsr findfreeiocb
beq iocbok ; we found one
pla
pla ; fix up stack
jsr incsp2
lda #TMOF ; too many open files
rts
iocbok: stx tmp4 ; remember IOCB index
pla
sta ptr2+1 ; remember newname
pla
sta ptr2 ; ditto.
jsr popax ; get oldname
ldy #0
sty sspc+1 ; initialize stack space
.ifndef UCASE_FILENAME
sta ptr3
stx ptr3+1
sty sspc
.else
; uppercase first (old) name and prepend device if needed
.ifdef DEFAULT_DEVICE
ldy #$80
sty tmp2 ; set flag for ucase_fn
.endif
jsr ucase_fn
bcc ucok1
lda #183 ; see oserror.s
rts
ucok1: sta ptr3
stx ptr3+1 ; remember pointer to uppercased old name
lda tmp3 ; # of bytes reserved on the stack
sta sspc ; remember...
; uppercase second (new) name and don't prepend device
.ifdef DEFAULT_DEVICE
ldy #0
sty tmp2 ; set flag for ucase_fn
.endif
lda ptr2
ldx ptr2+1
jsr ucase_fn
bcc ucok2
ldy tmp3 ; get size
jsr addysp ; free used space on the stack
lda #183 ; see oserror.s
rts
ucok2: sta ptr2 ; remember pointer to uppercased new name
stx ptr2+1
; update sspc -- # of bytes used on the stack
lda sspc
clc
adc tmp3
sta sspc
bcc ukok4
inc sspc+1
ukok4:
.endif
; create a string on the stack with the old filename and the new filename separated by an invalid character (space in our case)
; ptr2 - pointer to new name
; ptr3 - pointer to old name
lda #128
tay
clc
adc sspc
sta sspc
bcc L1
inc sspc+1
L1: jsr subysp ; make room on the stack
; copy old name
ldy #0
con: lda (ptr3),y
sta (sp),y
beq copyend
iny
bne con
copyend:lda #$20 ; space
sta (sp),y
iny
tya ; get current offset (beyond old name)
clc
adc sp
sta ptr3
lda sp+1
adc #0
sta ptr3+1 ; ptr3 now contains pointer to space for new filename
; copy new name
ldy #0
cnn: lda (ptr2),y
sta (ptr3),y
beq copend2
iny
bne cnn
copend2:ldx tmp4
lda sp
sta ICBAL,x
lda sp+1
sta ICBAH,x
lda #RENAME
sta ICCOM,x
lda #0
sta ICAX1,x
sta ICAX2,x
sta ICBLL,x
sta ICBLH,x
jsr CIOV
tya
pha
; clean up stack
lda sp
clc
adc sspc
sta sp
lda sp+1
adc sspc+1
sta sp+1
; handle status
pla
tay
bmi cioerr
lda #0
rts
cioerr: tya
rts
.endproc ; __sysrename
.bss
sspc: .res 2 ; stack space used

View File

@ -12,12 +12,17 @@
.export __sysrmdir
.import __sysremove
.import __dos_type
.import ucase_fn
.import findfreeiocb
.importzp tmp4
.ifdef UCASE_FILENAME
.import ucase_fn
.import addysp
.importzp sreg
.importzp tmp3
.importzp tmp4
.ifdef DEFAULT_DEVICE
.importzp tmp2
.endif
.endif
.proc __sysrmdir
@ -53,6 +58,10 @@ do_sparta:
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
sty tmp2 ; set flag for ucase_fn
.endif
jsr ucase_fn
bcc ucok1

View File

@ -7,6 +7,8 @@
;
; Calling parameters:
; AX - points to filename
; tmp2 - 0/$80 for don't/do prepend default device if no device
; is present in the passed string (only .ifdef DEFAULT_DEVICE)
; Return parameters:
; C - 0/1 for OK/Error (filename too long)
; AX - points to uppercased version of the filename on the stack
@ -38,15 +40,16 @@
stx ptr4+1
.ifdef DEFAULT_DEVICE
; bit #0 of tmp2 is used as a flag whether device name is present in passed string (1 = present, 0 = not present)
ldy #1
sty tmp2 ; initialize flag: device present in passed string
inc tmp2 ; initialize flag: device present
lda #':'
cmp (ptr4),y
beq hasdev
iny
cmp (ptr4),y
beq hasdev
sta tmp2 ; set flag: no device in passed string
dec tmp2 ; set flag: no device in passed string
hasdev:
.endif
@ -54,7 +57,7 @@ hasdev:
sty tmp3 ; save size
jsr subysp ; make room on the stack
; copy filename to the temp. place on the stack, also uppercasing it
; copy filename to the temp. place on the stack, while uppercasing it
ldy #0
loop2: lda (ptr4),y
@ -77,9 +80,10 @@ L1:
copy_end:
.ifdef DEFAULT_DEVICE
lda tmp2
cmp #1 ; was device present in passed string?
beq hasdev2 ; yes, don't prepend something
lda #1
bit tmp2
bne hasdev2 ; yes, don't prepend something
bpl hasdev2
ldy #128+3 ; no, prepend "D:" (or other device)
sty tmp3 ; adjust stack size used

385
testcode/lib/tinyshell.c Normal file
View File

@ -0,0 +1,385 @@
/*
* Simple ("tiny") shell to test filename and directory functions.
* Copyright (c) 2013, Christian Groessler, chris@groessler.org
*/
#define VERSION_ASC "0.90"
#define KEYB_BUFSZ 80
#define PROMPT ">>> "
#ifdef __ATARI__
#define UPPERCASE /* define (e.g. for Atari) to convert filenames etc. to upper case */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#ifndef __CC65__
#include <sys/stat.h>
#include <sys/param.h>
#else
#define MAXPATHLEN 64
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#define CMD_NOTHING 0
#define CMD_INVALID 1
#define CMD_HELP 2
#define CMD_QUIT 3
#define CMD_LS 4
#define CMD_MKDIR 5
#define CMD_RMDIR 6
#define CMD_CHDIR 7
#define CMD_RM 8
#define CMD_RENAME 9
#define CMD_COPY 10
#define CMD_PWD 11
static unsigned char terminate;
static unsigned char cmd;
static unsigned char *cmd_asc, *arg1, *arg2, *arg3;
static unsigned char keyb_buf[KEYB_BUFSZ];
static size_t cpbuf_sz = 4096;
struct cmd_table {
unsigned char *name;
unsigned char code;
} cmd_table[] = {
{ "help", CMD_HELP },
{ "quit", CMD_QUIT },
{ "q", CMD_QUIT },
{ "exit", CMD_QUIT },
{ "ls", CMD_LS },
{ "dir", CMD_LS },
{ "md", CMD_MKDIR },
{ "mkdir", CMD_MKDIR },
{ "rd", CMD_RMDIR },
{ "rmdir", CMD_RMDIR },
{ "cd", CMD_CHDIR },
{ "chdir", CMD_CHDIR },
{ "rm", CMD_RM },
{ "del", CMD_RM },
{ "cp", CMD_COPY },
{ "copy", CMD_COPY },
{ "mv", CMD_RENAME },
{ "ren", CMD_RENAME },
{ "pwd", CMD_PWD },
{ NULL, 0 }
};
static void banner(void)
{
puts("\"tiny\" command line shell, v" VERSION_ASC);
puts("written by chris@groessler.org");
puts("type 'help' for help\n");
}
static void get_command(void)
{
unsigned char i = 0;
arg1 = arg2 = arg3 = NULL;
/* issue prompt */
printf(PROMPT);
/* get input from the user */
if (! fgets(keyb_buf, KEYB_BUFSZ, stdin)) {
puts("");
cmd = CMD_QUIT;
return;
}
/* split input into cmd, arg1, arg2, arg3 */
/* get and parse command */
cmd_asc = strtok(keyb_buf, " \t\n");
if (! cmd_asc) {
cmd = CMD_NOTHING;
return;
}
cmd = CMD_INVALID;
while (cmd_table[i].name) {
if (! strcmp(cmd_table[i].name, cmd_asc)) {
cmd = cmd_table[i].code;
break;
}
i++;
}
/* get arguments */
arg1 = strtok(NULL, " \t\n");
if (! arg1)
return;
arg2 = strtok(NULL, " \t\n");
if (! arg2)
return;
arg3 = strtok(NULL, " \t\n");
}
static void cmd_help(void)
{
puts("quit, exit - exit shell");
puts("ls, dir - display current directory");
puts(" and drive contents");
puts("rm, del - delete file");
puts("cp, copy - copy file");
puts("mv, ren - rename file");
puts("cd, chdir - change directory or drive");
puts("md, mkdir - make directory or drive");
puts("rd, rmdir - remove directory or drive");
puts("sorry, you cannot start programs here");
}
static void cmd_ls(void)
{
DIR *dir;
unsigned char *arg;
struct dirent *dirent;
#ifdef __ATARI__
char need_free = 0;
#endif
if (arg2) {
puts("usage: ls [dir]");
return;
}
/* print directory listing */
if (arg1) {
#ifdef UPPERCASE
strupr(arg1);
#endif
#ifdef __ATARI__
/* not sure if this shouldn't be done by the runtime lib */
if (*(arg1 + strlen(arg1) - 1) == ':' || *(arg1 + strlen(arg1) - 1) == '>') {
arg = malloc(strlen(arg1) + 4);
if (! arg) {
printf("malloc failed: %s", strerror(errno));
return;
}
need_free = 1;
memcpy(arg, arg1, strlen(arg1) + 1);
strcat(arg, "*.*");
}
else
#endif
arg = arg1;
}
else
arg = ".";
dir = opendir(arg);
#ifdef __ATARI__
if (need_free) free(arg);
#endif
if (! dir) {
puts("opendir failed");
return;
}
while (dirent = readdir(dir))
puts(dirent->d_name);
closedir(dir);
}
static void cmd_rm(void)
{
if (!arg1 || arg2) {
puts("usage: rm <file>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (unlink(arg1))
printf("remove failed: %s\n", strerror(errno));
}
static void cmd_mkdir(void)
{
if (!arg1 || arg2) {
puts("usage: mkdir <dir>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (mkdir(arg1, 0777))
printf("mkdir failed: %s\n", strerror(errno));
}
static void cmd_rmdir(void)
{
if (!arg1 || arg2) {
puts("usage: rmdir <dir>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (rmdir(arg1))
printf("rmdir failed: %s\n", strerror(errno));
}
static void cmd_chdir(void)
{
if (!arg1 || arg2) {
puts("usage: cddir <dir>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (chdir(arg1))
printf("chdir failed: %s\n", strerror(errno));
}
static void cmd_pwd(void)
{
char *buf;
if (arg1) {
puts("usage: pwd");
return;
}
buf = malloc(MAXPATHLEN);
if (! buf) {
printf("malloc %u bytes failed: %s\n", MAXPATHLEN, strerror(errno));
return;
}
if (!getcwd(buf, MAXPATHLEN)) {
printf("getcwd failed: %s\n", strerror(errno));
free(buf);
return;
}
puts(buf);
free(buf);
}
static void cmd_rename(void)
{
if (!arg2 || arg3) {
puts("usage: mv <oldname> <newname>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
strupr(arg2);
#endif
if (rename(arg1, arg2))
printf("rename failed: %s\n", strerror(errno));
}
static void cmd_copy(void)
{
int srcfd = -1, dstfd = -1;
unsigned char *buf;
int readsz, writesz;
if (!arg2 || arg3) {
puts("usage: cp <src> <dest>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
strupr(arg2);
#endif
buf = malloc(cpbuf_sz);
if (! buf) {
printf("malloc %u bytes failed: %s\n", cpbuf_sz, strerror(errno));
return;
}
while (1) {
if (srcfd == -1) {
srcfd = open(arg1, O_RDONLY);
if (srcfd < 0) {
printf("open(%s) failed: %s\n", arg1, strerror(errno));
break;
}
}
readsz = read(srcfd, buf, cpbuf_sz);
if (readsz < 0) {
printf("read error: %s\n", strerror(errno));
break;
}
if (! readsz)
break;
if (dstfd == -1) {
dstfd = open(arg2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (dstfd < 0) {
printf("open(%s) failed: %s\n", arg2, strerror(errno));
break;
}
}
writesz = write(dstfd, buf, readsz);
if (writesz < 0 || writesz != readsz) {
printf("write error: %s\n", strerror(errno));
break;
}
if (readsz != cpbuf_sz)
break;
}
free(buf);
if (srcfd >= 0) close(srcfd);
if (dstfd >= 0) close(dstfd);
}
static void run_command(void)
{
switch (cmd) {
default: puts("internal error"); return;
case CMD_NOTHING: return;
case CMD_INVALID: puts("invalid command"); return;
case CMD_HELP: cmd_help(); return;
case CMD_QUIT: terminate = 1; return;
case CMD_LS: cmd_ls(); return;
case CMD_RM: cmd_rm(); return;
case CMD_CHDIR: cmd_chdir(); return;
case CMD_MKDIR: cmd_mkdir(); return;
case CMD_RMDIR: cmd_rmdir(); return;
case CMD_PWD: cmd_pwd(); return;
case CMD_RENAME: cmd_rename(); return;
case CMD_COPY: cmd_copy(); return;
}
}
int main(void)
{
banner();
while (! terminate) {
get_command();
run_command();
}
return 0;
}
/* Local Variables: */
/* c-file-style: "cpg" */
/* c-basic-offset: 4 */
/* End: */