This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches. git-svn-id: svn://svn.cc65.org/cc65/trunk@3 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
40
libsrc/common/.cvsignore
Normal file
40
libsrc/common/.cvsignore
Normal file
@@ -0,0 +1,40 @@
|
||||
fclose.s
|
||||
fgets.s
|
||||
fprintf.s
|
||||
strdup.s
|
||||
calloc.s
|
||||
_fopen.s
|
||||
fputs.s
|
||||
fread.s
|
||||
fwrite.s
|
||||
gets.s
|
||||
realloc.s
|
||||
bsearch.s
|
||||
printf.s
|
||||
_hextab.s
|
||||
malloc.s
|
||||
free.s
|
||||
vfprintf.s
|
||||
fdopen.s
|
||||
_afailed.s
|
||||
fopen.s
|
||||
fgetc.s
|
||||
fputc.s
|
||||
puts.s
|
||||
_printf.s
|
||||
vprintf.s
|
||||
vsprintf.s
|
||||
sprintf.s
|
||||
abort.s
|
||||
errormsg.s
|
||||
_hadd.s
|
||||
cprintf.s
|
||||
vcprintf.s
|
||||
freopen.s
|
||||
perror.s
|
||||
qsort.s
|
||||
strxfrm.s
|
||||
strtok.s
|
||||
locale.s
|
||||
putchar.s
|
||||
getchar.s
|
||||
39
libsrc/common/Makefile
Normal file
39
libsrc/common/Makefile
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# makefile for CC65 runtime library
|
||||
#
|
||||
|
||||
.SUFFIXES: .o .s .c
|
||||
|
||||
%.o: %.c
|
||||
@echo $<
|
||||
@$(CC) $(CFLAGS) $<
|
||||
@$(AS) -g -o $@ $(AFLAGS) $(*).s
|
||||
|
||||
%.o: %.s
|
||||
@echo $<
|
||||
@$(AS) -g -o $@ $(AFLAGS) $<
|
||||
|
||||
C_OBJS = fclose.o fgets.o fprintf.o strdup.o calloc.o _fopen.o\
|
||||
fputs.o fread.o fwrite.o gets.o realloc.o bsearch.o strxfrm.o\
|
||||
printf.o _hextab.o malloc.o free.o vfprintf.o fdopen.o strtok.o\
|
||||
_afailed.o fopen.o fgetc.o fputc.o puts.o gets.o perror.o getchar.o\
|
||||
_printf.o vprintf.o vsprintf.o sprintf.o abort.o qsort.o putchar.o\
|
||||
errormsg.o _hadd.o cprintf.o vcprintf.o freopen.o locale.o
|
||||
|
||||
S_OBJS = isalpha.o isdigit.o _file.o fmisc.o strlower.o strchr.o tolower.o\
|
||||
toupper.o errno.o strcpy.o strlen.o strcat.o strcmp.o itoa.o\
|
||||
strupper.o isalpha.o isalnum.o isgraph.o islower.o isupper.o\
|
||||
isprint.o ispunct.o isspace.o isxdigit.o isblank.o strrchr.o\
|
||||
_stksize.o _heap.o stricmp.o strncmp.o strncpy.o atoi.o setjmp.o\
|
||||
longjmp.o rand.o atexit.o memset.o memcpy.o memchr.o memcmp.o\
|
||||
ltoa.o strcspn.o strncat.o strpbrk.o strspn.o abs.o labs.o jmpvec.o\
|
||||
_fdesc.o stkcheck.o zerobss.o copydata.o _swap.o strstr.o strcoll.o\
|
||||
_sys.o getcpu.o _oserror.o strerror.o
|
||||
|
||||
all: $(C_OBJS) $(S_OBJS)
|
||||
|
||||
clean:
|
||||
@rm -f *~
|
||||
@rm -f $(C_OBJS:.o=.s)
|
||||
@rm -f $(C_OBJS)
|
||||
@rm -f $(S_OBJS)
|
||||
21
libsrc/common/_afailed.c
Normal file
21
libsrc/common/_afailed.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* _afailed.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 06.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
void _afailed (char* file, unsigned line)
|
||||
{
|
||||
fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line);
|
||||
exit (2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
39
libsrc/common/_fdesc.s
Normal file
39
libsrc/common/_fdesc.s
Normal file
@@ -0,0 +1,39 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 17.06.1998
|
||||
;
|
||||
; int _fdesc (void);
|
||||
; /* Find a free descriptor slot */
|
||||
|
||||
|
||||
.export __fdesc
|
||||
.import return0, __filetab
|
||||
.importzp tmp1
|
||||
|
||||
__fdesc:
|
||||
ldy #0
|
||||
L1: lda __filetab+1,y ; load flags
|
||||
beq L2 ; jump if empty (== CLOSED)
|
||||
iny
|
||||
iny
|
||||
cpy #16 ; Done?
|
||||
bne L1
|
||||
|
||||
; File table is full
|
||||
|
||||
jmp return0
|
||||
|
||||
; Free slot found
|
||||
|
||||
L2: sty tmp1 ; Offset
|
||||
lda #<__filetab
|
||||
ldx #>__filetab
|
||||
clc
|
||||
adc tmp1
|
||||
tay
|
||||
txa
|
||||
adc #0
|
||||
tax
|
||||
tya
|
||||
rts
|
||||
|
||||
|
||||
48
libsrc/common/_file.h
Normal file
48
libsrc/common/_file.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* _file.h
|
||||
*
|
||||
* Ullrich von Bassewitz, 02.06.1998
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __FILE_H
|
||||
#define __FILE_H
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/* Definition of struct _FILE */
|
||||
struct _FILE {
|
||||
char f_fd;
|
||||
char f_flags;
|
||||
};
|
||||
|
||||
/* File table. Beware: FOPEN_MAX is hardcoded in the ASM files! */
|
||||
extern FILE _filetab [FOPEN_MAX];
|
||||
|
||||
/* Flags field */
|
||||
#define _FCLOSED 0x00
|
||||
#define _FOPEN 0x01
|
||||
#define _FEOF 0x02
|
||||
#define _FERROR 0x04
|
||||
|
||||
|
||||
|
||||
FILE* _fopen (const char* name, const char* mode, FILE* f);
|
||||
/* Open the specified file and fill the descriptor values into f */
|
||||
|
||||
FILE* _fdesc (void);
|
||||
/* Find a free FILE descriptor */
|
||||
|
||||
|
||||
|
||||
/* End of _file.h */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
28
libsrc/common/_file.s
Normal file
28
libsrc/common/_file.s
Normal file
@@ -0,0 +1,28 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; Data for the stdio file stream.
|
||||
;
|
||||
|
||||
.export __filetab, _stdin, _stdout, _stderr
|
||||
|
||||
.data
|
||||
|
||||
__filetab:
|
||||
in: .byte 0, 1 ; stdin
|
||||
out: .byte 1, 1 ; stdout
|
||||
err: .byte 2, 1 ; stderr
|
||||
.byte 0, 0 ; free slot
|
||||
.byte 0, 0 ; free slot
|
||||
.byte 0, 0 ; free slot
|
||||
.byte 0, 0 ; free slot
|
||||
.byte 0, 0 ; free slot
|
||||
|
||||
_stdin:
|
||||
.word in
|
||||
|
||||
_stdout:
|
||||
.word out
|
||||
|
||||
_stderr:
|
||||
.word err
|
||||
73
libsrc/common/_fopen.c
Normal file
73
libsrc/common/_fopen.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* _fopen.c
|
||||
*
|
||||
* Ullrich von bassewitz, 17.06.1997
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
static unsigned char amode_to_bmode (const char* mode)
|
||||
/* Convert ASCII mode (like for fopen) to binary mode (for open) */
|
||||
{
|
||||
char c;
|
||||
char flag = 0;
|
||||
unsigned char binmode = 0;
|
||||
|
||||
while (c = *mode++) {
|
||||
switch(c) {
|
||||
case 'w':
|
||||
binmode = O_WRONLY;
|
||||
break;
|
||||
case 'r':
|
||||
binmode = O_RDONLY;
|
||||
break;
|
||||
case '+':
|
||||
binmode = O_RDWR;
|
||||
break;
|
||||
/* a,b missing */
|
||||
}
|
||||
}
|
||||
if (binmode == 0) {
|
||||
_errno = EINVAL;
|
||||
}
|
||||
return binmode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FILE* _fopen (const char* name, const char* mode, FILE* f)
|
||||
/* Open the specified file and fill the descriptor values into f */
|
||||
{
|
||||
int fd;
|
||||
unsigned char binmode;
|
||||
|
||||
|
||||
/* Convert ASCII mode to binary mode */
|
||||
if ((binmode = amode_to_bmode (mode)) == 0) {
|
||||
/* Invalid mode, _errno already set */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
fd = open (name, binmode);
|
||||
if (fd == -1) {
|
||||
/* Error - _oserror is set */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remember fd, mark the file as opened */
|
||||
f->f_fd = fd;
|
||||
f->f_flags = _FOPEN;
|
||||
|
||||
/* Return the file descriptor */
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
106
libsrc/common/_hadd.c
Normal file
106
libsrc/common/_hadd.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* _hadd.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 19.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include "_heap.h"
|
||||
|
||||
|
||||
|
||||
void _hadd (void* mem, size_t size)
|
||||
/* Add an arbitrary memory block to the heap. This function is used by
|
||||
* free(), but it does also allow usage of otherwise unused memory
|
||||
* blocks as heap space. The given block is entered in the free list
|
||||
* without any checks, so beware!
|
||||
*/
|
||||
{
|
||||
struct freeblock* f;
|
||||
struct freeblock* left;
|
||||
struct freeblock* right;
|
||||
|
||||
if (size >= sizeof (struct freeblock)) {
|
||||
|
||||
/* Set the admin data */
|
||||
f = (struct freeblock*) mem;
|
||||
f->size = size;
|
||||
|
||||
/* Check if the freelist is empty */
|
||||
if (_hfirst == 0) {
|
||||
|
||||
/* The freelist is empty until now, insert the block */
|
||||
f->prev = 0;
|
||||
f->next = 0;
|
||||
_hfirst = f;
|
||||
_hlast = f;
|
||||
|
||||
} else {
|
||||
|
||||
/* We have to search the free list. As we are doing so, we check
|
||||
* if it is possible to combine this block with another already
|
||||
* existing block. Beware: The block may be the "missing link"
|
||||
* between *two* other blocks.
|
||||
*/
|
||||
left = 0;
|
||||
right = _hfirst;
|
||||
while (right && f > right) {
|
||||
left = right;
|
||||
right = right->next;
|
||||
}
|
||||
|
||||
|
||||
/* Ok, the current block must be inserted between left and right (but
|
||||
* beware: one of the two may be zero!). Also check for the condition
|
||||
* that we have to merge two or three blocks.
|
||||
*/
|
||||
if (right) {
|
||||
/* Check if we must merge the block with the right one */
|
||||
if (((int) f) + size == (int) right) {
|
||||
/* Merge with the right block */
|
||||
f->size += right->size;
|
||||
if (f->next = right->next) {
|
||||
f->next->prev = f;
|
||||
} else {
|
||||
/* This is now the last block */
|
||||
_hlast = f;
|
||||
}
|
||||
} else {
|
||||
/* No merge, just set the link */
|
||||
f->next = right;
|
||||
right->prev = f;
|
||||
}
|
||||
} else {
|
||||
f->next = 0;
|
||||
/* Special case: This is the new freelist end */
|
||||
_hlast = f;
|
||||
}
|
||||
if (left) {
|
||||
/* Check if we must merge the block with the left one */
|
||||
if ((int) f == ((int) left) + left->size) {
|
||||
/* Merge with the left block */
|
||||
left->size += f->size;
|
||||
if (left->next = f->next) {
|
||||
left->next->prev = left;
|
||||
} else {
|
||||
/* This is now the last block */
|
||||
_hlast = left;
|
||||
}
|
||||
} else {
|
||||
/* No merge, just set the link */
|
||||
left->next = f;
|
||||
f->prev = left;
|
||||
}
|
||||
} else {
|
||||
f->prev = 0;
|
||||
/* Special case: This is the new freelist start */
|
||||
_hfirst = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
43
libsrc/common/_heap.h
Normal file
43
libsrc/common/_heap.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* _heap.h
|
||||
*
|
||||
* Ullrich von Bassewitz, 03.06.1998
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __HEAP_H
|
||||
#define __HEAP_H
|
||||
|
||||
|
||||
|
||||
/* Space needed for administering used blocks */
|
||||
#define HEAP_ADMIN_SPACE sizeof (unsigned)
|
||||
|
||||
/* The data type used to implement the free list.
|
||||
* Beware: Field order is significant!
|
||||
*/
|
||||
struct freeblock {
|
||||
unsigned size;
|
||||
struct freeblock* next;
|
||||
struct freeblock* prev;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Variables that describe the heap */
|
||||
extern unsigned* _horg; /* Bottom of heap */
|
||||
extern unsigned* _hptr; /* Current top */
|
||||
extern unsigned* _hend; /* Upper limit */
|
||||
extern struct freeblock* _hfirst; /* First free block in list */
|
||||
extern struct freeblock* _hlast; /* Last free block in list */
|
||||
|
||||
|
||||
|
||||
/* End of _heap.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
45
libsrc/common/_heap.s
Normal file
45
libsrc/common/_heap.s
Normal file
@@ -0,0 +1,45 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 03.06.1998
|
||||
;
|
||||
; Heap variables and initialization.
|
||||
;
|
||||
|
||||
.export __horg, __hptr, __hend, __hfirst, __hlast
|
||||
.export __hinit
|
||||
.import __BSS_RUN__, __BSS_SIZE__, __stksize
|
||||
.importzp sp
|
||||
|
||||
.data
|
||||
|
||||
__horg:
|
||||
.word __BSS_RUN__+__BSS_SIZE__ ; Linker calculates this symbol
|
||||
__hptr:
|
||||
.word __BSS_RUN__+__BSS_SIZE__ ; Dito
|
||||
__hend:
|
||||
.word __BSS_RUN__+__BSS_SIZE__
|
||||
__hfirst:
|
||||
.word 0
|
||||
__hlast:
|
||||
.word 0
|
||||
|
||||
|
||||
;
|
||||
; Initialization. Must be called from startup!
|
||||
;
|
||||
|
||||
.code
|
||||
|
||||
__hinit:
|
||||
sec
|
||||
lda sp
|
||||
sbc __stksize
|
||||
sta __hend
|
||||
lda sp+1
|
||||
sbc __stksize+1
|
||||
sta __hend+1
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
18
libsrc/common/_hextab.c
Normal file
18
libsrc/common/_hextab.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*
|
||||
* Hex conversion table. Must be in C since the compiler will convert
|
||||
* to the correct character set for the target platform.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Data in this module is read-only, put it into the RODATA segment */
|
||||
#pragma dataseg ("RODATA")
|
||||
|
||||
const unsigned char _hextab [16] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
|
||||
14
libsrc/common/_oserror.s
Normal file
14
libsrc/common/_oserror.s
Normal file
@@ -0,0 +1,14 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 16.05.2000
|
||||
;
|
||||
; extern unsigned char _oserror;
|
||||
; /* Operating system specific errors from the low level functions */
|
||||
|
||||
|
||||
.export __oserror
|
||||
|
||||
.bss
|
||||
|
||||
__oserror:
|
||||
.res 1
|
||||
|
||||
253
libsrc/common/_printf.c
Normal file
253
libsrc/common/_printf.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Helper function for the printf family.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "_printf.h"
|
||||
|
||||
|
||||
|
||||
/* Use static variables for locals */
|
||||
#pragma staticlocals (1);
|
||||
|
||||
|
||||
|
||||
int _printf (struct outdesc* d, char* f, va_list ap)
|
||||
{
|
||||
outfunc fout; /* Output function */
|
||||
unsigned char type; /* variable argument type */
|
||||
char str [20]; /* string buffer */
|
||||
char c; /* Current format char */
|
||||
char leftjust; /* left justify string */
|
||||
char addsign; /* always add + or - */
|
||||
char addblank; /* add blank instead of + */
|
||||
char altform; /* alternate form? */
|
||||
char padchar; /* pad with space or zeroes? */
|
||||
char islong; /* l modifier found */
|
||||
unsigned arglen; /* length of argument string */
|
||||
unsigned prec; /* Precision */
|
||||
unsigned width; /* Width of output field */
|
||||
int i; /* Integer value */
|
||||
long l; /* Long value */
|
||||
char* sptr; /* pointer to argument string */
|
||||
register char* s; /* work pointer to argument string */
|
||||
|
||||
/* Remember the format string in a register variable for shorter code */
|
||||
register char* format = f;
|
||||
|
||||
/* Remember the output function in a local variable for speed and size */
|
||||
fout = d->fout;
|
||||
|
||||
/* */
|
||||
d->ccount = 0;
|
||||
while (c = *format++) {
|
||||
|
||||
if (c != '%') {
|
||||
fout (d, &c, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* %%? */
|
||||
if (*format == '%') {
|
||||
fout (d, format, 1);
|
||||
++format;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* format is: %[flags][width][.precision][mod]type */
|
||||
|
||||
/* flags */
|
||||
leftjust = addsign = addblank = altform = 0;
|
||||
do {
|
||||
switch (c = *format) {
|
||||
|
||||
case '-':
|
||||
leftjust = 1;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
addsign = 1;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
altform = 1;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
addblank = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto flags_done;
|
||||
|
||||
}
|
||||
++format;
|
||||
} while (1);
|
||||
flags_done:
|
||||
|
||||
/* width */
|
||||
padchar = ' ';
|
||||
if (*format == '0') {
|
||||
padchar = '0';
|
||||
++format;
|
||||
}
|
||||
if (*format == '*') {
|
||||
width = va_arg (ap, int);
|
||||
++format;
|
||||
} else {
|
||||
width = 0;
|
||||
while (isdigit (c = *format)) {
|
||||
width = width * 10 + (c - '0');
|
||||
++format;
|
||||
}
|
||||
}
|
||||
|
||||
/* precision */
|
||||
prec = 0;
|
||||
if (*format == '.') {
|
||||
++format;
|
||||
if (*format == '*') {
|
||||
prec = va_arg (ap, int);
|
||||
++format;
|
||||
} else {
|
||||
while (isdigit (c = *format)) {
|
||||
prec = prec * 10 + (c - '0');
|
||||
++format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* modifiers */
|
||||
islong = 0;
|
||||
while (strchr ("FNhlL", c = *format)) {
|
||||
switch (c) {
|
||||
|
||||
case 'l':
|
||||
islong = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
++format;
|
||||
}
|
||||
|
||||
/* Check the format specifier */
|
||||
sptr = s = str;
|
||||
type = *format++;
|
||||
switch (type) {
|
||||
|
||||
case 'c':
|
||||
str [0] = va_arg (ap, char);
|
||||
str [1] = 0;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
if (addsign) {
|
||||
*s++ = '+';
|
||||
} else if (addblank) {
|
||||
*s++ = ' ';
|
||||
}
|
||||
if (islong) {
|
||||
ltoa (va_arg (ap, long), s, 10);
|
||||
} else {
|
||||
itoa (va_arg (ap, int), s, 10);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
*va_arg (ap, int*) = d->ccount;
|
||||
continue;
|
||||
|
||||
case 'o':
|
||||
if (islong) {
|
||||
l = va_arg (ap, unsigned long);
|
||||
if (altform && (l || prec)) {
|
||||
*s++ = '0';
|
||||
}
|
||||
ultoa (l, s, 8);
|
||||
} else {
|
||||
i = va_arg (ap, unsigned);
|
||||
if (altform && (i || prec)) {
|
||||
*s++ = '0';
|
||||
}
|
||||
utoa (i, s, 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
sptr = va_arg (ap, char*);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (islong) {
|
||||
ultoa (va_arg (ap, unsigned long), str, 10);
|
||||
} else {
|
||||
utoa (va_arg (ap, unsigned), str, 10);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (altform) {
|
||||
*s++ = '0';
|
||||
*s++ = 'X';
|
||||
}
|
||||
if (islong) {
|
||||
ultoa (va_arg (ap, unsigned long), s, 16);
|
||||
} else {
|
||||
utoa (va_arg (ap, unsigned), s, 16);
|
||||
}
|
||||
if (type == 'x') {
|
||||
strlower (str);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown type char - skip it */
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Do argument string formatting */
|
||||
arglen = strlen (sptr);
|
||||
if (prec && prec < arglen) {
|
||||
arglen = prec;
|
||||
}
|
||||
if (width > arglen) {
|
||||
width -= arglen; /* padcount */
|
||||
} else {
|
||||
width = 0;
|
||||
}
|
||||
|
||||
/* Do padding on the left side if needed */
|
||||
if (!leftjust) {
|
||||
/* argument right justified */
|
||||
while (width) {
|
||||
fout (d, &padchar, 1);
|
||||
--width;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the argument string */
|
||||
fout (d, sptr, arglen);
|
||||
|
||||
/* Output right padding bytes if needed */
|
||||
if (leftjust) {
|
||||
/* argument left justified */
|
||||
while (width) {
|
||||
fout (d, &padchar, 1);
|
||||
--width;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
41
libsrc/common/_printf.h
Normal file
41
libsrc/common/_printf.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* _printf.h
|
||||
*
|
||||
* (C) Copyright 1998 Ullrich von Bassewitz (uz@ibb.schwaben.com)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __PRINTF_H
|
||||
#define __PRINTF_H
|
||||
|
||||
|
||||
|
||||
/* Forward */
|
||||
struct outdesc;
|
||||
|
||||
/* Type of the function that is called to output data */
|
||||
typedef void (*outfunc) (struct outdesc* desc, char* buf, unsigned count);
|
||||
|
||||
|
||||
|
||||
struct outdesc {
|
||||
outfunc fout; /* Routine used to output data */
|
||||
int ccount; /* Character counter */
|
||||
void* ptr; /* Data internal to print routine */
|
||||
unsigned uns; /* Data internal to print routine */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Internal formatting routine */
|
||||
int _printf (struct outdesc* d, char* format, va_list ap);
|
||||
|
||||
|
||||
|
||||
/* End of _printf.h */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
15
libsrc/common/_stksize.s
Normal file
15
libsrc/common/_stksize.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 03.06.1998
|
||||
;
|
||||
; Stack default size definition
|
||||
;
|
||||
|
||||
.export __stksize
|
||||
|
||||
.data
|
||||
|
||||
__stksize:
|
||||
.word $800 ; 2K
|
||||
|
||||
|
||||
|
||||
62
libsrc/common/_swap.s
Normal file
62
libsrc/common/_swap.s
Normal file
@@ -0,0 +1,62 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 09.12.1998
|
||||
;
|
||||
; void __fastcall__ _swap (void* p, void* q, size_t size);
|
||||
;
|
||||
|
||||
.export __swap
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
|
||||
__swap: sta ptr3 ; Save size
|
||||
stx ptr3+1
|
||||
|
||||
jsr popax ; Get q
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
|
||||
jsr popax ; Get p
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
; Prepare for swap
|
||||
|
||||
ldy #$00
|
||||
|
||||
; Swap 256 byte blocks
|
||||
|
||||
ldx ptr3+1
|
||||
beq @L2
|
||||
|
||||
@L1: lda (ptr1),y
|
||||
tax
|
||||
lda (ptr2),y
|
||||
sta (ptr1),y
|
||||
txa
|
||||
sta (ptr2),y
|
||||
iny
|
||||
bne @L1
|
||||
dec ptr3+1
|
||||
bne @L1
|
||||
|
||||
; Swap remaining bytes (Y is zero)
|
||||
|
||||
@L2: ldx ptr3
|
||||
beq @L9
|
||||
|
||||
@L3: lda (ptr1),y
|
||||
tax
|
||||
lda (ptr2),y
|
||||
sta (ptr1),y
|
||||
txa
|
||||
sta (ptr2),y
|
||||
iny
|
||||
dec ptr3
|
||||
bne @L3
|
||||
|
||||
; Done
|
||||
|
||||
@L9: rts
|
||||
|
||||
|
||||
72
libsrc/common/_sys.s
Normal file
72
libsrc/common/_sys.s
Normal file
@@ -0,0 +1,72 @@
|
||||
;
|
||||
; void __fastcall__ _sys (struct regs* r);
|
||||
;
|
||||
; Ullrich von Bassewitz, 16.12.1998
|
||||
;
|
||||
|
||||
.export __sys
|
||||
.import jmpvec
|
||||
.importzp ptr1
|
||||
|
||||
|
||||
__sys: sta ptr1
|
||||
stx ptr1+1 ; Save the pointer to r
|
||||
|
||||
; Fetch the PC and store it into the jump vector
|
||||
|
||||
ldy #5
|
||||
lda (ptr1),y
|
||||
sta jmpvec+2
|
||||
dey
|
||||
lda (ptr1),y
|
||||
sta jmpvec+1
|
||||
|
||||
; Get the flags, mask unnecessary bits and push them. Push a
|
||||
|
||||
dey
|
||||
lda (ptr1),y
|
||||
and #%11001011
|
||||
pha
|
||||
ldy #0
|
||||
lda (ptr1),y
|
||||
pha
|
||||
|
||||
; Get and assign X and Y
|
||||
|
||||
iny
|
||||
lda (ptr1),y
|
||||
tay
|
||||
iny
|
||||
lda (ptr1),y
|
||||
tay
|
||||
|
||||
; Set a and the flags, call the machine code routine
|
||||
|
||||
pla
|
||||
plp
|
||||
jsr jmpvec
|
||||
|
||||
; Back from the routine. Save the flags and a
|
||||
|
||||
php
|
||||
pha
|
||||
|
||||
; Put the register values into the regs structure
|
||||
|
||||
tya
|
||||
ldy #2
|
||||
sta (ptr1),y
|
||||
dey
|
||||
txa
|
||||
sta (ptr1),y
|
||||
dey
|
||||
pla
|
||||
sta (ptr1),y
|
||||
ldy #3
|
||||
pla
|
||||
sta (ptr1),y
|
||||
|
||||
; Done
|
||||
|
||||
rts
|
||||
|
||||
21
libsrc/common/abort.c
Normal file
21
libsrc/common/abort.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* abort.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 02.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
void abort (void)
|
||||
{
|
||||
fputs ("ABNORMAL PROGRAM TERMINATION\n", stderr);
|
||||
exit (3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
17
libsrc/common/abs.s
Normal file
17
libsrc/common/abs.s
Normal file
@@ -0,0 +1,17 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 17.06.1998
|
||||
;
|
||||
; int abs (int x);
|
||||
;
|
||||
|
||||
.export _abs
|
||||
.import negax
|
||||
|
||||
_abs: dex
|
||||
inx ; test hi byte
|
||||
bpl L1
|
||||
jmp negax ; Negate if negative
|
||||
L1: rts
|
||||
|
||||
|
||||
|
||||
69
libsrc/common/atexit.s
Normal file
69
libsrc/common/atexit.s
Normal file
@@ -0,0 +1,69 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 06.06.1998
|
||||
;
|
||||
; int atexit (void (*f) (void));
|
||||
;
|
||||
|
||||
; The exit functions
|
||||
|
||||
.export _atexit, doatexit
|
||||
.import __errno, jmpvec
|
||||
|
||||
.bss
|
||||
ecount: .byte 0 ; Really an index, inc'ed by 2
|
||||
efunc: .word 0,0,0,0,0 ; 5 exit functions
|
||||
maxcount = * - efunc
|
||||
|
||||
|
||||
.code
|
||||
|
||||
_atexit:
|
||||
ldy ecount
|
||||
cpy #maxcount ; slot available?
|
||||
beq E0 ; jump if no
|
||||
|
||||
; Enter the function into the table
|
||||
|
||||
sta efunc,y
|
||||
iny
|
||||
txa
|
||||
sta efunc,y
|
||||
iny
|
||||
sty ecount
|
||||
|
||||
; Done, return zero
|
||||
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
; Error, no space left
|
||||
|
||||
E0: lda #$FF
|
||||
sta __errno ; Use -1 until codes are defined ###
|
||||
sta __errno+1
|
||||
tax
|
||||
rts
|
||||
|
||||
; Function called from exit
|
||||
|
||||
doatexit:
|
||||
ldy ecount ; get index
|
||||
beq L9 ; jump if done
|
||||
dey
|
||||
lda efunc,y
|
||||
sta jmpvec+2
|
||||
dey
|
||||
lda efunc,y
|
||||
sta jmpvec+1
|
||||
sty ecount
|
||||
ldy #0 ; number of function parms
|
||||
jsr jmpvec
|
||||
jmp doatexit ; next one
|
||||
|
||||
L9: rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
156
libsrc/common/atoi.s
Normal file
156
libsrc/common/atoi.s
Normal file
@@ -0,0 +1,156 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 05.06.1998
|
||||
;
|
||||
; int atoi (const char* s);
|
||||
; long atol (const char* s);
|
||||
;
|
||||
|
||||
.export _atoi, _atol
|
||||
.import __ctype
|
||||
.importzp sreg, ptr1, ptr2, tmp1
|
||||
|
||||
;
|
||||
; Conversion routine (32 bit)
|
||||
;
|
||||
|
||||
_atoi:
|
||||
_atol: sta ptr1 ; Store s
|
||||
stx ptr1+1
|
||||
ldy #0
|
||||
sty ptr2
|
||||
sty ptr2+1 ; initial value (32 bit)
|
||||
sty sreg
|
||||
sty sreg+1
|
||||
|
||||
; Skip whitespace
|
||||
|
||||
L1: lda (ptr1),y
|
||||
tax
|
||||
lda __ctype,x ; get character classification
|
||||
and #$80 ; tab or space?
|
||||
beq L2 ; jump if no
|
||||
iny
|
||||
bne L1
|
||||
inc ptr1+1
|
||||
bne L1 ; branch always
|
||||
|
||||
; Check for a sign. The character is in X
|
||||
|
||||
L2: txa ; get char
|
||||
ldx #0 ; flag: positive
|
||||
cmp #'+' ; ### portable?
|
||||
beq L3
|
||||
cmp #'-' ; ### portable?
|
||||
bne L5
|
||||
dex ; flag: negative
|
||||
L3: iny
|
||||
bne L5
|
||||
inc ptr1+1
|
||||
|
||||
; Store the sign flag and setup for conversion
|
||||
|
||||
L5: stx tmp1 ; remember sign flag
|
||||
|
||||
L6: lda (ptr1),y ; get next char
|
||||
tax
|
||||
lda __ctype,x ; get character classification
|
||||
and #$04 ; digit?
|
||||
beq L8 ; done
|
||||
|
||||
; Multiply ptr2 (the converted value) by 10
|
||||
|
||||
jsr mul2 ; * 2
|
||||
|
||||
lda sreg+1
|
||||
pha
|
||||
lda sreg
|
||||
pha
|
||||
lda ptr2+1
|
||||
pha
|
||||
lda ptr2
|
||||
pha ; Save value
|
||||
|
||||
jsr mul2 ; * 4
|
||||
jsr mul2 ; * 8
|
||||
|
||||
clc
|
||||
pla
|
||||
adc ptr2
|
||||
sta ptr2
|
||||
pla
|
||||
adc ptr2+1
|
||||
sta ptr2+1
|
||||
pla
|
||||
adc sreg
|
||||
sta sreg
|
||||
pla
|
||||
adc sreg+1
|
||||
sta sreg+1 ; x*2 + x*8 = x*10
|
||||
|
||||
; Get the character back and add it
|
||||
|
||||
txa ; get char back
|
||||
sec
|
||||
sbc #'0' ; make numeric value
|
||||
clc
|
||||
adc ptr2
|
||||
sta ptr2
|
||||
bcc L7
|
||||
inc ptr2+1
|
||||
bne L7
|
||||
inc sreg
|
||||
bne L7
|
||||
inc sreg+1
|
||||
|
||||
; Next character
|
||||
|
||||
L7: iny
|
||||
bne L6
|
||||
inc ptr1+1
|
||||
bne L6
|
||||
|
||||
; Conversion done. Be shure to negate the value if needed.
|
||||
|
||||
L8: lda ptr2
|
||||
ldx ptr2+1
|
||||
ldy tmp1 ; sign
|
||||
beq L9
|
||||
|
||||
; Negate the 32 bit value in ptr2/sreg
|
||||
|
||||
sec
|
||||
lda ptr2
|
||||
eor #$FF
|
||||
adc #0
|
||||
sta ptr2
|
||||
lda ptr2+1
|
||||
eor #$FF
|
||||
adc #0
|
||||
sta ptr2+1
|
||||
lda sreg
|
||||
eor #$FF
|
||||
adc #0
|
||||
sta sreg
|
||||
lda sreg+1
|
||||
eor #$FF
|
||||
adc #0
|
||||
sta sreg+1
|
||||
|
||||
; Done, load the low 16 bit into A/X
|
||||
|
||||
L9: lda ptr2
|
||||
ldx ptr2+1 ; get value
|
||||
rts
|
||||
|
||||
;
|
||||
; Helper functions
|
||||
;
|
||||
|
||||
mul2:
|
||||
asl ptr2
|
||||
rol ptr2+1
|
||||
rol sreg
|
||||
rol sreg+1 ; * 2
|
||||
rts
|
||||
|
||||
|
||||
48
libsrc/common/bsearch.c
Normal file
48
libsrc/common/bsearch.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* bsearch.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 17.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
void* bsearch (void* key, void* base, size_t n, size_t size, int (*cmp) (void*, void*))
|
||||
{
|
||||
int current;
|
||||
int result;
|
||||
int found = 0;
|
||||
int first = 0;
|
||||
int last = n - 1;
|
||||
|
||||
/* Binary search */
|
||||
while (first <= last) {
|
||||
|
||||
/* Set current to mid of range */
|
||||
current = (last + first) / 2;
|
||||
|
||||
/* Do a compare */
|
||||
result = cmp ((void*) (((int) base) + current*size), key);
|
||||
if (result < 0) {
|
||||
first = current + 1;
|
||||
} else {
|
||||
last = current - 1;
|
||||
if (result == 0) {
|
||||
/* Found one entry that matches the search key. However there may be
|
||||
* more than one entry with the same key value and ANSI guarantees
|
||||
* that we return the first of a row of items with the same key.
|
||||
*/
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we find the entry? */
|
||||
return (void*) (found? ((int) base) + first*size : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
25
libsrc/common/calloc.c
Normal file
25
libsrc/common/calloc.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* calloc.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 06.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
void* calloc (size_t count, size_t size)
|
||||
{
|
||||
void* mem;
|
||||
size *= count;
|
||||
if (mem = malloc (size)) {
|
||||
memset (mem, 0, size);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
53
libsrc/common/copydata.s
Normal file
53
libsrc/common/copydata.s
Normal file
@@ -0,0 +1,53 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 07.12.1998
|
||||
;
|
||||
; Copy the data segment from the LOAD to the RUN location
|
||||
;
|
||||
|
||||
.export copydata
|
||||
.import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
|
||||
.importzp ptr1, ptr2
|
||||
|
||||
|
||||
copydata:
|
||||
lda #<__DATA_LOAD__ ; Source pointer
|
||||
sta ptr1
|
||||
lda #>__DATA_LOAD__
|
||||
sta ptr1+1
|
||||
|
||||
lda #<__DATA_RUN__ ; Target pointer
|
||||
sta ptr2
|
||||
lda #>__DATA_RUN__
|
||||
sta ptr2+1
|
||||
|
||||
ldy #$00
|
||||
ldx #>__DATA_SIZE__ ; Get page count
|
||||
beq @L2 ; No full pages
|
||||
|
||||
; Copy full pages
|
||||
|
||||
@L1: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
iny
|
||||
bne @L1
|
||||
inc ptr1+1
|
||||
inc ptr2+2 ; Bump pointers
|
||||
dex
|
||||
bne @L1
|
||||
|
||||
; Copy last page (remember: y contains zero)
|
||||
|
||||
@L2: ldx #<__DATA_SIZE__ ; Get remaining bytes
|
||||
beq @L4
|
||||
|
||||
@L3: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
iny
|
||||
dex
|
||||
bne @L3
|
||||
|
||||
; Done
|
||||
|
||||
@L4: rts
|
||||
|
||||
|
||||
26
libsrc/common/cprintf.c
Normal file
26
libsrc/common/cprintf.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* cprintf.c
|
||||
*
|
||||
* Ullrich von Bassewitz. 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <conio.h>
|
||||
|
||||
|
||||
|
||||
int cprintf (char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
|
||||
/* Do formatting and output. Since we know, that va_end is empty, we don't
|
||||
* call it here, saving an extra variable and some code.
|
||||
*/
|
||||
return vcprintf ((char*) va_fix (ap, 1), ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
24
libsrc/common/errno.inc
Normal file
24
libsrc/common/errno.inc
Normal file
@@ -0,0 +1,24 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 16.05.2000
|
||||
;
|
||||
|
||||
; Error codes, must match the values in the C headers
|
||||
|
||||
ENOENT = 1 ; No such file or directory
|
||||
ENOMEM = 2 ; Out of memory
|
||||
EACCES = 3 ; Permission denied
|
||||
ENODEV = 4 ; No such device
|
||||
EMFILE = 5 ; Too many open files
|
||||
EBUSY = 6 ; Device or resource busy
|
||||
EINVAL = 7 ; Invalid argument
|
||||
ENOSPC = 8 ; No space left on device
|
||||
EEXIST = 9 ; File exists
|
||||
EAGAIN = 10 ; Try again
|
||||
EIO = 11 ; I/O error
|
||||
EINTR = 12 ; Interrupted system call
|
||||
ENOSYS = 13 ; Function not implemented
|
||||
ESPIPE = 14 ; Illegal seek
|
||||
EUNKNOWN = 15 ; Unknown OS specific error - must be last!
|
||||
|
||||
EMAX = 15 ; Highest error code
|
||||
|
||||
33
libsrc/common/errno.s
Normal file
33
libsrc/common/errno.s
Normal file
@@ -0,0 +1,33 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 06.06.1998
|
||||
;
|
||||
; int _errno;
|
||||
;
|
||||
; void _maperrno(void);
|
||||
; /* Map an OS error to a system independent error code */
|
||||
;
|
||||
|
||||
.export __maperrno
|
||||
.export __errno
|
||||
.import __oserror
|
||||
.import __osmaperrno
|
||||
|
||||
|
||||
.code
|
||||
|
||||
__maperrno:
|
||||
lda __oserror ; Get the error code
|
||||
beq @L1 ; Jump if no error
|
||||
ldx #$00 ; Clear error
|
||||
stx __oserror
|
||||
jsr __osmaperrno ; Map the code
|
||||
sta __errno
|
||||
stx __errno+1
|
||||
@L1: rts
|
||||
|
||||
|
||||
.bss
|
||||
|
||||
__errno:
|
||||
.word 0
|
||||
|
||||
33
libsrc/common/errormsg.c
Normal file
33
libsrc/common/errormsg.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* errormsg.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 17.05.2000
|
||||
*
|
||||
* Must be a C function, since we have otherwise problems with the different
|
||||
* character sets.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Place the following data into the readonly data segment */
|
||||
#pragma dataseg ("RODATA")
|
||||
|
||||
const char* _sys_errlist[] = {
|
||||
"Unknown error", /* 0 */
|
||||
"No such file or directory", /* 1 */
|
||||
"Out of memory", /* 2 */
|
||||
"Permission denied", /* 3 */
|
||||
"No such device", /* 4 */
|
||||
"Too many open files", /* 5 */
|
||||
"Device or resource busy", /* 6 */
|
||||
"Invalid argument", /* 7 */
|
||||
"No space left on device", /* 8 */
|
||||
"File exists", /* 9 */
|
||||
"Try again", /* 10 */
|
||||
"I/O error", /* 11 */
|
||||
"Interrupted system call", /* 12 */
|
||||
"Function not implemented", /* 13 */
|
||||
"Illegal seek", /* 14 */
|
||||
};
|
||||
|
||||
|
||||
27
libsrc/common/fclose.c
Normal file
27
libsrc/common/fclose.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* int fclose (FILE* f);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
int fclose (FILE* f)
|
||||
{
|
||||
if ((f->f_flags & _FOPEN) == 0) {
|
||||
/* File is not open */
|
||||
_errno = EINVAL; /* File not input */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reset the flags and close the file */
|
||||
f->f_flags = _FCLOSED;
|
||||
return close (f->f_fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
libsrc/common/fdopen.c
Normal file
37
libsrc/common/fdopen.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* fopen.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 17.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
FILE* fdopen (int handle, char* /*mode*/)
|
||||
{
|
||||
FILE* f;
|
||||
|
||||
/* Find a free file slot */
|
||||
if (!(f = _fdesc ())) {
|
||||
/* No slots */
|
||||
errno = EMFILE; /* Too many files */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert the handle, and return the descriptor */
|
||||
f->f_fd = handle;
|
||||
f->f_flags = _FOPEN;
|
||||
|
||||
/* Return the file descriptor */
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
46
libsrc/common/fgetc.c
Normal file
46
libsrc/common/fgetc.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*
|
||||
* int fgetc (FILE* f);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
int fgetc (FILE* f)
|
||||
{
|
||||
char c;
|
||||
|
||||
/* Check if the file is open or if there is an error condition */
|
||||
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the byte */
|
||||
switch (read (f->f_fd, &c, 1)) {
|
||||
|
||||
case -1:
|
||||
/* Error */
|
||||
f->f_flags |= _FERROR;
|
||||
return -1;
|
||||
|
||||
case 0:
|
||||
/* EOF */
|
||||
f->f_flags |= _FEOF;
|
||||
return -1;
|
||||
|
||||
default:
|
||||
/* Char read */
|
||||
return ((int) c) & 0xFF;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
59
libsrc/common/fgets.c
Normal file
59
libsrc/common/fgets.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*
|
||||
* char* fgets (char* s, int size, FILE* f);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
char* fgets (char* s, unsigned size, FILE* f)
|
||||
{
|
||||
int i, c;
|
||||
|
||||
/* We do not handle the case "size == 0" here */
|
||||
i = 0; --size;
|
||||
while (i < size) {
|
||||
|
||||
/* Get next character */
|
||||
c = fgetc (f);
|
||||
if (c == -1) {
|
||||
s [i] = 0;
|
||||
/* Error or EOF */
|
||||
if (f->f_flags & _FERROR) {
|
||||
/* ERROR */
|
||||
return 0;
|
||||
} else {
|
||||
/* EOF */
|
||||
if (i) {
|
||||
return s;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* One char more */
|
||||
s [i++] = c;
|
||||
|
||||
/* Stop at end of line */
|
||||
if (c == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace newline by NUL */
|
||||
s [i-1] = '\0';
|
||||
|
||||
/* Done */
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
81
libsrc/common/fmisc.s
Normal file
81
libsrc/common/fmisc.s
Normal file
@@ -0,0 +1,81 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; Several small file stream functions
|
||||
;
|
||||
|
||||
.export _clearerr, _feof, _ferror, _fileno, _fflush
|
||||
.import return0
|
||||
.import __errno
|
||||
.importzp ptr1
|
||||
|
||||
;
|
||||
; Get the FILE* parameter, check if the file is open
|
||||
;
|
||||
|
||||
getf: sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #1
|
||||
lda (ptr1),y ; get f->f_flags
|
||||
and #$01 ; file open?
|
||||
beq @L1 ; jump if no
|
||||
clc ; ok
|
||||
rts
|
||||
@L1: sec
|
||||
rts
|
||||
|
||||
;
|
||||
; void clearerr (FILE* f);
|
||||
;
|
||||
|
||||
_clearerr:
|
||||
jsr getf
|
||||
bcs err
|
||||
lda (ptr1),y
|
||||
and #$F9
|
||||
sta (ptr1),y
|
||||
err: rts
|
||||
|
||||
;
|
||||
; int feof (FILE* f);
|
||||
;
|
||||
|
||||
_feof:
|
||||
jsr getf
|
||||
; bcs err
|
||||
lda (ptr1),y
|
||||
and #$02
|
||||
ldx #0
|
||||
rts
|
||||
|
||||
;
|
||||
; int ferror (FILE* f);
|
||||
;
|
||||
|
||||
_ferror:
|
||||
jsr getf
|
||||
; bcs err
|
||||
lda (ptr1),y
|
||||
and #$04
|
||||
ldx #0
|
||||
rts
|
||||
|
||||
;
|
||||
; int fileno (FILE* f);
|
||||
;
|
||||
|
||||
_fileno:
|
||||
jsr getf
|
||||
; bcs err
|
||||
dey
|
||||
lda (ptr1),y
|
||||
ldx #0
|
||||
rts
|
||||
|
||||
;
|
||||
; int __fastcall__ fflush (FILE* f);
|
||||
;
|
||||
|
||||
_fflush = return0
|
||||
|
||||
|
||||
15
libsrc/common/fmode.inc
Normal file
15
libsrc/common/fmode.inc
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 05.06.1999
|
||||
;
|
||||
|
||||
; File mode constants, must match the values in the C headers
|
||||
|
||||
|
||||
O_RDONLY = $01
|
||||
O_WRONLY = $02
|
||||
O_RDWR = $03
|
||||
O_CREAT = $04
|
||||
O_TRUNC = $10
|
||||
O_APPEND = $20
|
||||
|
||||
|
||||
32
libsrc/common/fopen.c
Normal file
32
libsrc/common/fopen.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* fopen.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 17.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
FILE* fopen (const char* name, const char* mode)
|
||||
{
|
||||
FILE* f;
|
||||
|
||||
/* Find a free file slot */
|
||||
if (!(f = _fdesc ())) {
|
||||
/* No slots */
|
||||
_errno = EMFILE; /* Too many files */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the file and return the descriptor */
|
||||
return _fopen (name, mode, f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
26
libsrc/common/fprintf.c
Normal file
26
libsrc/common/fprintf.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* fprintf.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
int fprintf (FILE* /*F*/, char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
|
||||
/* Do formatting and output. Since we know, that va_end is empty, we don't
|
||||
* call it here, saving an extra variable and some code.
|
||||
*/
|
||||
return vfprintf ((FILE*) va_fix (ap, 1), (char*) va_fix (ap, 2), ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
34
libsrc/common/fputc.c
Normal file
34
libsrc/common/fputc.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* fputc.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 02.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
int fputc (int c, FILE* f)
|
||||
{
|
||||
/* Check if the file is open or if there is an error condition */
|
||||
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write the byte (knows about byte order!) */
|
||||
if (write (f->f_fd, &c, 1) <= 0) {
|
||||
/* Error */
|
||||
f->f_flags |= _FERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return the byte written */
|
||||
return c & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
28
libsrc/common/fputs.c
Normal file
28
libsrc/common/fputs.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* int fputs (const char* s, FILE* f);
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
int fputs (char* s, FILE* f)
|
||||
{
|
||||
/* Check if the file is open or if there is an error condition */
|
||||
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write the string */
|
||||
return write (f->f_fd, s, strlen (s));
|
||||
}
|
||||
|
||||
|
||||
|
||||
61
libsrc/common/fread.c
Normal file
61
libsrc/common/fread.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* fread.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 02.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
size_t fread (void* buf, size_t size, size_t count, FILE* f)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
/* Is the file open? */
|
||||
if ((f->f_flags & _FOPEN) == 0) {
|
||||
_errno = EINVAL; /* File not open */
|
||||
return (size_t) -1;
|
||||
}
|
||||
|
||||
/* Did we have an error or EOF? */
|
||||
if ((f->f_flags & (_FERROR | _FEOF)) != 0) {
|
||||
/* Cannot read from stream */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* How many bytes to read? */
|
||||
bytes = size * count;
|
||||
|
||||
if (bytes) {
|
||||
/* Read the data. */
|
||||
bytes = read (f->f_fd, buf, bytes);
|
||||
if (bytes == -1) {
|
||||
/* Read error */
|
||||
f->f_flags |= _FERROR;
|
||||
return (size_t) -1;
|
||||
}
|
||||
if (bytes == 0) {
|
||||
/* End of file */
|
||||
f->f_flags |= _FEOF;
|
||||
return (size_t) -1;
|
||||
}
|
||||
|
||||
/* Unfortunately, we cannot avoid the divide here... */
|
||||
return bytes / size;
|
||||
|
||||
} else {
|
||||
|
||||
/* 0 bytes read */
|
||||
return count;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
65
libsrc/common/free.c
Normal file
65
libsrc/common/free.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* free.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "_heap.h"
|
||||
|
||||
|
||||
|
||||
void free (void* block)
|
||||
/* Release an allocated memory block. The function will accept NULL pointers
|
||||
* (and do nothing in this case).
|
||||
*/
|
||||
{
|
||||
unsigned* b;
|
||||
unsigned size;
|
||||
struct freeblock* f;
|
||||
|
||||
|
||||
/* Allow NULL arguments */
|
||||
if (block == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get a pointer to the real memory block, then get the size */
|
||||
b = (unsigned*) block;
|
||||
size = *--b;
|
||||
|
||||
/* Check if the block is at the top of the heap */
|
||||
if (((int) b) + size == (int) _hptr) {
|
||||
|
||||
/* Decrease _hptr to release the block */
|
||||
_hptr = (unsigned*) (((int) _hptr) - size);
|
||||
|
||||
/* Check if the last block in the freelist is now at heap top. If so,
|
||||
* remove this block from the freelist.
|
||||
*/
|
||||
if (f = _hlast) {
|
||||
if (((int) f) + f->size == (int) _hptr) {
|
||||
/* Remove the last block */
|
||||
_hptr = (unsigned*) (((int) _hptr) - f->size);
|
||||
if (_hlast = f->prev) {
|
||||
/* Block before is now last block */
|
||||
f->prev->next = 0;
|
||||
} else {
|
||||
/* The freelist is empty now */
|
||||
_hfirst = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Not at heap top, enter the block into the free list */
|
||||
_hadd (b, size);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
38
libsrc/common/freopen.c
Normal file
38
libsrc/common/freopen.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* freopen.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 17.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
FILE* freopen (char* name, char* mode, FILE* f)
|
||||
{
|
||||
/* Check if the file is open, if so, close it */
|
||||
if ((f->f_flags & _FOPEN) == 0) {
|
||||
/* File is not open */
|
||||
_errno = EINVAL; /* File not input */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Close the file. Don't bother setting the flag, it will get
|
||||
* overwritten by _fopen.
|
||||
*/
|
||||
if (close (f->f_fd) < 0) {
|
||||
/* An error occured, _oserror is set */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the file and return the descriptor */
|
||||
return _fopen (name, mode, f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
51
libsrc/common/fwrite.c
Normal file
51
libsrc/common/fwrite.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* fwrite.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 04.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
size_t fwrite (void* buf, size_t size, size_t count, FILE* f)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
/* Is the file open? */
|
||||
if ((f->f_flags & _FOPEN) == 0) {
|
||||
_errno = EINVAL; /* File not open */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Did we have an error */
|
||||
if ((f->f_flags & _FERROR) != 0) {
|
||||
/* Cannot write to stream */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* How many bytes to write? */
|
||||
bytes = size * count;
|
||||
|
||||
if (bytes) {
|
||||
/* Write the data. */
|
||||
if (write (f->f_fd, buf, bytes) == -1) {
|
||||
/* Write error */
|
||||
f->f_flags |= _FERROR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't waste time with expensive calculations, assume the write was
|
||||
* complete and return the count of items.
|
||||
*/
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
22
libsrc/common/getchar.c
Normal file
22
libsrc/common/getchar.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* getchar.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.12.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* This is usually declared as a macro */
|
||||
#undef getchar
|
||||
|
||||
|
||||
|
||||
int getchar (void)
|
||||
{
|
||||
return fgetc (stdin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
libsrc/common/getcpu.s
Normal file
37
libsrc/common/getcpu.s
Normal file
@@ -0,0 +1,37 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.04.1999
|
||||
;
|
||||
; unsigned char getcpu (void);
|
||||
;
|
||||
|
||||
.export _getcpu
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Subroutine to detect an 816. Returns
|
||||
;
|
||||
; - carry clear and 0 in A for a NMOS 6502 CPU
|
||||
; - carry set and 1 in A for some CMOS 6502 CPU
|
||||
; - carry set and 2 in A for a 65816
|
||||
;
|
||||
; This function uses a $1A opcode which is a INA on the 816 and ignored
|
||||
; (interpreted as a NOP) on a NMOS 6502. There are several CMOS versions
|
||||
; of the 6502, but all of them interpret unknown opcodes as NOP so this is
|
||||
; just what we want.
|
||||
|
||||
.p816 ; Enable 65816 instructions
|
||||
|
||||
_getcpu:
|
||||
lda #0
|
||||
inc a ; .byte $1A
|
||||
cmp #1
|
||||
bcc @L9
|
||||
|
||||
; This is at least a 65C02, check for a 65816
|
||||
|
||||
xba ; .byte $eb, put $01 in B accu
|
||||
dec a ; .byte $3a, A=$00 if 65C02
|
||||
xba ; .byte $eb, get $01 back if 65816
|
||||
inc a ; .byte $1a, make $01/$02
|
||||
@L9: ldx #0 ; Load high byte of word
|
||||
rts
|
||||
|
||||
52
libsrc/common/gets.c
Normal file
52
libsrc/common/gets.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* gets.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
char* gets (char* s)
|
||||
{
|
||||
int i, c;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
|
||||
/* Get next character */
|
||||
c = fgetc (stdin);
|
||||
if (c == -1) {
|
||||
/* Error or EOF */
|
||||
s [i] = 0;
|
||||
if (stdin->f_flags & _FERROR) {
|
||||
/* ERROR */
|
||||
return 0;
|
||||
} else {
|
||||
/* EOF */
|
||||
if (i) {
|
||||
return s;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* One char more */
|
||||
s [i++] = c;
|
||||
|
||||
} while (c != '\n');
|
||||
|
||||
/* Replace newline by NUL */
|
||||
s [i-1] = '\0';
|
||||
|
||||
/* Done */
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
15
libsrc/common/isalnum.s
Normal file
15
libsrc/common/isalnum.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isalnum (int c);
|
||||
;
|
||||
|
||||
.export _isalnum
|
||||
.import __ctype
|
||||
|
||||
_isalnum:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$07 ; Mask character/digit bits
|
||||
rts
|
||||
|
||||
15
libsrc/common/isalpha.s
Normal file
15
libsrc/common/isalpha.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isalpha (int c);
|
||||
;
|
||||
|
||||
.export _isalpha
|
||||
.import __ctype
|
||||
|
||||
_isalpha:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$03 ; Mask character bits
|
||||
rts
|
||||
|
||||
17
libsrc/common/isblank.s
Normal file
17
libsrc/common/isblank.s
Normal file
@@ -0,0 +1,17 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isblank (int c);
|
||||
;
|
||||
; cc65 (and GNU) extension.
|
||||
;
|
||||
|
||||
.export _isblank
|
||||
.import __ctype
|
||||
|
||||
_isblank:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$80 ; Mask blank bit
|
||||
rts
|
||||
|
||||
16
libsrc/common/iscntrl.s
Normal file
16
libsrc/common/iscntrl.s
Normal file
@@ -0,0 +1,16 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int iscntrl (int c);
|
||||
;
|
||||
|
||||
.export _iscntrl
|
||||
.import __ctype
|
||||
|
||||
_iscntrl:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$10 ; Mask control character bit
|
||||
rts
|
||||
|
||||
|
||||
15
libsrc/common/isdigit.s
Normal file
15
libsrc/common/isdigit.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isdigit (int c);
|
||||
;
|
||||
|
||||
.export _isdigit
|
||||
.import __ctype
|
||||
|
||||
_isdigit:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$04 ; Mask digit bit
|
||||
rts
|
||||
|
||||
16
libsrc/common/isgraph.s
Normal file
16
libsrc/common/isgraph.s
Normal file
@@ -0,0 +1,16 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isgraph (int c);
|
||||
;
|
||||
|
||||
.export _isgraph
|
||||
.import __ctype
|
||||
|
||||
_isgraph:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
eor #$30 ; NOT control and NOT space
|
||||
and #$30 ; Mask character bits
|
||||
rts
|
||||
|
||||
15
libsrc/common/islower.s
Normal file
15
libsrc/common/islower.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int islower (int c);
|
||||
;
|
||||
|
||||
.export _islower
|
||||
.import __ctype
|
||||
|
||||
_islower:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$01 ; Mask lower char bit
|
||||
rts
|
||||
|
||||
16
libsrc/common/isprint.s
Normal file
16
libsrc/common/isprint.s
Normal file
@@ -0,0 +1,16 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isprint (int c);
|
||||
;
|
||||
|
||||
.export _isprint
|
||||
.import __ctype
|
||||
|
||||
_isprint:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
eor #$10 ; NOT a control char
|
||||
and #$10 ; Mask control char bit
|
||||
rts
|
||||
|
||||
16
libsrc/common/ispunct.s
Normal file
16
libsrc/common/ispunct.s
Normal file
@@ -0,0 +1,16 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int ispunct (int c);
|
||||
;
|
||||
|
||||
.export _ispunct
|
||||
.import __ctype
|
||||
|
||||
_ispunct:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
eor #$37 ; NOT (space | control | digit | char)
|
||||
and #$37 ; Mask relevant bits
|
||||
rts
|
||||
|
||||
15
libsrc/common/isspace.s
Normal file
15
libsrc/common/isspace.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isspace (int c);
|
||||
;
|
||||
|
||||
.export _isspace
|
||||
.import __ctype
|
||||
|
||||
_isspace:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$60 ; Mask space bits
|
||||
rts
|
||||
|
||||
15
libsrc/common/isupper.s
Normal file
15
libsrc/common/isupper.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isupper (int c);
|
||||
;
|
||||
|
||||
.export _isupper
|
||||
.import __ctype
|
||||
|
||||
_isupper:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$02 ; Mask upper char bit
|
||||
rts
|
||||
|
||||
15
libsrc/common/isxdigit.s
Normal file
15
libsrc/common/isxdigit.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int isxdigit (int c);
|
||||
;
|
||||
|
||||
.export _isxdigit
|
||||
.import __ctype
|
||||
|
||||
_isxdigit:
|
||||
tay
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$08 ; Mask xdigit bit
|
||||
rts
|
||||
|
||||
146
libsrc/common/itoa.s
Normal file
146
libsrc/common/itoa.s
Normal file
@@ -0,0 +1,146 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; char* itoa (int value, char* s, int radix);
|
||||
; char* utoa (unsigned value, char* s, int radix);
|
||||
;
|
||||
|
||||
.export _itoa, _utoa
|
||||
.import addysp1
|
||||
.import __hextab
|
||||
.importzp sp, sreg, ptr2, ptr3, tmp1
|
||||
|
||||
.rodata
|
||||
specval:
|
||||
.byte '-', '3', '2', '7', '6', '8', 0
|
||||
.code
|
||||
|
||||
;
|
||||
; Common subroutine to pop the parameters and put them into core
|
||||
;
|
||||
|
||||
dopop: sta tmp1 ; will loose high byte
|
||||
ldy #0
|
||||
lda (sp),y
|
||||
sta ptr2
|
||||
sta ptr3
|
||||
iny
|
||||
lda (sp),y
|
||||
sta ptr2+1
|
||||
sta ptr3+1
|
||||
iny
|
||||
lda (sp),y
|
||||
sta sreg
|
||||
iny
|
||||
lda (sp),y
|
||||
sta sreg+1
|
||||
jmp addysp1 ; Bump stack pointer
|
||||
|
||||
;
|
||||
; itoa
|
||||
;
|
||||
|
||||
_itoa: jsr dopop ; pop the arguments
|
||||
|
||||
; We must handle $8000 in a special way, since it is the only negative
|
||||
; number that has no positive 16-bit counterpart
|
||||
|
||||
ldy tmp1 ; get radix
|
||||
cpy #10
|
||||
bne utoa
|
||||
cmp #$00
|
||||
bne L2
|
||||
cpx #$80
|
||||
bne L2
|
||||
|
||||
ldy #6
|
||||
L1: lda specval,y ; copy -32768
|
||||
sta (ptr2),y
|
||||
dey
|
||||
bpl L1
|
||||
jmp L10
|
||||
|
||||
; Check if the value is negative. If so, write a - sign and negate the
|
||||
; number.
|
||||
|
||||
L2: lda sreg+1 ; get high byte
|
||||
bpl utoa
|
||||
lda #'-'
|
||||
ldy #0
|
||||
sta (ptr2),y ; store sign
|
||||
inc ptr2
|
||||
bne L3
|
||||
inc ptr2+1
|
||||
|
||||
L3: lda sreg
|
||||
eor #$FF
|
||||
clc
|
||||
adc #$01
|
||||
sta sreg
|
||||
lda sreg+1
|
||||
eor #$FF
|
||||
adc #$00
|
||||
sta sreg+1
|
||||
jmp utoa
|
||||
|
||||
;
|
||||
; utoa
|
||||
;
|
||||
|
||||
_utoa: jsr dopop ; pop the arguments
|
||||
|
||||
; Convert to string by dividing and push the result onto the stack
|
||||
|
||||
utoa: lda #$00
|
||||
pha ; sentinel
|
||||
|
||||
; Divide sreg/tmp1 -> sreg, remainder in a
|
||||
|
||||
L5: ldy #16 ; 16 bit
|
||||
lda #0 ; remainder
|
||||
L6: asl sreg
|
||||
rol sreg+1
|
||||
rol a
|
||||
cmp tmp1
|
||||
bcc L7
|
||||
sbc tmp1
|
||||
inc sreg
|
||||
L7: dey
|
||||
bne L6
|
||||
|
||||
tay ; get remainder into y
|
||||
lda __hextab,y ; get hex character
|
||||
pha ; save char value on stack
|
||||
|
||||
lda sreg
|
||||
ora sreg+1
|
||||
bne L5
|
||||
|
||||
; Get the characters from the stack into the string
|
||||
|
||||
ldy #0
|
||||
L9: pla
|
||||
sta (ptr2),y
|
||||
beq L10 ; jump if sentinel
|
||||
iny
|
||||
bne L9 ; jump always
|
||||
|
||||
; Done! Return the target string
|
||||
|
||||
L10: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
14
libsrc/common/jmpvec.s
Normal file
14
libsrc/common/jmpvec.s
Normal file
@@ -0,0 +1,14 @@
|
||||
;
|
||||
; General purpose jump vector in the data segment that is patched at
|
||||
; runtime and used by several routines.
|
||||
;
|
||||
; Ullrich von Bassewitz, 16.12.1998
|
||||
;
|
||||
|
||||
.export jmpvec
|
||||
|
||||
|
||||
.data
|
||||
|
||||
jmpvec: jmp $FFFF
|
||||
|
||||
15
libsrc/common/labs.s
Normal file
15
libsrc/common/labs.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 17.06.1998
|
||||
;
|
||||
; long labs (long x);
|
||||
;
|
||||
|
||||
.export _labs
|
||||
.import negeax, tsteax
|
||||
.importzp sreg
|
||||
|
||||
_labs: ldy sreg+1 ; test hi byte
|
||||
bpl L1
|
||||
jmp negeax ; Negate if negative
|
||||
L1: rts
|
||||
|
||||
78
libsrc/common/locale.c
Normal file
78
libsrc/common/locale.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* locale.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.12.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <locale.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Data in this module is read-only, put it into the RODATA segment */
|
||||
#pragma dataseg ("RODATA");
|
||||
|
||||
/* For memory efficiency use a separate empty string */
|
||||
static const char EmptyString [] = "";
|
||||
|
||||
static struct lconv lc = {
|
||||
EmptyString, /* currency_symbol */
|
||||
".", /* decimal_point */
|
||||
EmptyString, /* grouping */
|
||||
EmptyString, /* int_curr_symbol */
|
||||
EmptyString, /* mon_decimal_point */
|
||||
EmptyString, /* mon_grouping */
|
||||
EmptyString, /* mon_thousands_sep */
|
||||
EmptyString, /* negative_sign */
|
||||
EmptyString, /* positive_sign */
|
||||
EmptyString, /* thousands_sep */
|
||||
CHAR_MAX, /* frac_digits */
|
||||
CHAR_MAX, /* int_frac_digits */
|
||||
CHAR_MAX, /* n_cs_precedes */
|
||||
CHAR_MAX, /* n_sep_by_space */
|
||||
CHAR_MAX, /* n_sign_posn */
|
||||
CHAR_MAX, /* p_cs_precedes */
|
||||
CHAR_MAX, /* p_sep_by_space */
|
||||
CHAR_MAX, /* p_sign_posn */
|
||||
};
|
||||
|
||||
/* Restore the old data segment name */
|
||||
#pragma dataseg ("DATA");
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct lconv* localeconv (void)
|
||||
{
|
||||
return &lc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char* setlocale (int, const char* locale)
|
||||
{
|
||||
if (locale == 0 || (locale [0] == 'C' && locale [1] == '\0') || locale [0] == '\0') {
|
||||
/* No change, or value already set, our locale is the "C" locale */
|
||||
return "C";
|
||||
} else {
|
||||
/* Cannot set this one */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
48
libsrc/common/longjmp.s
Normal file
48
libsrc/common/longjmp.s
Normal file
@@ -0,0 +1,48 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 06.06.1998
|
||||
;
|
||||
; void longjmp (jmp_buf buf, int retval);
|
||||
;
|
||||
|
||||
.export _longjmp
|
||||
.import popax
|
||||
.importzp sp, ptr1, ptr2
|
||||
|
||||
_longjmp:
|
||||
sta ptr2 ; Save retval
|
||||
stx ptr2+1
|
||||
jsr popax ; get buf
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #0
|
||||
|
||||
; Get the old parameter stack
|
||||
|
||||
lda (ptr1),y
|
||||
iny
|
||||
sta sp
|
||||
lda (ptr1),y
|
||||
iny
|
||||
sta sp+1
|
||||
|
||||
; Get the old stack pointer
|
||||
|
||||
lda (ptr1),y
|
||||
iny
|
||||
tax
|
||||
txs
|
||||
|
||||
; Get the return address and push it on the stack
|
||||
|
||||
lda (ptr1),y
|
||||
iny
|
||||
pha
|
||||
lda (ptr1),y
|
||||
pha
|
||||
|
||||
; Load the return value and return to the caller
|
||||
|
||||
lda ptr2
|
||||
ldx ptr2+1
|
||||
rts
|
||||
|
||||
160
libsrc/common/ltoa.s
Normal file
160
libsrc/common/ltoa.s
Normal file
@@ -0,0 +1,160 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.06.1998
|
||||
;
|
||||
; char* ltoa (long value, char* s, int radix);
|
||||
; char* ultoa (unsigned long value, char* s, int radix);
|
||||
;
|
||||
|
||||
.export _ltoa, _ultoa
|
||||
.import popax
|
||||
.import __hextab
|
||||
.importzp sreg, ptr1, ptr2, ptr3, tmp1
|
||||
|
||||
|
||||
|
||||
.rodata
|
||||
specval:
|
||||
.byte '-', '2', '1', '4', '7', '4', '8', '3', '6', '4', '8', 0
|
||||
.code
|
||||
|
||||
;
|
||||
; Common subroutine to pop the parameters and put them into core
|
||||
;
|
||||
|
||||
dopop: sta tmp1 ; will loose high byte
|
||||
jsr popax ; get s
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
sta sreg ; save for return
|
||||
stx sreg+1
|
||||
jsr popax ; get low word of value
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
jsr popax ; get high word of value
|
||||
sta ptr3
|
||||
stx ptr3+1
|
||||
rts
|
||||
|
||||
;
|
||||
; ltoa
|
||||
;
|
||||
|
||||
_ltoa: jsr dopop ; pop the arguments
|
||||
|
||||
; We must handle $80000000 in a special way, since it is the only negative
|
||||
; number that has no positive 32-bit counterpart
|
||||
|
||||
ldx ptr3+1 ; get high byte
|
||||
ldy tmp1 ; get radix
|
||||
cpy #10
|
||||
bne ultoa
|
||||
lda ptr3
|
||||
ora ptr2+1
|
||||
ora ptr2
|
||||
bne L2
|
||||
cpx #$80
|
||||
bne L2
|
||||
|
||||
ldy #11
|
||||
L1: lda specval,y ; copy -2147483648
|
||||
sta (ptr1),y
|
||||
dey
|
||||
bpl L1
|
||||
jmp L10
|
||||
|
||||
; Check if the value is negative. If so, write a - sign and negate the
|
||||
; number.
|
||||
|
||||
L2: txa ; get high byte
|
||||
bpl ultoa
|
||||
lda #'-'
|
||||
ldy #0
|
||||
sta (ptr1),y ; store sign
|
||||
inc ptr1
|
||||
bne L3
|
||||
inc ptr1+1
|
||||
|
||||
L3: lda ptr2 ; negate val
|
||||
eor #$FF
|
||||
clc
|
||||
adc #$01
|
||||
sta ptr2
|
||||
lda ptr2+1
|
||||
eor #$FF
|
||||
adc #$00
|
||||
sta ptr2+1
|
||||
lda ptr3
|
||||
eor #$FF
|
||||
adc #$00
|
||||
sta ptr3
|
||||
lda ptr3+1
|
||||
eor #$FF
|
||||
adc #$00
|
||||
sta ptr3+1
|
||||
jmp ultoa
|
||||
|
||||
;
|
||||
; utoa
|
||||
;
|
||||
|
||||
_ultoa: jsr dopop ; pop the arguments
|
||||
|
||||
; Convert to string by dividing and push the result onto the stack
|
||||
|
||||
ultoa: lda #$00
|
||||
pha ; sentinel
|
||||
|
||||
; Divide val/tmp1 -> val, remainder in a
|
||||
|
||||
L5: ldy #32 ; 32 bit
|
||||
lda #0 ; remainder
|
||||
L6: asl ptr2
|
||||
rol ptr2+1
|
||||
rol ptr3
|
||||
rol ptr3+1
|
||||
rol a
|
||||
cmp tmp1
|
||||
bcc L7
|
||||
sbc tmp1
|
||||
inc ptr2
|
||||
L7: dey
|
||||
bne L6
|
||||
|
||||
tay ; get remainder into y
|
||||
lda __hextab,y ; get hex character
|
||||
pha ; save char value on stack
|
||||
|
||||
lda ptr2
|
||||
ora ptr2+1
|
||||
ora ptr3
|
||||
ora ptr3+1
|
||||
bne L5
|
||||
|
||||
; Get the characters from the stack into the string
|
||||
|
||||
ldy #0
|
||||
L9: pla
|
||||
sta (ptr1),y
|
||||
beq L10 ; jump if sentinel
|
||||
iny
|
||||
bne L9 ; jump always
|
||||
|
||||
; Done! Return the target string
|
||||
|
||||
L10: lda sreg
|
||||
ldx sreg+1
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
125
libsrc/common/malloc.c
Normal file
125
libsrc/common/malloc.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* malloc.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 03.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include "_heap.h"
|
||||
|
||||
|
||||
|
||||
void* malloc (size_t size)
|
||||
/* Allocate memory from the given heap. The function returns a pointer to the
|
||||
* allocated memory block or a NULL pointer if not enough memory is available.
|
||||
* Allocating a zero size block is not allowed.
|
||||
*/
|
||||
{
|
||||
struct freeblock* f;
|
||||
unsigned* p;
|
||||
|
||||
|
||||
/* Check for a size of zero, then add the administration space and round
|
||||
* up the size if needed.
|
||||
*/
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
size += HEAP_ADMIN_SPACE;
|
||||
if (size < sizeof (struct freeblock)) {
|
||||
size = sizeof (struct freeblock);
|
||||
}
|
||||
|
||||
/* Search the freelist for a block that is big enough */
|
||||
f = _hfirst;
|
||||
while (f && f->size < size) {
|
||||
f = f->next;
|
||||
}
|
||||
|
||||
/* Did we find one? */
|
||||
if (f) {
|
||||
|
||||
/* We found a block big enough. If the block can hold just the
|
||||
* requested size, use the block in full. Beware: When slicing blocks,
|
||||
* there must be space enough to create a new one! If this is not the
|
||||
* case, then use the complete block.
|
||||
*/
|
||||
if (f->size - size < sizeof (struct freeblock)) {
|
||||
|
||||
/* Use the actual size */
|
||||
size = f->size;
|
||||
|
||||
/* Remove the block from the free list */
|
||||
if (f->prev) {
|
||||
/* We have a previous block */
|
||||
f->prev->next = f->next;
|
||||
} else {
|
||||
/* This is the first block, correct the freelist pointer */
|
||||
_hfirst = f->next;
|
||||
}
|
||||
if (f->next) {
|
||||
/* We have a next block */
|
||||
f->next->prev = f->prev;
|
||||
} else {
|
||||
/* This is the last block, correct the freelist pointer */
|
||||
_hlast = f->prev;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* We must slice the block found */
|
||||
struct freeblock* newblock;
|
||||
newblock = (struct freeblock*) ((unsigned) f) + size;
|
||||
|
||||
/* Insert the new block (the remaining space) instead of the
|
||||
* old one.
|
||||
*/
|
||||
newblock->size = f->size - size; /* Remaining size */
|
||||
newblock->next = f->next;
|
||||
newblock->prev = f->prev;
|
||||
if (f->prev) {
|
||||
/* We have a previous block */
|
||||
f->prev->next = newblock;
|
||||
} else {
|
||||
/* This is the first block, correct the freelist pointer */
|
||||
_hfirst = newblock;
|
||||
}
|
||||
if (f->next) {
|
||||
/* We have a next block */
|
||||
f->next->prev = newblock;
|
||||
} else {
|
||||
/* This is the last block, correct the freelist pointer */
|
||||
_hlast = newblock;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Setup the pointer for the bock */
|
||||
p = (unsigned*) f;
|
||||
|
||||
} else {
|
||||
|
||||
/* We did not find a block big enough. Try to use new space from the
|
||||
* heap top.
|
||||
*/
|
||||
if (((unsigned) _hend) - ((unsigned) _hptr) < size) {
|
||||
/* Out of heap space */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* There is enough space left, take it from the heap top */
|
||||
p = _hptr;
|
||||
_hptr = (unsigned*) (((unsigned) _hptr) + size);
|
||||
|
||||
}
|
||||
|
||||
/* New block is now in p. Fill in the size and return the user pointer */
|
||||
*p++ = size;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
57
libsrc/common/memchr.s
Normal file
57
libsrc/common/memchr.s
Normal file
@@ -0,0 +1,57 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 09.06.1998
|
||||
;
|
||||
; void* memchr (const void* p, int c, size_t n);
|
||||
;
|
||||
|
||||
.export _memchr
|
||||
.import popax, return0
|
||||
.importzp ptr1, ptr2, tmp1
|
||||
|
||||
|
||||
_memchr:
|
||||
sta ptr2 ; Save n
|
||||
stx ptr2+1
|
||||
jsr popax ; get c
|
||||
sta tmp1
|
||||
jsr popax ; get p
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
ldy #0
|
||||
lda tmp1 ; get c
|
||||
ldx ptr2 ; use X as low counter byte
|
||||
beq L3 ; check high byte
|
||||
|
||||
; Search for the char
|
||||
|
||||
L1: cmp (ptr1),y
|
||||
beq L5 ; jump if found
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
L2: cpx #0
|
||||
beq L3
|
||||
dex
|
||||
jmp L1
|
||||
L3: ldx ptr2+1 ; Check high byte
|
||||
beq L4 ; Jump if counter off
|
||||
dec ptr2+1
|
||||
ldx #$FF
|
||||
bne L1 ; branch always
|
||||
|
||||
; Character not found, return zero
|
||||
|
||||
L4: jmp return0
|
||||
|
||||
; Character found, calculate pointer
|
||||
|
||||
L5: ldx ptr1+1 ; get high byte of pointer
|
||||
tya ; low byte offset
|
||||
clc
|
||||
adc ptr1
|
||||
bcc L6
|
||||
inx
|
||||
L6: rts
|
||||
|
||||
|
||||
54
libsrc/common/memcmp.s
Normal file
54
libsrc/common/memcmp.s
Normal file
@@ -0,0 +1,54 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 09.06.1998
|
||||
;
|
||||
; int memcmp (const void* p1, const void* p2, size_t count);
|
||||
;
|
||||
|
||||
.export _memcmp
|
||||
.import popax, return0
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
_memcmp:
|
||||
sta ptr3 ; Save count
|
||||
sta ptr3+1
|
||||
jsr popax ; get p2
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
jsr popax ; get p1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
ldy #0
|
||||
ldx ptr3 ; use X as low counter byte
|
||||
beq L3
|
||||
|
||||
L1: lda (ptr1),y
|
||||
cmp (ptr2),y
|
||||
bne L5
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
L2: txa
|
||||
beq L3
|
||||
dex
|
||||
jmp L1
|
||||
L3: lda ptr3+1 ; check high byte
|
||||
beq L4
|
||||
dec ptr3+1
|
||||
dex ; X = $FF
|
||||
bne L1 ; branch always
|
||||
|
||||
; Memory areas are equal
|
||||
|
||||
L4: jmp return0
|
||||
|
||||
; Not equal, check which one is greater
|
||||
|
||||
L5: bcs L6
|
||||
ldx #$FF
|
||||
rts
|
||||
|
||||
L6: ldx #$01
|
||||
rts
|
||||
|
||||
113
libsrc/common/memcpy.s
Normal file
113
libsrc/common/memcpy.s
Normal file
@@ -0,0 +1,113 @@
|
||||
;
|
||||
; void* memcpy (void* dest, const void* src, size_t n);
|
||||
; void* memmove (void* dest, const void* src, size_t n);
|
||||
;
|
||||
; Ullrich von Bassewitz, 10.12.1998
|
||||
;
|
||||
|
||||
.export _memcpy, _memmove
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
_memcpy:
|
||||
jsr getparms ; Get the parameters from stack
|
||||
|
||||
; Copy upwards
|
||||
|
||||
copyup: ldy #0 ; set up to move 256
|
||||
ldx tmp2 ; hi byte of n
|
||||
beq @L2
|
||||
|
||||
@L1: lda (ptr1),y ; get a byte
|
||||
sta (ptr2),y ; store it
|
||||
iny
|
||||
bne @L1
|
||||
inc ptr1+1 ; bump ptrs
|
||||
inc ptr2+1
|
||||
dex
|
||||
bne @L1 ; do another block
|
||||
|
||||
@L2: ldx tmp1 ; get low byte of n
|
||||
beq done ; jump if done
|
||||
|
||||
@L3: lda (ptr1),y ; get a byte
|
||||
sta (ptr2),y ; store it
|
||||
iny
|
||||
dex
|
||||
bne @L3
|
||||
|
||||
done: lda ptr3
|
||||
ldx ptr3+1 ; get function result (dest)
|
||||
rts
|
||||
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
_memmove:
|
||||
jsr getparms ; Get the parameters from stack
|
||||
|
||||
cpx ptr1+1 ; dest > src?
|
||||
bne @L1
|
||||
cmp ptr1
|
||||
@L1: beq done ; Both pointers are equal - nothing to copy
|
||||
bcc copyup ; Copy upwards
|
||||
|
||||
; Copy downwards
|
||||
|
||||
clc
|
||||
lda ptr1+1
|
||||
adc tmp2
|
||||
sta ptr1+1
|
||||
|
||||
clc
|
||||
lda ptr2+1
|
||||
adc tmp2
|
||||
sta ptr2+1
|
||||
|
||||
; Copy the incomplete page
|
||||
|
||||
ldy tmp1 ; Get low byte of count
|
||||
beq @L3
|
||||
|
||||
@L2: dey
|
||||
lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
tya ; Test Y
|
||||
bne @L2 ; Jump if not zero
|
||||
|
||||
; Copy complete pages
|
||||
|
||||
@L3: ldx tmp2 ; Get hi byte of count
|
||||
beq done
|
||||
|
||||
@L4: dec ptr1+1
|
||||
dec ptr2+1
|
||||
@L5: dey
|
||||
lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
tya
|
||||
bne @L5
|
||||
dex
|
||||
bne @L4
|
||||
|
||||
; Done
|
||||
|
||||
beq done
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Get the parameters from stack
|
||||
|
||||
getparms:
|
||||
sta tmp1 ; Save n
|
||||
stx tmp2
|
||||
jsr popax ; src
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
jsr popax ; dest
|
||||
sta ptr2
|
||||
stx ptr2+1 ; save work copy
|
||||
sta ptr3
|
||||
stx ptr3+1 ; save function result
|
||||
rts
|
||||
|
||||
|
||||
52
libsrc/common/memset.s
Normal file
52
libsrc/common/memset.s
Normal file
@@ -0,0 +1,52 @@
|
||||
;
|
||||
; void* memset (void* ptr, int c, size_t n);
|
||||
;
|
||||
; Ullrich von Bassewitz, 29.05.1998
|
||||
;
|
||||
|
||||
.export _memset
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, tmp1, tmp2, tmp3
|
||||
|
||||
_memset:
|
||||
sta tmp1 ; Save n
|
||||
stx tmp2
|
||||
jsr popax ; Get c
|
||||
sta tmp3 ; Save c
|
||||
jsr popax ; Get ptr
|
||||
sta ptr1
|
||||
stx ptr1+1 ; Save work copy
|
||||
sta ptr2
|
||||
stx ptr2+1 ; Save a copy for the function result
|
||||
lda tmp3
|
||||
|
||||
ldy #0
|
||||
ldx tmp2 ; Get high byte of n
|
||||
beq L2 ; Jump if zero
|
||||
|
||||
; Set 256 byte blocks
|
||||
|
||||
L1: sta (ptr1),y ; Set one byte
|
||||
iny
|
||||
sta (ptr1),y ; Unroll this a bit to make it faster
|
||||
iny
|
||||
bne L1
|
||||
inc ptr1+1
|
||||
dex ; Next 256 byte block
|
||||
bne L1 ; Repeat if any
|
||||
|
||||
; Set the remaining bytes if any
|
||||
|
||||
L2: ldx tmp1 ; Get the low byte of n
|
||||
beq L9 ; Low byte is zero
|
||||
|
||||
L3: sta (ptr1),y ; Set one byte
|
||||
iny
|
||||
dex ; Done?
|
||||
bne L3
|
||||
|
||||
L9: lda ptr2 ; Load function result
|
||||
ldx ptr2+1
|
||||
rts
|
||||
|
||||
|
||||
24
libsrc/common/perror.c
Normal file
24
libsrc/common/perror.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* perror.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 01.10.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
|
||||
void perror (const char* msg)
|
||||
{
|
||||
if (msg) {
|
||||
fprintf (stderr, "%s: ", msg);
|
||||
}
|
||||
fprintf (stderr, "%s\n", strerror (errno));
|
||||
}
|
||||
|
||||
|
||||
|
||||
26
libsrc/common/printf.c
Normal file
26
libsrc/common/printf.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* printf.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
int printf (char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
|
||||
/* Do formatting and output. Since we know, that va_end is empty, we don't
|
||||
* call it here, saving an extra variable and some code.
|
||||
*/
|
||||
return vfprintf (stdout, (char*) va_fix (ap, 1), ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
22
libsrc/common/putchar.c
Normal file
22
libsrc/common/putchar.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* putchar.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.12.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* This is usually declared as a macro */
|
||||
#undef putchar
|
||||
|
||||
|
||||
|
||||
int putchar (int c)
|
||||
{
|
||||
return fputc (c, stdout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
32
libsrc/common/puts.c
Normal file
32
libsrc/common/puts.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* puts.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "_file.h"
|
||||
|
||||
|
||||
|
||||
int puts (const char* s)
|
||||
{
|
||||
static char nl = '\n';
|
||||
|
||||
/* Assume stdout is always open */
|
||||
if (write (stdout->f_fd, s, strlen (s)) < 0 ||
|
||||
write (stdout->f_fd, &nl, 1) < 0) {
|
||||
stdout->f_flags |= _FERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
68
libsrc/common/qsort.c
Normal file
68
libsrc/common/qsort.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* qsort.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 09.12.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
static void QuickSort (void* Base, int Lo, int Hi, size_t Size,
|
||||
int (*Compare)(const void*, const void*))
|
||||
/* Internal recursive function. Works with ints, but this shouldn't be
|
||||
* a problem.
|
||||
*/
|
||||
{
|
||||
int I, J;
|
||||
|
||||
/* Get a char pointer */
|
||||
unsigned char* B = Base;
|
||||
|
||||
/* Quicksort */
|
||||
while (Hi > Lo) {
|
||||
I = Lo + Size;
|
||||
J = Hi;
|
||||
while (I <= J) {
|
||||
while (I <= J && Compare (B + Lo, B + I) >= 0) {
|
||||
I += Size;
|
||||
}
|
||||
while (I <= J && Compare (B + Lo, B + J) < 0) {
|
||||
J -= Size;
|
||||
}
|
||||
if (I <= J) {
|
||||
_swap (B + I, B + J, Size);
|
||||
I += Size;
|
||||
J -= Size;
|
||||
}
|
||||
}
|
||||
if (J != Lo) {
|
||||
_swap (B + J, B + Lo, Size);
|
||||
}
|
||||
if (((unsigned) J) * 2 > (Hi + Lo)) {
|
||||
QuickSort (Base, J + Size, Hi, Size, Compare);
|
||||
Hi = J - Size;
|
||||
} else {
|
||||
QuickSort (Base, Lo, J - Size, Size, Compare);
|
||||
Lo = J + Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void qsort (void* base, size_t nmemb, size_t size,
|
||||
int (*compare)(const void*, const void*))
|
||||
/* Quicksort implementation */
|
||||
{
|
||||
if (nmemb > 1) {
|
||||
QuickSort (base, 0, (nmemb-1) * size, size, compare);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
63
libsrc/common/rand.s
Normal file
63
libsrc/common/rand.s
Normal file
@@ -0,0 +1,63 @@
|
||||
;
|
||||
; Randum number generator
|
||||
;
|
||||
; Written and donated by Sidney Cadot - sidney@ch.twi.tudelft.nl
|
||||
;
|
||||
; May be distributed with the cc65 runtime using the same license.
|
||||
;
|
||||
;
|
||||
; int rand (void);
|
||||
; void srand (unsigned seed);
|
||||
;
|
||||
; Uses 4-byte state.
|
||||
; Multiplier must be 1 (mod 4)
|
||||
; Added value must be 1 (mod 2)
|
||||
; This guarantees max. period (2**32)
|
||||
; Bits 8-22 are returned (positive 2-byte int)
|
||||
; where 0 is LSB, 31 is MSB.
|
||||
; This is better as lower bits exhibit easily
|
||||
; detectable patterns.
|
||||
;
|
||||
|
||||
.export _rand, _srand
|
||||
|
||||
.bss
|
||||
|
||||
rand: .res 4 ; Seed
|
||||
|
||||
.code
|
||||
|
||||
_rand: clc
|
||||
lda rand+0 ; SEED *= $01010101
|
||||
adc rand+1
|
||||
sta rand+1
|
||||
adc rand+2
|
||||
sta rand+2
|
||||
adc rand+3
|
||||
sta rand+3
|
||||
clc
|
||||
lda rand+0 ; SEED += $31415927
|
||||
adc #$27
|
||||
sta rand+0
|
||||
lda rand+1
|
||||
adc #$59
|
||||
sta rand+1
|
||||
pha
|
||||
lda rand+2
|
||||
adc #$41
|
||||
sta rand+2
|
||||
and #$7f ; Suppress sign bit (make it positive)
|
||||
tax
|
||||
lda rand+3
|
||||
adc #$31
|
||||
sta rand+3
|
||||
pla ; return bit 8-22 in (X,A)
|
||||
rts
|
||||
|
||||
_srand: sta rand+0 ; Store the seed
|
||||
stx rand+1
|
||||
lda #0
|
||||
sta rand+2 ; Set MSW to zero
|
||||
sta rand+3
|
||||
rts
|
||||
|
||||
78
libsrc/common/realloc.c
Normal file
78
libsrc/common/realloc.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* realloc.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 06.06.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "_heap.h"
|
||||
|
||||
|
||||
|
||||
void* realloc (void* block, size_t size)
|
||||
{
|
||||
unsigned* b;
|
||||
unsigned* newblock;
|
||||
unsigned oldsize;
|
||||
int diff;
|
||||
|
||||
/* Check the block parameter */
|
||||
if (!block) {
|
||||
/* Block is NULL, same as malloc */
|
||||
return malloc (size);
|
||||
}
|
||||
|
||||
/* Check the size parameter */
|
||||
if (size == 0) {
|
||||
/* Block is not NULL, but size is: free the block */
|
||||
free (block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the internal used size from the given size */
|
||||
size += HEAP_ADMIN_SPACE;
|
||||
if (size < sizeof (struct freeblock)) {
|
||||
size = sizeof (struct freeblock);
|
||||
}
|
||||
|
||||
/* Get a pointer to the real block, get the old block size */
|
||||
b = (unsigned*) (((int) block) - 2);
|
||||
oldsize = *b;
|
||||
|
||||
/* Get the size difference as a signed quantity */
|
||||
diff = size - oldsize;
|
||||
|
||||
/* Is the block at the current heap top? */
|
||||
if (((int) b) + oldsize == ((int) _hptr)) {
|
||||
/* Check if we've enough memory at the heap top */
|
||||
int newhptr;
|
||||
newhptr = ((int) _hptr) + diff;
|
||||
if (newhptr <= ((int) _hend)) {
|
||||
/* Ok, there's space enough */
|
||||
_hptr = (unsigned*) newhptr;
|
||||
*b = size;
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
/* The given block was not located on top of the heap, or there's no
|
||||
* room left. Try to allocate a new block and copy the data.
|
||||
*/
|
||||
if (newblock = malloc (size)) {
|
||||
memcpy (newblock, block, oldsize - 2);
|
||||
free (block);
|
||||
}
|
||||
return newblock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
52
libsrc/common/setjmp.s
Normal file
52
libsrc/common/setjmp.s
Normal file
@@ -0,0 +1,52 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 06.06.1998
|
||||
;
|
||||
; int setjmp (jmp_buf buf);
|
||||
;
|
||||
|
||||
.export __setjmp
|
||||
.importzp sp, ptr1
|
||||
|
||||
__setjmp:
|
||||
sta ptr1 ; Save buf
|
||||
stx ptr1+1
|
||||
ldy #0
|
||||
|
||||
; The parameter stack is now empty, put it into buf
|
||||
|
||||
lda sp
|
||||
sta (ptr1),y
|
||||
iny
|
||||
lda sp+1
|
||||
sta (ptr1),y
|
||||
iny
|
||||
|
||||
; Put the return stack pointer next
|
||||
|
||||
tsx
|
||||
inx
|
||||
inx ; drop return address
|
||||
txa
|
||||
sta (ptr1),y
|
||||
iny
|
||||
|
||||
; Last thing is the return address.
|
||||
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
sta (ptr1),y ; high byte first
|
||||
iny
|
||||
pha
|
||||
txa
|
||||
sta (ptr1),y
|
||||
pha
|
||||
|
||||
; Return zero
|
||||
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
|
||||
|
||||
26
libsrc/common/sprintf.c
Normal file
26
libsrc/common/sprintf.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* sprintf.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
int sprintf (char* /*buf*/, char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
|
||||
/* Do formatting and output. Since we know, that va_end is empty, we don't
|
||||
* call it here, saving an extra variable and some code.
|
||||
*/
|
||||
return vsprintf ((char*) va_fix (ap, 1), (char*) va_fix (ap, 2), ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
48
libsrc/common/stkcheck.s
Normal file
48
libsrc/common/stkcheck.s
Normal file
@@ -0,0 +1,48 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 18.08.1998
|
||||
;
|
||||
; Stack checker
|
||||
;
|
||||
|
||||
|
||||
.export _stkcheck, __stksafety
|
||||
.import pushax, exit
|
||||
.import __hend
|
||||
.importzp sp
|
||||
|
||||
.data
|
||||
__stksafety:
|
||||
.word 64 ;
|
||||
|
||||
.code
|
||||
_stkcheck:
|
||||
clc
|
||||
lda __hend
|
||||
adc __stksafety
|
||||
tax ; Remember low byte
|
||||
lda __hend+1
|
||||
adc __stksafety+1
|
||||
|
||||
cmp sp+1
|
||||
bcc Ok
|
||||
bne L1
|
||||
cpx sp
|
||||
bcc Ok
|
||||
|
||||
; Stack overflow
|
||||
|
||||
L1: inc sp+1 ; Create 256 bytes of space
|
||||
ldx #0
|
||||
lda #4
|
||||
jsr pushax
|
||||
jmp exit
|
||||
|
||||
; All is well
|
||||
|
||||
Ok: rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
57
libsrc/common/strcat.s
Normal file
57
libsrc/common/strcat.s
Normal file
@@ -0,0 +1,57 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; char* strcat (char* dest, const char* src);
|
||||
;
|
||||
|
||||
.export _strcat
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
_strcat:
|
||||
sta ptr1 ; Save src
|
||||
stx ptr1+1
|
||||
jsr popax ; Get dest
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
sta ptr3 ; Remember for function return
|
||||
stx ptr3+1
|
||||
ldy #0
|
||||
|
||||
; find end of dest
|
||||
|
||||
sc1: lda (ptr2),y
|
||||
beq sc2
|
||||
iny
|
||||
bne sc1
|
||||
inc ptr2+1
|
||||
bne sc1
|
||||
|
||||
; end found, get offset in y into pointer
|
||||
|
||||
sc2: tya
|
||||
clc
|
||||
adc ptr2
|
||||
sta ptr2
|
||||
bcc sc3
|
||||
inc ptr2+1
|
||||
|
||||
; copy src
|
||||
|
||||
sc3: ldy #0
|
||||
sc4: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
beq sc5
|
||||
iny
|
||||
bne sc4
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne sc4
|
||||
|
||||
; done, return pointer to dest
|
||||
|
||||
sc5: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts
|
||||
|
||||
|
||||
41
libsrc/common/strchr.s
Normal file
41
libsrc/common/strchr.s
Normal file
@@ -0,0 +1,41 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; const char* strchr (const char* s, int c);
|
||||
;
|
||||
|
||||
.export _strchr
|
||||
.import popax
|
||||
.importzp ptr1, tmp1
|
||||
|
||||
_strchr:
|
||||
sta tmp1 ; Save c
|
||||
jsr popax ; get s
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #0
|
||||
|
||||
scloop: lda (ptr1),y ; get next char
|
||||
beq strz ; jump if end of string
|
||||
cmp tmp1 ; found?
|
||||
beq strf ; jump if yes
|
||||
iny
|
||||
bne scloop
|
||||
inc ptr1+1
|
||||
bne scloop ; jump always
|
||||
|
||||
; found, calculate pointer to c
|
||||
|
||||
strf: ldx ptr1+1 ; get high byte of pointer
|
||||
tya ; low byte offset
|
||||
clc
|
||||
adc ptr1
|
||||
bcc str1
|
||||
inx
|
||||
str1: rts
|
||||
|
||||
; not found, return zero
|
||||
|
||||
strz: tax ; return 0
|
||||
rts
|
||||
|
||||
35
libsrc/common/strcmp.s
Normal file
35
libsrc/common/strcmp.s
Normal file
@@ -0,0 +1,35 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; int strcmp (const char* s1, const char* s2);
|
||||
;
|
||||
|
||||
.export _strcmp
|
||||
.import popax
|
||||
.importzp ptr1, ptr2
|
||||
|
||||
_strcmp:
|
||||
sta ptr2 ; Save s2
|
||||
stx ptr2+1
|
||||
jsr popax ; Get s1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #0
|
||||
|
||||
loop: lda (ptr1),y
|
||||
cmp (ptr2),y
|
||||
bne L1
|
||||
tax ; end of strings?
|
||||
beq L3
|
||||
iny
|
||||
bne loop
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne loop
|
||||
|
||||
L1: bcs L2
|
||||
ldx #$FF
|
||||
rts
|
||||
|
||||
L2: ldx #$01
|
||||
L3: rts
|
||||
13
libsrc/common/strcoll.s
Normal file
13
libsrc/common/strcoll.s
Normal file
@@ -0,0 +1,13 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.12.1998
|
||||
;
|
||||
; int strcoll (const char* s1, const char* s2);
|
||||
;
|
||||
; Since we don't have locales, this function is equivalent to strcmp.
|
||||
;
|
||||
|
||||
.export _strcoll
|
||||
.import _strcmp
|
||||
|
||||
_strcoll = _strcmp
|
||||
|
||||
33
libsrc/common/strcpy.s
Normal file
33
libsrc/common/strcpy.s
Normal file
@@ -0,0 +1,33 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; char* strcpy (char* dest, const char* src);
|
||||
;
|
||||
|
||||
.export _strcpy
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
_strcpy:
|
||||
sta ptr1 ; Save src
|
||||
stx ptr1+1
|
||||
jsr popax ; Get dest
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
sta ptr3 ; remember for function return
|
||||
stx ptr3+1
|
||||
ldy #$00
|
||||
|
||||
L1: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
beq L9
|
||||
iny
|
||||
bne L1
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne L1
|
||||
|
||||
L9: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts
|
||||
|
||||
54
libsrc/common/strcspn.s
Normal file
54
libsrc/common/strcspn.s
Normal file
@@ -0,0 +1,54 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.06.1998
|
||||
;
|
||||
; size_t strcspn (const char* s1, const char* s2);
|
||||
;
|
||||
|
||||
.export _strcspn
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, tmp1, tmp2, tmp3
|
||||
|
||||
_strcspn:
|
||||
sta ptr2 ; Save s2
|
||||
stx ptr2+1
|
||||
jsr popax ; Get s1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldx #0 ; low counter byte
|
||||
stx tmp1 ; high counter byte
|
||||
ldy #$00
|
||||
|
||||
L1: lda (ptr1),y ; get next char from s1
|
||||
beq L6 ; jump if done
|
||||
sta tmp2 ; save char
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
L2: sty tmp3 ; save index into s1
|
||||
|
||||
ldy #0 ; get index into s2
|
||||
L3: lda (ptr2),y ;
|
||||
beq L4 ; jump if done
|
||||
cmp tmp2
|
||||
beq L6
|
||||
iny
|
||||
bne L3
|
||||
|
||||
; The character was not found in s2. Increment the counter and start over
|
||||
|
||||
L4: ldy tmp3 ; reload index
|
||||
inx
|
||||
bne L1
|
||||
inc tmp1
|
||||
bne L1
|
||||
|
||||
; The character was found, or we reached the end of s1. Return count of
|
||||
; characters
|
||||
|
||||
L6: txa ; get low counter byte
|
||||
ldx tmp1 ; get high counter byte
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
25
libsrc/common/strdup.c
Normal file
25
libsrc/common/strdup.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* strdup.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
char* strdup (char* s)
|
||||
{
|
||||
char* p;
|
||||
p = malloc (strlen (s) + 1);
|
||||
if (p) {
|
||||
strcpy (p, s);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
29
libsrc/common/strerror.s
Normal file
29
libsrc/common/strerror.s
Normal file
@@ -0,0 +1,29 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 17.05.2000
|
||||
;
|
||||
; char* __fastcall__ strerror (int errcode);
|
||||
; /* Map an error number to an error message */
|
||||
;
|
||||
|
||||
.export _strerror
|
||||
.import __sys_errlist
|
||||
|
||||
.include "errno.inc"
|
||||
|
||||
_strerror:
|
||||
cpx #$00 ; High byte must be zero
|
||||
bne @L1 ; Jump if invalid error
|
||||
cmp #EMAX ; Valid error code (map EUNKNOWN to 0)?
|
||||
bcc @L2 ; Jump if ok
|
||||
@L1: lda #$00 ; "Unknown error"
|
||||
@L2: asl a ; * 2
|
||||
tay
|
||||
|
||||
; Load the pointer to the error message and return
|
||||
|
||||
lda __sys_errlist+1,y
|
||||
tax
|
||||
lda __sys_errlist,y
|
||||
rts
|
||||
|
||||
|
||||
59
libsrc/common/stricmp.s
Normal file
59
libsrc/common/stricmp.s
Normal file
@@ -0,0 +1,59 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 03.06.1998
|
||||
;
|
||||
; int stricmp (const char* s1, const char* s2); /* DOS way */
|
||||
; int strcasecmp (const char* s1, const char* s2); /* UNIX way */
|
||||
;
|
||||
|
||||
.export _stricmp, _strcasecmp
|
||||
.import popax
|
||||
.import __ctype, __cdiff
|
||||
.importzp ptr1, ptr2, tmp1
|
||||
|
||||
|
||||
_stricmp:
|
||||
_strcasecmp:
|
||||
sta ptr2 ; Save s2
|
||||
stx ptr2+1
|
||||
jsr popax ; get s1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #0
|
||||
|
||||
loop: lda (ptr2),y ; get char from second string
|
||||
tax
|
||||
lda __ctype,x ; get character classification
|
||||
and #$01 ; lower case char?
|
||||
beq L1 ; jump if no
|
||||
txa ; get character back
|
||||
clc
|
||||
adc __cdiff ; make upper case char
|
||||
tax ;
|
||||
L1: stx tmp1 ; remember upper case equivalent
|
||||
|
||||
lda (ptr1),y ; get character from first string
|
||||
tax
|
||||
lda __ctype,x ; get character classification
|
||||
and #$01 ; lower case char?
|
||||
beq L2 ; jump if no
|
||||
txa ; get character back
|
||||
clc
|
||||
adc __cdiff ; make upper case char
|
||||
tax
|
||||
|
||||
L2: cpx tmp1 ; compare characters
|
||||
bne L3
|
||||
txa ; end of strings?
|
||||
beq L5 ; a/x both zero
|
||||
iny
|
||||
bne loop
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne loop
|
||||
|
||||
L3: bcs L4
|
||||
ldx #$FF
|
||||
rts
|
||||
|
||||
L4: ldx #$01
|
||||
L5: rts
|
||||
26
libsrc/common/strlen.s
Normal file
26
libsrc/common/strlen.s
Normal file
@@ -0,0 +1,26 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; int strlen (const char* s);
|
||||
;
|
||||
|
||||
.export _strlen
|
||||
.importzp ptr1
|
||||
|
||||
_strlen:
|
||||
sta ptr1 ; Save s
|
||||
stx ptr1+1
|
||||
ldx #0 ; YX used as counter
|
||||
ldy #0
|
||||
|
||||
L1: lda (ptr1),y
|
||||
beq L9
|
||||
iny
|
||||
bne L1
|
||||
inc ptr1+1
|
||||
inx
|
||||
bne L1
|
||||
|
||||
L9: tya ; get low byte of counter, hi's all set
|
||||
rts
|
||||
|
||||
45
libsrc/common/strlower.s
Normal file
45
libsrc/common/strlower.s
Normal file
@@ -0,0 +1,45 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; char* strlower (char* s);
|
||||
; char* strlwr (char* s);
|
||||
;
|
||||
; Non-ANSI
|
||||
;
|
||||
|
||||
.export _strlower, _strlwr
|
||||
.import popax
|
||||
.import __ctype, __cdiff
|
||||
.importzp ptr1, ptr2
|
||||
|
||||
_strlower:
|
||||
_strlwr:
|
||||
sta ptr1 ; Save s (working copy)
|
||||
stx ptr1+1
|
||||
sta ptr2
|
||||
sta ptr2+2 ; save function result
|
||||
ldy #0
|
||||
|
||||
loop: lda (ptr1),y ; get character
|
||||
beq L9 ; jump if done
|
||||
tax
|
||||
lda __ctype,x ; get character classification
|
||||
and #$02 ; upper case char?
|
||||
beq L1 ; jump if no
|
||||
txa ; get character back into accu
|
||||
sec
|
||||
sbc __cdiff ; make lower case char
|
||||
sta (ptr1),y ; store back
|
||||
L1: iny ; next char
|
||||
bne loop
|
||||
inc ptr1+1 ; handle offset overflow
|
||||
bne loop ; branch always
|
||||
|
||||
; Done, return the argument string
|
||||
|
||||
L9: lda ptr2
|
||||
ldx ptr2+1
|
||||
rts
|
||||
|
||||
|
||||
|
||||
72
libsrc/common/strncat.s
Normal file
72
libsrc/common/strncat.s
Normal file
@@ -0,0 +1,72 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; char* strncat (char* dest, const char* src, size_t n);
|
||||
;
|
||||
|
||||
.export _strncat
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
|
||||
|
||||
_strncat:
|
||||
eor #$FF ; one's complement to count upwards
|
||||
sta tmp1
|
||||
txa
|
||||
eor #$FF
|
||||
sta tmp2
|
||||
jsr popax ; get src
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
jsr popax ; get dest
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
sta ptr3 ; remember for function return
|
||||
stx ptr3+1
|
||||
ldy #0
|
||||
|
||||
; find end of dest
|
||||
|
||||
L1: lda (ptr2),y
|
||||
beq L2
|
||||
iny
|
||||
bne L1
|
||||
inc ptr2+1
|
||||
bne L1
|
||||
|
||||
; end found, get offset in y into pointer
|
||||
|
||||
L2: tya
|
||||
clc
|
||||
adc ptr2
|
||||
sta ptr2
|
||||
bcc L3
|
||||
inc ptr2+1
|
||||
|
||||
; copy src. We've put the ones complement of the count into the counter, so
|
||||
; we'll increment the counter on top of the loop
|
||||
|
||||
L3: ldy #0
|
||||
ldx tmp1 ; low counter byte
|
||||
|
||||
L4: inx
|
||||
bne L5
|
||||
inc tmp2
|
||||
beq L6 ; jump if done
|
||||
L5: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
beq L7
|
||||
iny
|
||||
bne L4
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne L4
|
||||
|
||||
; done, set the trailing zero and return pointer to dest
|
||||
|
||||
L6: lda #0
|
||||
sta (ptr2),y
|
||||
L7: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts
|
||||
|
||||
|
||||
81
libsrc/common/strncmp.s
Normal file
81
libsrc/common/strncmp.s
Normal file
@@ -0,0 +1,81 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 25.05.2000
|
||||
;
|
||||
; int strncmp (const char* s1, const char* s2, unsigned n);
|
||||
;
|
||||
|
||||
.export _strncmp
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
|
||||
_strncmp:
|
||||
|
||||
; Convert the given counter value in a/x from a downward counter into an
|
||||
; upward counter, so we can increment the counter in the loop below instead
|
||||
; of decrementing it. This adds some overhead now, but is cheaper than
|
||||
; executing a more complex test in each iteration of the loop. We do also
|
||||
; correct the value by one, so we can do the test on top of the loop.
|
||||
|
||||
eor #$FF
|
||||
sta ptr3
|
||||
txa
|
||||
eor #$FF
|
||||
sta ptr3+1
|
||||
|
||||
; Get the remaining arguments
|
||||
|
||||
jsr popax ; get s2
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
jsr popax ; get s1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
; Loop setup
|
||||
|
||||
ldy #0
|
||||
|
||||
; Start of compare loop. Check the counter.
|
||||
|
||||
Loop: inc ptr3
|
||||
beq IncHi ; Increment high byte
|
||||
|
||||
; Compare a byte from the strings
|
||||
|
||||
Comp: lda (ptr1),y
|
||||
cmp (ptr2),y
|
||||
bne NotEqual ; Jump if strings different
|
||||
tax ; End of strings?
|
||||
beq Equal1 ; Jump if EOS reached, a/x == 0
|
||||
|
||||
; Increment the pointers
|
||||
|
||||
iny
|
||||
bne Loop
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne Loop ; Branch always
|
||||
|
||||
; Increment hi byte
|
||||
|
||||
IncHi: inc ptr3+1
|
||||
bne Comp ; Jump if counter not zero
|
||||
|
||||
; Exit code if strings are equal. a/x not set
|
||||
|
||||
Equal: lda #$00
|
||||
tax
|
||||
Equal1: rts
|
||||
|
||||
; Exit code if strings not equal
|
||||
|
||||
NotEqual:
|
||||
bcs L1
|
||||
ldx #$FF ; Make result negative
|
||||
rts
|
||||
|
||||
L1: ldx #$01 ; Make result positive
|
||||
rts
|
||||
|
||||
|
||||
98
libsrc/common/strncpy.s
Normal file
98
libsrc/common/strncpy.s
Normal file
@@ -0,0 +1,98 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; char* strncpy (char* dest, const char* src, unsigned size);
|
||||
;
|
||||
|
||||
.export _strncpy
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
|
||||
|
||||
_strncpy:
|
||||
sta tmp1 ; Save size
|
||||
stx tmp2
|
||||
jsr popax ; get src
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
jsr popax ; get dest
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
sta ptr3 ; remember for function return
|
||||
stx ptr3+1
|
||||
|
||||
ldy #$00
|
||||
ldx tmp1 ; Low byte of size
|
||||
beq L1
|
||||
|
||||
; Copy the first chunk < 256
|
||||
|
||||
jsr CopyChunk
|
||||
bcs L3 ; Jump if end of string found
|
||||
|
||||
; Copy full 256 byte chunks
|
||||
|
||||
L1: lda tmp2 ; High byte of size
|
||||
beq L3
|
||||
ldx #$00 ; Copy 256 bytes
|
||||
L2: jsr CopyChunk
|
||||
bcs L3
|
||||
dec tmp2
|
||||
bne L2
|
||||
beq L9
|
||||
|
||||
; Fill the remaining space with zeroes. If we come here, the value in X
|
||||
; is the low byte of the fill count, tmp2 holds the high byte. Y is the index
|
||||
; into the target string.
|
||||
|
||||
L3: tax ; Test low byte
|
||||
beq L4
|
||||
jsr FillChunk
|
||||
|
||||
L4: lda tmp2 ; Test high byte
|
||||
beq L9
|
||||
L5: jsr FillChunk
|
||||
dec tmp2
|
||||
bne L5
|
||||
|
||||
; Done - return a pointer to the string
|
||||
|
||||
L9: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts
|
||||
|
||||
|
||||
; -------------------------------------------------------------------
|
||||
; Copy byte count in X from ptr1 to ptr2
|
||||
|
||||
.proc CopyChunk
|
||||
L1: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
beq L3
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
L2: dex
|
||||
bne L1
|
||||
clc
|
||||
rts
|
||||
L3: sec
|
||||
rts
|
||||
.endproc
|
||||
|
||||
|
||||
; -------------------------------------------------------------------
|
||||
; Fill byte count in X with zeroes
|
||||
|
||||
.proc FillChunk
|
||||
lda #$00
|
||||
L1: sta (ptr1),y
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
L2: dex
|
||||
bne L1
|
||||
rts
|
||||
.endproc
|
||||
|
||||
|
||||
60
libsrc/common/strpbrk.s
Normal file
60
libsrc/common/strpbrk.s
Normal file
@@ -0,0 +1,60 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.06.1998
|
||||
;
|
||||
; char* strpbrk (const char* s1, const char* s2);
|
||||
;
|
||||
|
||||
.export _strpbrk
|
||||
.import popax, return0
|
||||
.importzp ptr1, ptr2, tmp1, tmp2, tmp3
|
||||
|
||||
_strpbrk:
|
||||
jsr popax ; get s2
|
||||
sta ptr2
|
||||
stx ptr2+1
|
||||
jsr popax ; get s1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #$00
|
||||
|
||||
L1: lda (ptr1),y ; get next char from s1
|
||||
beq L9 ; jump if done
|
||||
sta tmp2 ; save char
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
L2: sty tmp3 ; save index into s1
|
||||
|
||||
ldy #0 ; get index into s2
|
||||
L3: lda (ptr2),y ;
|
||||
beq L4 ; jump if done
|
||||
cmp tmp2
|
||||
beq L6
|
||||
iny
|
||||
bne L3
|
||||
|
||||
; The character was not found in s2. Increment the counter and start over
|
||||
|
||||
L4: ldy tmp3 ; reload index
|
||||
inx
|
||||
bne L1
|
||||
inc tmp1
|
||||
bne L1
|
||||
|
||||
; A character was found. Calculate a pointer to this char in s1 and return it.
|
||||
|
||||
L6: ldx ptr1+1
|
||||
lda tmp3 ; get y offset
|
||||
clc
|
||||
adc ptr1
|
||||
bcc L7
|
||||
inx
|
||||
L7: rts
|
||||
|
||||
; None of the characters in s2 was found - return NULL
|
||||
|
||||
L9: jmp return0
|
||||
|
||||
|
||||
|
||||
|
||||
47
libsrc/common/strrchr.s
Normal file
47
libsrc/common/strrchr.s
Normal file
@@ -0,0 +1,47 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 31.05.1998
|
||||
;
|
||||
; char* strrchr (const char* s, int c);
|
||||
;
|
||||
|
||||
.export _strrchr
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, tmp1
|
||||
|
||||
_strrchr:
|
||||
sta tmp1 ; Save c
|
||||
jsr popax ; get s
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
lda #0 ; function result = NULL
|
||||
sta ptr2
|
||||
sta ptr2+1
|
||||
tay
|
||||
|
||||
L1: lda (ptr1),y ; get next char
|
||||
beq L3 ; jump if end of string
|
||||
cmp tmp1 ; found?
|
||||
bne L2 ; jump if no
|
||||
|
||||
; Remember a pointer to the character
|
||||
|
||||
tya
|
||||
clc
|
||||
adc ptr1
|
||||
sta ptr2
|
||||
lda ptr1+1
|
||||
adc #$00
|
||||
sta ptr2+1
|
||||
|
||||
; Next char
|
||||
|
||||
L2: iny
|
||||
bne L1
|
||||
inc ptr1+1
|
||||
bne L1 ; jump always
|
||||
|
||||
; Return the pointer to the last occurrence
|
||||
|
||||
L3: lda ptr2
|
||||
ldx ptr2+1
|
||||
rts
|
||||
56
libsrc/common/strspn.s
Normal file
56
libsrc/common/strspn.s
Normal file
@@ -0,0 +1,56 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.06.1998
|
||||
;
|
||||
; size_t strspn (const char* s1, const char* s2);
|
||||
;
|
||||
|
||||
.export _strspn
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, tmp1, tmp2, tmp3
|
||||
|
||||
_strspn:
|
||||
sta ptr2 ; Save s2
|
||||
stx ptr2+1
|
||||
jsr popax ; get s1
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldx #0 ; low counter byte
|
||||
stx tmp1 ; high counter byte
|
||||
ldy #$00
|
||||
|
||||
L1: lda (ptr1),y ; get next char from s1
|
||||
beq L6 ; jump if done
|
||||
sta tmp2 ; save char
|
||||
iny
|
||||
bne L2
|
||||
inc ptr1+1
|
||||
L2: sty tmp3 ; save index into s1
|
||||
|
||||
ldy #0 ; get index into s2
|
||||
L3: lda (ptr2),y ;
|
||||
beq L6 ; jump if done
|
||||
cmp tmp2
|
||||
beq L4
|
||||
iny
|
||||
bne L3
|
||||
|
||||
; The character was found in s2. Increment the counter and start over
|
||||
|
||||
L4: ldy tmp3 ; reload index
|
||||
inx
|
||||
bne L1
|
||||
inc tmp1
|
||||
bne L1
|
||||
|
||||
; The character was not found, or we reached the end of s1. Return count of
|
||||
; characters
|
||||
|
||||
L6: txa ; get low counter byte
|
||||
ldx tmp1 ; get high counter byte
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
97
libsrc/common/strstr.s
Normal file
97
libsrc/common/strstr.s
Normal file
@@ -0,0 +1,97 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.12.1998
|
||||
;
|
||||
; char* strstr (const char* haystack, const char* needle);
|
||||
;
|
||||
|
||||
.export _strstr
|
||||
.import popax
|
||||
.importzp ptr1, ptr2, ptr3, ptr4, tmp1
|
||||
|
||||
_strstr:
|
||||
sta ptr2 ; Save needle
|
||||
stx ptr2+1
|
||||
sta ptr4 ; Setup temp copy for later
|
||||
|
||||
jsr popax ; Get haystack
|
||||
sta ptr1
|
||||
stx ptr1+1 ; Save haystack
|
||||
|
||||
; If needle is empty, return haystack
|
||||
|
||||
ldy #$00
|
||||
lda (ptr2),y ; Get first byte of needle
|
||||
beq @Found ; Needle is empty --> we're done
|
||||
|
||||
; Search for the beginning of the string (this is not an optimal search
|
||||
; strategy [in fact, it's pretty dumb], but it's simple to implement).
|
||||
|
||||
sta tmp1 ; Save start of needle
|
||||
@L1: lda (ptr1),y ; Get next char from haystack
|
||||
beq @NotFound ; Jump if end
|
||||
cmp tmp1 ; Start of needle found?
|
||||
beq @L2 ; Jump if so
|
||||
iny ; Next char
|
||||
bne @L1
|
||||
inc ptr1+1 ; Bump high byte
|
||||
bne @L1 ; Branch always
|
||||
|
||||
; We found the start of needle in haystack
|
||||
|
||||
@L2: tya ; Get offset
|
||||
clc
|
||||
adc ptr1
|
||||
sta ptr1 ; Make ptr1 point to start
|
||||
bcc @L3
|
||||
inc ptr1+1
|
||||
|
||||
; ptr1 points to the start of needle now. Setup temporary pointers for the
|
||||
; search. The low byte of ptr4 is already set.
|
||||
|
||||
@L3: sta ptr3
|
||||
lda ptr1+1
|
||||
sta ptr3+1
|
||||
lda ptr2+1
|
||||
sta ptr4+1
|
||||
ldy #1 ; First char is identical, so start on second
|
||||
|
||||
; Do the compare
|
||||
|
||||
@L4: lda (ptr4),y ; Get char from needle
|
||||
beq @Found ; Jump if end of needle (-> found)
|
||||
cmp (ptr3),y ; Compare with haystack
|
||||
bne @L5 ; Jump if not equal
|
||||
iny ; Next char
|
||||
bne @L4
|
||||
inc ptr3+1
|
||||
inc ptr4+1 ; Bump hi byte of pointers
|
||||
bne @L4 ; Next char (branch always)
|
||||
|
||||
; The strings did not compare equal, search next start of needle
|
||||
|
||||
@L5: ldy #1 ; Start after this char
|
||||
bne @L1 ; Branch always
|
||||
|
||||
; We found the start of needle
|
||||
|
||||
@Found: lda ptr1
|
||||
ldx ptr1+1
|
||||
rts
|
||||
|
||||
; We reached end of haystack without finding needle
|
||||
|
||||
@NotFound:
|
||||
lda #$00 ; return NULL
|
||||
tax
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
77
libsrc/common/strtok.c
Normal file
77
libsrc/common/strtok.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* strtok.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.12.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Memory location that holds the last input */
|
||||
static char* Last = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
char* strtok (char* s1, const char* s2)
|
||||
{
|
||||
char c;
|
||||
char* start;
|
||||
|
||||
/* Use the stored location if called with a NULL pointer */
|
||||
if (s1 == 0) {
|
||||
s1 = Last;
|
||||
}
|
||||
|
||||
/* If s1 is empty, there are no more tokens. Return 0 in this case. */
|
||||
if (*s1 == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search the address of the first element in s1 that equals none
|
||||
* of the characters in s2.
|
||||
*/
|
||||
while ((c = *s1) && strchr (s2, c) != 0) {
|
||||
++s1;
|
||||
}
|
||||
if (c == '\0') {
|
||||
/* No more tokens found */
|
||||
Last = s1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remember the start of the token */
|
||||
start = s1;
|
||||
|
||||
/* Search for the end of the token */
|
||||
while ((c = *s1) && strchr (s2, c) == 0) {
|
||||
++s1;
|
||||
}
|
||||
if (c == '\0') {
|
||||
/* Last element */
|
||||
Last = s1;
|
||||
} else {
|
||||
*s1 = '\0';
|
||||
Last = s1 + 1;
|
||||
}
|
||||
|
||||
/* Return the start of the token */
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
45
libsrc/common/strupper.s
Normal file
45
libsrc/common/strupper.s
Normal file
@@ -0,0 +1,45 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; char* strupper (char* s);
|
||||
; char* strupr (char* s);
|
||||
;
|
||||
; Non-ANSI
|
||||
;
|
||||
|
||||
.export _strupper, _strupr
|
||||
.import popax
|
||||
.import __ctype, __cdiff
|
||||
.importzp ptr1, ptr2
|
||||
|
||||
_strupper:
|
||||
_strupr:
|
||||
sta ptr1 ; Save s (working copy)
|
||||
stx ptr1+1
|
||||
sta ptr2
|
||||
sta ptr2+2 ; save function result
|
||||
ldy #0
|
||||
|
||||
loop: lda (ptr1),y ; get character
|
||||
beq L9 ; jump if done
|
||||
tax
|
||||
lda __ctype,x ; get character classification
|
||||
and #$01 ; lower case char?
|
||||
beq L1 ; jump if no
|
||||
txa ; get character back into accu
|
||||
clc
|
||||
adc __cdiff ; make upper case char
|
||||
sta (ptr1),y ; store back
|
||||
L1: iny ; next char
|
||||
bne loop
|
||||
inc ptr1+1 ; handle offset overflow
|
||||
bne loop ; branch always
|
||||
|
||||
; Done, return the argument string
|
||||
|
||||
L9: lda ptr2
|
||||
ldx ptr2+1
|
||||
rts
|
||||
|
||||
|
||||
|
||||
20
libsrc/common/strxfrm.c
Normal file
20
libsrc/common/strxfrm.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* strxfrm.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.12.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
size_t strxfrm (char* dest, const char* src, size_t count)
|
||||
{
|
||||
strncpy (dest, src, count);
|
||||
return strlen (src);
|
||||
}
|
||||
|
||||
|
||||
|
||||
22
libsrc/common/tolower.s
Normal file
22
libsrc/common/tolower.s
Normal file
@@ -0,0 +1,22 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
;
|
||||
; int tolower (int c);
|
||||
;
|
||||
|
||||
.export _tolower
|
||||
.import __ctype, __cdiff
|
||||
|
||||
_tolower:
|
||||
tay ; Get C into Y
|
||||
lda __ctype,y ; Get character classification
|
||||
and #$02 ; Is this an upper case char?
|
||||
beq L1 ; Jump if no
|
||||
tya ; Get char back into A
|
||||
sec
|
||||
sbc __cdiff ; make lower case char
|
||||
rts ; CC are set
|
||||
|
||||
L1: tya ; Get char back into A
|
||||
rts ; CC are set
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user