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:
uz
2000-05-28 13:40:48 +00:00
parent 579491e8a4
commit 53dd513176
847 changed files with 91345 additions and 0 deletions

40
libsrc/common/.cvsignore Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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