Added some parts of standard library

WARNING, this stuff should compile fine but it's untested. There's no
support for many functions atm.
master
Marcin Gasperowicz 11 years ago
parent e60e83ce68
commit 35b97557e7

1
.gitignore vendored

@ -1,3 +1,4 @@
.DS_Store
*.o
*.img
os/

@ -0,0 +1,176 @@
/*****************************************************************************/
/* */
/* ctype.h */
/* */
/* Character handling */
/* */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _CTYPE_H
#define _CTYPE_H
/* The array containing character classification data */
extern unsigned char _ctype[256];
/* Bits used to specify characters classes */
#define _CT_LOWER 0x01 /* 0 - Lower case char */
#define _CT_UPPER 0x02 /* 1 - Upper case char */
#define _CT_DIGIT 0x04 /* 2 - Numeric digit */
#define _CT_XDIGIT 0x08 /* 3 - Hex digit (both, lower and upper) */
#define _CT_CNTRL 0x10 /* 4 - Control character */
#define _CT_SPACE 0x20 /* 5 - The space character itself */
#define _CT_OTHER_WS 0x40 /* 6 - Other whitespace ('\f', '\n', '\r', '\t' and '\v') */
#define _CT_SPACE_TAB 0x80 /* 7 - Space or tab character */
/* Bit combinations */
#define _CT_ALNUM (_CT_LOWER | _CT_UPPER | _CT_DIGIT)
#define _CT_ALPHA (_CT_LOWER | _CT_UPPER)
#define _CT_NOT_GRAPH (_CT_CNTRL | _CT_SPACE)
#define _CT_NOT_PRINT (_CT_CNTRL)
#define _CT_NOT_PUNCT (_CT_SPACE | _CT_CNTRL | _CT_DIGIT | _CT_UPPER | _CT_LOWER)
#define _CT_WS (_CT_SPACE | _CT_OTHER_WS)
/* Character classification functions */
int __fastcall__ isalnum (int c);
int __fastcall__ isalpha (int c);
int __fastcall__ iscntrl (int c);
int __fastcall__ isdigit (int c);
int __fastcall__ isgraph (int c);
int __fastcall__ islower (int c);
int __fastcall__ isprint (int c);
int __fastcall__ ispunct (int c);
int __fastcall__ isspace (int c);
int __fastcall__ isupper (int c);
int __fastcall__ isxdigit (int c);
#if __CC65_STD__ >= __CC65_STD_C99__
int __fastcall__ isblank (int c); /* New in C99 */
#endif
int __fastcall__ toupper (int c); /* Always external */
int __fastcall__ tolower (int c); /* Always external */
/* When inlining of known function is enabled, overload most of the above
* functions by macros. The function prototypes are again available after
* #undef'ing the macros.
* Please note that the following macros do NOT handle EOF correctly, as
* stated in the manual. If you need correct behaviour for EOF, don't
* use -Os, or #undefine the following macros.
*/
#ifdef __OPT_s__
#define isalnum(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_ALNUM), \
__AX__)
#define isalpha(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_ALPHA), \
__AX__)
#if __CC65_STD__ >= __CC65_STD_C99__
#define isblank(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_SPACE_TAB), \
__AX__)
#endif
#define iscntrl(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_CNTRL), \
__AX__)
#define isdigit(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_DIGIT), \
__AX__)
#define isgraph(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("eor #%b", _CT_NOT_GRAPH), \
__asm__ ("and #%b", _CT_NOT_GRAPH), \
__AX__)
#define islower(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_LOWER), \
__AX__)
#define isprint(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("eor #%b", _CT_NOT_PRINT), \
__asm__ ("and #%b", _CT_NOT_PRINT), \
__AX__)
#define ispunct(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("eor #%b", _CT_NOT_PUNCT), \
__asm__ ("and #%b", _CT_NOT_PUNCT), \
__AX__)
#define isspace(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_WS), \
__AX__)
#define isupper(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_UPPER), \
__AX__)
#define isxdigit(c) (__AX__ = (c), \
__asm__ ("tay"), \
__asm__ ("lda %v,y", _ctype), \
__asm__ ("and #%b", _CT_XDIGIT), \
__AX__)
#endif
/* End of ctype.h */
#endif

@ -0,0 +1,81 @@
/*****************************************************************************/
/* */
/* errno.h */
/* */
/* Error codes */
/* */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _ERRNO_H
#define _ERRNO_H
/* Operating system specific error codes */
extern unsigned char _oserror;
/* Mapper function, don't call directly */
void _maperrno (void);
/* This one is called under the hood. User callable. */
int __fastcall__ _osmaperrno (unsigned char oserror);
/* System error codes go here */
extern int _errno;
/* errno must be a macro, here the mapper is called */
#define errno (_maperrno(), _errno)
/* Possible error codes */
#define ENOENT 1 /* No such file or directory */
#define ENOMEM 2 /* Out of memory */
#define EACCES 3 /* Permission denied */
#define ENODEV 4 /* No such device */
#define EMFILE 5 /* Too many open files */
#define EBUSY 6 /* Device or resource busy */
#define EINVAL 7 /* Invalid argument */
#define ENOSPC 8 /* No space left on device */
#define EEXIST 9 /* File exists */
#define EAGAIN 10 /* Try again */
#define EIO 11 /* I/O error */
#define EINTR 12 /* Interrupted system call */
#define ENOSYS 13 /* Function not implemented */
#define ESPIPE 14 /* Illegal seek */
#define ERANGE 15 /* Range error */
#define EUNKNOWN 16 /* Unknown OS specific error */
#endif

@ -0,0 +1,72 @@
/*****************************************************************************/
/* */
/* limits.h */
/* */
/* Sizes of integer types */
/* */
/* */
/* */
/* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _LIMITS_H
#define _LIMITS_H
#define CHAR_BIT 8
#define SCHAR_MIN ((signed char) 0x80)
#define SCHAR_MAX 127
#define UCHAR_MAX 255
#define CHAR_MIN 0
#define CHAR_MAX 255
#define SHRT_MIN ((short) 0x8000)
#define SHRT_MAX 32767
#define USHRT_MAX 65535U
#define INT_MIN ((int) 0x8000)
#define INT_MAX 32767
#define UINT_MAX 65535U
#define LONG_MAX 2147483647L
#define LONG_MIN ((long) 0x80000000)
#define ULONG_MAX 4294967295UL
/* End of limits.h */
#endif

@ -0,0 +1,57 @@
/*****************************************************************************/
/* */
/* stdarg.h */
/* */
/* Variable arguments */
/* */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _STDARG_H
#define _STDARG_H
typedef unsigned char* va_list;
#define va_start(ap, fix) ap = ((va_list)&(fix))
#define va_arg(ap,type) (*(type*)(ap -= ((sizeof (type) + 1) & ~1)))
#if __CC65_STD__ >= __CC65_STD_C99__
#define va_copy(dest, src) ((dest)=(src))
#endif
#define va_end(ap)
/* End of stdarg.h */
#endif

@ -0,0 +1,53 @@
/*****************************************************************************/
/* */
/* stdbool.h */
/* */
/* C99 Boolean definitions */
/* */
/* */
/* */
/* (C) 2002 Greg King */
/* */
/* */
/* This software is provided "as-is," without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment, in the product's documentation, */
/* would be appreciated, but is not required. */
/* 2. Alterred source versions must be marked plainly as such, */
/* and must not be misrepresented as being the original software. */
/* 3. This notice may not be removed or alterred */
/* from any source distribution. */
/*****************************************************************************/
#ifndef _STDBOOL_H
#define _STDBOOL_H
#define bool _Bool
typedef unsigned char _Bool;
/* Standard test-results. */
#define false 0
#define true 1
/* All three names are macroes. */
#define __bool_true_false_are_defined 1
/* End of stdbool.h */
#endif

@ -0,0 +1,70 @@
/*****************************************************************************/
/* */
/* stddef.h */
/* */
/* Common definitions */
/* */
/* */
/* */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _STDDEF_H
#define _STDDEF_H
/* Standard data types */
#ifndef _HAVE_ptrdiff_t
#define _HAVE_ptrdiff_t
typedef int ptrdiff_t;
#endif
#ifndef _HAVE_wchar_t
#define _HAVE_wchar_t
typedef char wchar_t;
#endif
#ifndef _HAVE_size_t
#define _HAVE_size_t
typedef unsigned size_t;
#endif
/* NULL pointer */
#ifndef _HAVE_NULL
#define NULL 0
#define _HAVE_NULL
#endif
/* offsetof macro */
#define offsetof(type, member) (size_t) (&((type*) 0)->member)
/* End of stddef.h */
#endif

@ -0,0 +1,144 @@
/*****************************************************************************/
/* */
/* stdint.h */
/* */
/* Standard integer types */
/* */
/* */
/* */
/* (C) 2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
/* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks
* a 64 bit data types. The declarations have been adjusted accordingly.
*/
#ifndef _STDINT_H
#define _STDINT_H
/* Exact-width integer types */
typedef signed char int8_t;
typedef int int16_t;
typedef long int32_t;
typedef unsigned char uint8_t;
typedef unsigned uint16_t;
typedef unsigned long uint32_t;
#define INT8_MIN ((int8_t) 0x80)
#define INT8_MAX ((int8_t) 0x7F)
#define INT16_MIN ((int16_t) 0x8000)
#define INT16_MAX ((int16_t) 0x7FFF)
#define INT32_MIN ((int32_t) 0x80000000)
#define INT32_MAX ((int32_t) 0x7FFFFFFF)
#define UINT8_MAX ((uint8_t) 0xFF)
#define UINT16_MAX ((uint16_t) 0xFFFF)
#define UINT32_MAX ((uint32_t) 0xFFFFFFFF)
/* Minimum-width integer types */
typedef signed char int_least8_t;
typedef int int_least16_t;
typedef long int_least32_t;
typedef unsigned char uint_least8_t;
typedef unsigned uint_least16_t;
typedef unsigned long uint_least32_t;
#define INT_LEAST8_MIN ((int_least8_t) 0x80)
#define INT_LEAST8_MAX ((int_least8_t) 0x7F)
#define INT_LEAST16_MIN ((int_least16_t) 0x8000)
#define INT_LEAST16_MAX ((int_least16_t) 0x7FFF)
#define INT_LEAST32_MIN ((int_least32_t) 0x80000000)
#define INT_LEAST32_MAX ((int_least32_t) 0x7FFFFFFF)
#define UINT_LEAST8_MAX ((uint_least8_t) 0xFF)
#define UINT_LEAST16_MAX ((uint_least16_t) 0xFFFF)
#define UINT_LEAST32_MAX ((uint_least32_t) 0xFFFFFFFF)
/* Fastest minimum-width integer types */
typedef signed char int_fast8_t;
typedef int int_fast16_t;
typedef long int_fast32_t;
typedef unsigned char uint_fast8_t;
typedef unsigned uint_fast16_t;
typedef unsigned long uint_fast32_t;
#define INT_FAST8_MIN ((int_fast8_t) 0x80)
#define INT_FAST8_MAX ((int_fast8_t) 0x7F)
#define INT_FAST16_MIN ((int_fast16_t) 0x8000)
#define INT_FAST16_MAX ((int_fast16_t) 0x7FFF)
#define INT_FAST32_MIN ((int_fast32_t) 0x80000000)
#define INT_FAST32_MAX ((int_fast32_t) 0x7FFFFFFF)
#define UINT_FAST8_MAX ((uint_fast8_t) 0xFF)
#define UINT_FAST16_MAX ((uint_fast16_t) 0xFFFF)
#define UINT_FAST32_MAX ((uint_fast32_t) 0xFFFFFFFF)
/* Integer types capable of holding object pointers */
typedef int intptr_t;
typedef unsigned uintptr_t;
#define INTPTR_MIN ((intptr_t)0x8000)
#define INTPTR_MAX ((intptr_t)0x7FFF)
#define UINTPTR_MAX ((uintptr_t) 0xFFFF)
/* Greatest width integer types */
typedef long intmax_t;
typedef unsigned long uintmax_t;
#define INTMAX_MIN ((intmax_t) 0x80000000)
#define INTMAX_MAX ((intmax_t) 0x7FFFFFFF)
#define UINTMAX_MAX ((uintmax_t) 0xFFFFFFFF)
/* Limits of other integer types */
#define PTRDIFF_MIN ((int) 0x8000)
#define PTRDIFF_MAX ((int) 0x7FFF)
#define SIG_ATOMIC_MIN ((unsigned char) 0x00)
#define SIG_ATOMIC_MAX ((unsigned char) 0xFF)
#define SIZE_MAX 0xFFFF
/* Macros for minimum width integer constants */
#define INT8_C(c) c
#define INT16_C(c) c
#define INT32_C(c) c##L
#define UINT8_C(c) c##U
#define UINT16_C(c) c##U
#define UINT32_C(c) c##UL
/* Macros for greatest width integer constants */
#define INTMAX_C(c) c##L
#define UINTMAX_C(c) c##UL
/* End of stdint.h */
#endif

@ -0,0 +1,150 @@
/*****************************************************************************/
/* */
/* stdio.h */
/* */
/* Input/output */
/* */
/* */
/* */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _STDIO_H
#define _STDIO_H
#ifndef _STDDEF_H
# include <stddef.h>
#endif
#ifndef _STDARG_H
# include <stdarg.h>
#endif
/* Types */
typedef struct _FILE FILE;
typedef unsigned long fpos_t;
/* Standard file descriptors */
extern FILE* stdin;
extern FILE* stdout;
extern FILE* stderr;
/* Standard defines */
#define _IOFBF 0
#define _IOLBF 1
#define _IONBF 2
#define BUFSIZ 256
#define EOF -1
#define FOPEN_MAX 8
#define SEEK_CUR 0
#define SEEK_END 1
#define SEEK_SET 2
#define TMP_MAX 256
/* Standard defines that are platform dependent */
#if defined(__APPLE2__) || defined(__APPLE2ENH__)
# define FILENAME_MAX (64+1)
#elif defined(__ATARI__)
# define FILENAME_MAX (12+1)
#elif defined(__LUNIX__)
# define FILENAME_MAX (80+1)
#else
# define FILENAME_MAX (16+1)
#endif
#define L_tmpnam FILENAME_MAX
/*****************************************************************************/
/* Code */
/*****************************************************************************/
/* Functions */
void __fastcall__ clearerr (FILE* f);
int __fastcall__ fclose (FILE* f);
int __fastcall__ feof (FILE* f);
int __fastcall__ ferror (FILE* f);
int __fastcall__ fflush (FILE* f);
int __fastcall__ fgetc (FILE* f);
char* __fastcall__ fgets (char* buf, size_t size, FILE* f);
FILE* __fastcall__ fopen (const char* name, const char* mode);
int fprintf (FILE* f, const char* format, ...);
int __fastcall__ fputc (int c, FILE* f);
int __fastcall__ fputs (const char* s, FILE* f);
size_t __fastcall__ fread (void* buf, size_t size, size_t count, FILE* f);
FILE* __fastcall__ freopen (const char* name, const char* mode, FILE* f);
size_t __fastcall__ fwrite (const void* buf, size_t size, size_t count, FILE* f);
int __fastcall__ fgetpos (FILE* f, fpos_t *pos);
int __fastcall__ fsetpos (FILE* f, const fpos_t* pos);
long __fastcall__ ftell (FILE* f);
int __fastcall__ fseek (FILE* f, long offset, int whence);
void __fastcall__ rewind (FILE *f);
int __fastcall__ getchar (void);
char* __fastcall__ gets (char* s);
void __fastcall__ perror (const char* s);
int printf (const char* format, ...);
int __fastcall__ putchar (int c);
int __fastcall__ puts (const char* s);
int __fastcall__ remove (const char* name);
int __fastcall__ rename (const char* oldname, const char* newname);
int snprintf (char* buf, size_t size, const char* format, ...);
int sprintf (char* buf, const char* format, ...);
int __fastcall__ ungetc (int c, FILE* f);
int __fastcall__ vfprintf (FILE* f, const char* format, va_list ap);
int __fastcall__ vprintf (const char* format, va_list ap);
int __fastcall__ vsnprintf (char* buf, size_t size, const char* format, va_list ap);
int __fastcall__ vsprintf (char* buf, const char* format, va_list ap);
int scanf (const char* format, ...);
int fscanf (FILE* f, const char* format, ...);
int sscanf (const char* s, const char* format, ...);
int __fastcall__ vscanf (const char* format, va_list ap);
int __fastcall__ vsscanf (const char* s, const char* format, va_list ap);
int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap);
#if __CC65_STD__ == __CC65_STD_CC65__
FILE* __fastcall__ fdopen (int fd, const char* mode); /* Unix */
int __fastcall__ fileno (FILE* f); /* Unix */
#endif
void __fastcall__ _poserror (const char* msg); /* cc65 */
/* Masking macros for some functions */
#define getc(f) fgetc (f) /* ANSI */
#define putc(c, f) fputc (c, f) /* ANSI */
/* End of stdio.h */
#endif

@ -0,0 +1,136 @@
/*****************************************************************************/
/* */
/* stdlib.h */
/* */
/* General utilities */
/* */
/* */
/* */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _STDLIB_H
#define _STDLIB_H
/* size_t is needed */
#ifndef _HAVE_size_t
typedef unsigned size_t;
#define _HAVE_size_t
#endif
/* Standard exit codes */
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
/* Return type of the div function */
typedef struct {
int rem;
int quot;
} div_t;
/* Return type of the ldiv function (which currently doesn't exist) */
typedef struct {
long rem;
long quot;
} ldiv_t;
/* Memory management */
void* __fastcall__ malloc (size_t size);
void* __fastcall__ calloc (size_t count, size_t size);
void* __fastcall__ realloc (void* block, size_t size);
void __fastcall__ free (void* block);
/* Non standard memory management functions */
#if __CC65_STD__ == __CC65_STD_CC65__
int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size);
/* Allocate a block of memory with the given "size", which is aligned to a
* memory address that is a multiple of "alignment". "alignment" MUST NOT be
* zero, and MUST be a power of two; otherwise, this function will return
* EINVAL. The function returns ENOMEM if not enough memory is available
* to satisfy the request. "memptr" must point to a variable; that variable
* will return the address of the allocated memory. Use free() to release that
* allocated block.
*/
#endif
void __fastcall__ _heapadd (void* mem, size_t size);
/* Add a block to the heap */
size_t __fastcall__ _heapblocksize (const void* block);
/* Return the size of an allocated block */
size_t __fastcall__ _heapmemavail (void);
/* Return the total free heap space */
size_t __fastcall__ _heapmaxavail (void);
/* Return the size of the largest free block on the heap */
/* Random numbers */
#define RAND_MAX 0x7FFF
int rand (void);
void __fastcall__ srand (unsigned seed);
void _randomize (void); /* Non-standard */
/* Other standard stuff */
void abort (void);
int __fastcall__ abs (int val);
long __fastcall__ labs (long val);
int __fastcall__ atoi (const char* s);
long __fastcall__ atol (const char* s);
int __fastcall__ atexit (void (*exitfunc) (void));
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
size_t size, int (*cmp) (const void*, const void*));
div_t __fastcall__ div (int numer, int denom);
void __fastcall__ exit (int ret);
char* __fastcall__ getenv (const char* name);
void __fastcall__ qsort (void* base, size_t count, size_t size,
int (*compare) (const void*, const void*));
long __fastcall__ strtol (const char* nptr, char** endptr, int base);
unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base);
int __fastcall__ system (const char* s);
/* Non-ANSI functions */
void __fastcall__ _swap (void* p, void* q, size_t size);
#if __CC65_STD__ == __CC65_STD_CC65__
char* __fastcall__ itoa (int val, char* buf, int radix);
char* __fastcall__ utoa (unsigned val, char* buf, int radix);
char* __fastcall__ ltoa (long val, char* buf, int radix);
char* __fastcall__ ultoa (unsigned long val, char* buf, int radix);
int __fastcall__ putenv (char* s);
#endif
/* End of stdlib.h */
#endif

@ -0,0 +1,95 @@
/*****************************************************************************/
/* */
/* string.h */
/* */
/* String handling */
/* */
/* */
/* */
/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _STRING_H
#define _STRING_H
#include <stddef.h>
char* __fastcall__ strcat (char* dest, const char* src);
char* __fastcall__ strchr (const char* s, int c);
int __fastcall__ strcmp (const char* s1, const char* s2);
int __fastcall__ strcoll (const char* s1, const char* s2);
char* __fastcall__ strcpy (char* dest, const char* src);
size_t __fastcall__ strcspn (const char* s1, const char* s2);
char* __fastcall__ strerror (int errcode);
size_t __fastcall__ strlen (const char* s);
char* __fastcall__ strncat (char* s1, const char* s2, size_t count);
int __fastcall__ strncmp (const char* s1, const char* s2, size_t count);
char* __fastcall__ strncpy (char* dest, const char* src, size_t count);
char* __fastcall__ strrchr (const char* s, int c);
size_t __fastcall__ strspn (const char* s1, const char* s2);
char* __fastcall__ strstr (const char* str, const char* substr);
char* __fastcall__ strtok (char* s1, const char* s2);
size_t __fastcall__ strxfrm (char* s1, const char* s2, size_t count);
void* __fastcall__ memchr (const void* mem, int c, size_t count);
int __fastcall__ memcmp (const void* p1, const void* p2, size_t count);
void* __fastcall__ memcpy (void* dest, const void* src, size_t count);
void* __fastcall__ memmove (void* dest, const void* src, size_t count);
void* __fastcall__ memset (void* s, int c, size_t count);
/* The following is an internal function, the compiler will replace memset
* with it if the fill value is zero. Never use this one directly!
*/
void* __fastcall__ _bzero (void* ptr, size_t n);
/* Non standard: */
#if __CC65_STD__ == __CC65_STD_CC65__
void __fastcall__ bzero (void* ptr, size_t n); /* BSD */
char* __fastcall__ strdup (const char* s); /* SYSV/BSD */
int __fastcall__ stricmp (const char* s1, const char* s2); /* DOS/Windows */
int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */
int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count); /* DOS/Windows */
int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count); /* Same for Unix */
char* __fastcall__ strlwr (char* s);
char* __fastcall__ strlower (char* s);
char* __fastcall__ strupr (char* s);
char* __fastcall__ strupper (char* s);
#endif
const char* __fastcall__ _stroserror (unsigned char errcode);
/* Map an operating system error number to an error message. */
/* End of string.h */
#endif

@ -0,0 +1,29 @@
;
; Definitions for the character type tables
;
; Ullrich von Bassewitz, 08.09.2001
;
; Make the __ctype table an exported/imported symbol
.global __ctype
; Define bitmapped constants for the table entries
CT_NONE = $00 ; Nothing special
CT_LOWER = $01 ; 0 - Lower case char
CT_UPPER = $02 ; 1 - Upper case char
CT_DIGIT = $04 ; 2 - Numeric digit
CT_XDIGIT = $08 ; 3 - Hex digit (both, lower and upper)
CT_CTRL = $10 ; 4 - Control character
CT_SPACE = $20 ; 5 - The space character itself
CT_OTHER_WS = $40 ; 6 - Other whitespace ('\f', '\n', '\r', '\t' and '\v')
CT_SPACE_TAB = $80 ; 7 - Space or tab character
; Combined stuff
CT_ALNUM = (CT_LOWER | CT_UPPER | CT_DIGIT)
CT_ALPHA = (CT_LOWER | CT_UPPER)
CT_CTRL_SPACE = (CT_CTRL | CT_SPACE)
CT_NOT_PUNCT = (CT_SPACE | CT_CTRL | CT_DIGIT | CT_UPPER | CT_LOWER)

@ -35,11 +35,17 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include --cpu $(
%.lst : %.s
@$(AS) $(AFLAGS) -l -o /dev/null $<
#--------------------------------------------------------------------------
# Object files
# From C source-files
# C_OBJS = _afailed.o \
C_OBJS = strtok.o \
strtol.o \
strtoul.o \
strxfrm.o
# strftime.o \
#_afailed.o \
# _hextab.o \
# _poserror.o \
# _scanf.o \
@ -70,134 +76,137 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include --cpu $(
# realloc.o \
# rewind.o \
# sleep.o \
# strftime.o \
# strtok.o \
# strtol.o \
# strtoul.o \
# strxfrm.o \
# system.o \
# timezone.o
# From assembly source-files
S_OBJS = zerobss.o copydata.o
#_cwd.o \
# _environ.o \
# _fdesc.o \
# _file.o \
# _fopen.o \
# _heap.o \
# _heapadd.o \
# _heapblocksize.o\
# _heapmaxavail.o \
# _heapmemavail.o \
# _oserror.o \
# _printf.o \
# _seterrno.o \
# _swap.o \
# _sys.o \
# abs.o \
# atexit.o \
# atoi.o \
# calloc.o \
# chdir.o \
# copydata.o \
# creat.o \
# ctime.o \
# divt.o \
# errno.o \
# fclose.o \
# fmisc.o \
# fopen.o \
# fprintf.o \
# fread.o \
# free.o \
# fscanf.o \
# fwrite.o \
# getcpu.o \
# getcwd.o \
# getenv.o \
# interrupt.o \
# isalnum.o \
# isalpha.o \
# isblank.o \
# iscntrl.o \
# isdigit.o \
# isgraph.o \
# islower.o \
# isprint.o \
# ispunct.o \
# isspace.o \
# isupper.o \
# isxdigit.o \
# itoa.o \
# labs.o \
# longjmp.o \
# ltoa.o \
# malloc.o \
# maperrno.o \
# memchr.o \
# memcmp.o \
# memcpy.o \
# memmove.o \
# memset.o \
# mkdir.o \
# modfree.o \
# modload.o \
# oserrcheck.o \
# printf.o \
# putchar.o \
# putenv.o \
# rand.o \
# raise.o \
# remove.o \
# rename.o \
# rmdir.o \
# scanf.o \
# searchenv.o \
# setjmp.o \
# signal.o \
# sigtable.o \
# snprintf.o \
# sprintf.o \
# sscanf.o \
# strcat.o \
# strchr.o \
# strcmp.o \
# strcoll.o \
# strcpy.o \
# strcspn.o \
# strdup.o \
# strerror.o \
# stricmp.o \
# strlen.o \
# strlower.o \
# strncat.o \
# strncmp.o \
# strncpy.o \
# strnicmp.o \
# stroserr.o \
# strpbrk.o \
# strrchr.o \
# strspn.o \
# strstr.o \
# strtoimax.o \
# strtoumax.o \
# strupper.o \
# time.o \
# tolower.o \
# toupper.o \
# uname.o \
# ungetc.o \
# unlink.o \
# utscopy.o \
# vfprintf.o \
# vfscanf.o \
# vprintf.o \
# vscanf.o \
# vsnprintf.o \
# vsprintf.o \
# vsscanf.o \
# zerobss.o
S_OBJS = zerobss.o \
copydata.o \
abs.o \
atoi.o \
isalnum.o \
isalpha.o \
isblank.o \
iscntrl.o \
isdigit.o \
isgraph.o \
islower.o \
isprint.o \
ispunct.o \
isspace.o \
isupper.o \
isxdigit.o \
itoa.o \
memchr.o \
memcmp.o \
memcpy.o \
memmove.o \
memset.o \
# mkdir.o \
strcat.o \
strchr.o \
strcmp.o \
strcoll.o \
strcpy.o \
strcspn.o \
strdup.o \
strerror.o \
stricmp.o \
strlen.o \
strlower.o \
strncat.o \
strncmp.o \
strncpy.o \
strnicmp.o \
stroserr.o \
strpbrk.o \
strrchr.o \
strspn.o \
strstr.o \
strtoimax.o \
strtoumax.o \
strupper.o \
tolower.o \
toupper.o
# _cwd.o \
# _environ.o \
# _fdesc.o \
# _file.o \
# _fopen.o \
# _heap.o \
# _heapadd.o \
# _heapblocksize.o\
# _heapmaxavail.o \
# _heapmemavail.o \
# _oserror.o \
# _printf.o \
# _seterrno.o \
# _swap.o \
# _sys.o \
# atexit.o \
# calloc.o \
# chdir.o \
# copydata.o \
# creat.o \
# ctime.o \
# divt.o \
# errno.o \
# fclose.o \
# fmisc.o \
# fopen.o \
# fprintf.o \
# fread.o \
# free.o \
# fscanf.o \
# fwrite.o \
# getcpu.o \
# getcwd.o \
# getenv.o \
# interrupt.o \
# labs.o \
# longjmp.o \
# ltoa.o \
# malloc.o \
# maperrno.o \
# modfree.o \
# modload.o \
# oserrcheck.o \
# printf.o \
# putchar.o \
# putenv.o \
# rand.o \
# raise.o \
# remove.o \
# rename.o \
# rmdir.o \
# scanf.o \
# searchenv.o \
# setjmp.o \
# signal.o \
# sigtable.o \
# snprintf.o \
# sprintf.o \
# sscanf.o \
# time.o \
# uname.o \
# ungetc.o \
# unlink.o \s
# utscopy.o \
# vfprintf.o \
# vfscanf.o \
# vprintf.o \
# vscanf.o \
# vsnprintf.o \
# vsprintf.o \
# vsscanf.o \
# zerobss.o
#--------------------------------------------------------------------------

@ -0,0 +1,16 @@
;
; Ullrich von Bassewitz, 17.06.1998
;
; int abs (int x);
;
.export _abs
.import negax
_abs: cpx #$00 ; test hi byte
bpl L1
jmp negax ; Negate if negative
L1: rts

@ -0,0 +1,138 @@
;
; Ullrich von Bassewitz, 05.06.1998
;
; int atoi (const char* s);
; long atol (const char* s);
;
.export _atoi, _atol
.import negeax, __ctype
.importzp sreg, ptr1, ptr2, tmp1
.include "ctype.inc"
;
; 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 #CT_SPACE_TAB ; 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. Load the low 16 bit into A/X
L8: lda ptr2
ldx ptr2+1
; Negate the value if necessary, otherwise we're done
ldy tmp1 ; sign
beq L9 ; Branch if positive
; Negate the 32 bit value in ptr2/sreg
jmp negeax
;
; Helper functions
;
mul2: asl ptr2
rol ptr2+1
rol sreg
rol sreg+1 ; * 2
L9: rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isalnum (int c);
;
.export _isalnum
.include "ctype.inc"
_isalnum:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_ALNUM ; Mask character/digit bits
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isalpha (int c);
;
.export _isalpha
.include "ctype.inc"
_isalpha:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_ALPHA ; Mask character bits
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,23 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isblank (int c);
;
; cc65 (and GNU) extension.
;
.export _isblank
.include "ctype.inc"
_isblank:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_SPACE_TAB ; Mask blank bit
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int iscntrl (int c);
;
.export _iscntrl
.include "ctype.inc"
_iscntrl:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_CTRL ; Mask control character bit
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isdigit (int c);
;
.export _isdigit
.include "ctype.inc"
_isdigit:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_DIGIT ; Mask digit bit
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,22 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isgraph (int c);
;
.export _isgraph
.include "ctype.inc"
_isgraph:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
eor #CT_CTRL_SPACE ; NOT control and NOT space
and #CT_CTRL_SPACE ; Mask character bits
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int islower (int c);
;
.export _islower
.include "ctype.inc"
_islower:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_LOWER ; Mask lower char bit
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,22 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isprint (int c);
;
.export _isprint
.include "ctype.inc"
_isprint:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
eor #CT_CTRL ; NOT a control char
and #CT_CTRL ; Mask control char bit
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,22 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int ispunct (int c);
;
.export _ispunct
.include "ctype.inc"
_ispunct:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
eor #CT_NOT_PUNCT ; NOT (space | control | digit | alpha)
and #CT_NOT_PUNCT ; Mask relevant bits
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isspace (int c);
;
.export _isspace
.include "ctype.inc"
_isspace:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #(CT_SPACE | CT_OTHER_WS) ; Mask space bits
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isupper (int c);
;
.export _isupper
.include "ctype.inc"
_isupper:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_UPPER ; Mask upper char bit
rts
@L1: lda #$00 ; Return false
tax
rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int isxdigit (int c);
;
.export _isxdigit
.include "ctype.inc"
_isxdigit:
cpx #$00 ; Char range ok?
bne @L1 ; Jump if no
tay
lda __ctype,y ; Get character classification
and #CT_XDIGIT ; Mask xdigit bit
rts
@L1: lda #$00 ; Return false
tax
rts

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

@ -0,0 +1,57 @@
;
; Ullrich von Bassewitz, 2003-05-05
;
; void* __fastcall__ memchr (const void* p, int c, size_t n);
;
.export _memchr
.import popax, return0
.importzp ptr1, ptr2
.proc _memchr
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Save ones complement of n
jsr popax ; get c
pha
jsr popax ; get p
sta ptr1
stx ptr1+1
ldy #$00
pla ; Get c
ldx ptr2 ; Use X as low counter byte
L1: inx
beq L3
L2: cmp (ptr1),y
beq found
iny
bne L1
inc ptr1+1
bne L1 ; Branch always
L3: inc ptr2+1 ; Bump counter high byte
bne L2
; Not found, return NULL
notfound:
jmp return0
; Found, return pointer to char
found: ldx ptr1+1 ; get high byte of pointer
tya ; low byte offset
clc
adc ptr1
bcc L9
inx
L9: rts
.endproc

@ -0,0 +1,72 @@
;
; Ullrich von Bassewitz, 15.09.2000
;
; int memcmp (const void* p1, const void* p2, size_t count);
;
.export _memcmp
.import popax, return0
.importzp ptr1, ptr2, ptr3
_memcmp:
; Calculate (-count-1) and store it into ptr3. This is some overhead here but
; saves time in the compare loop
eor #$FF
sta ptr3
txa
eor #$FF
sta ptr3+1
; Get the pointer parameters
jsr popax ; Get p2
sta ptr2
stx ptr2+1
jsr popax ; Get p1
sta ptr1
stx ptr1+1
; Loop initialization
ldx ptr3 ; Load low counter byte into X
ldy #$00 ; Initialize pointer
; Head of compare loop: Test for the end condition
Loop: inx ; Bump low byte of (-count-1)
beq BumpHiCnt ; Jump on overflow
; Do the compare
Comp: lda (ptr1),y
cmp (ptr2),y
bne NotEqual ; Jump if bytes not equal
; Bump the pointers
iny ; Increment pointer
bne Loop
inc ptr1+1 ; Increment high bytes
inc ptr2+1
bne Loop ; Branch always (pointer wrap is illegal)
; Entry on low counter byte overflow
BumpHiCnt:
inc ptr3+1 ; Bump high byte of (-count-1)
bne Comp ; Jump if not done
jmp return0 ; Count is zero, areas are identical
; Not equal, check which one is greater
NotEqual:
bcs Greater
ldx #$FF ; Make result negative
rts
Greater:
ldx #$01 ; Make result positive
rts

@ -0,0 +1,80 @@
;
; Ullrich von Bassewitz, 2003-08-20
; Performance increase (about 20%) by
; Christian Krueger, 2009-09-13
;
; void* __fastcall__ memcpy (void* dest, const void* src, size_t n);
;
; NOTE: This function contains entry points for memmove, which will ressort
; to memcpy for an upwards copy. Don't change this module without looking
; at memmove!
;
.export _memcpy, memcpy_upwards, memcpy_getparams
.import popax
.importzp sp, ptr1, ptr2, ptr3
; ----------------------------------------------------------------------
_memcpy:
jsr memcpy_getparams
memcpy_upwards: ; assert Y = 0
ldx ptr3+1 ; Get high byte of n
beq L2 ; Jump if zero
L1: .repeat 2 ; Unroll this a bit to make it faster...
lda (ptr1),Y ; copy a byte
sta (ptr2),Y
iny
.endrepeat
bne L1
inc ptr1+1
inc ptr2+1
dex ; Next 256 byte block
bne L1 ; Repeat if any
; the following section could be 10% faster if we were able to copy
; back to front - unfortunately we are forced to copy strict from
; low to high since this function is also used for
; memmove and blocks could be overlapping!
; {
L2: ; assert Y = 0
ldx ptr3 ; Get the low byte of n
beq done ; something to copy
L3: lda (ptr1),Y ; copy a byte
sta (ptr2),Y
iny
dex
bne L3
; }
done: jmp popax ; Pop ptr and return as result
; ----------------------------------------------------------------------
; Get the parameters from stack as follows:
;
; size --> ptr3
; src --> ptr1
; dest --> ptr2
; First argument (dest) will remain on stack and is returned in a/x!
memcpy_getparams: ; IMPORTANT! Function has to leave with Y=0!
sta ptr3
stx ptr3+1 ; save n to ptr3
jsr popax
sta ptr1
stx ptr1+1 ; save src to ptr1
; save dest to ptr2
ldy #1 ; (direct stack access is three cycles faster
; (total cycle count with return))
lda (sp),y
tax
stx ptr2+1 ; save high byte of ptr2
dey ; Y = 0
lda (sp),y ; Get ptr2 low
sta ptr2
rts

@ -0,0 +1,84 @@
;
; Ullrich von Bassewitz, 2003-08-20
; Performance increase (about 20%) by
; Christian Krueger, 2009-09-13
;
; void* __fastcall__ memmove (void* dest, const void* src, size_t size);
;
; NOTE: This function uses entry points from memcpy!
;
.export _memmove
.import memcpy_getparams, memcpy_upwards, popax
.importzp ptr1, ptr2, ptr3, ptr4, tmp1
.macpack generic
.macpack longbranch
; ----------------------------------------------------------------------
_memmove:
jsr memcpy_getparams
; Check for the copy direction. If dest < src, we must copy upwards (start at
; low addresses and increase pointers), otherwise we must copy downwards
; (start at high addresses and decrease pointers).
sec
sbc ptr1
txa
sbc ptr1+1
jcc memcpy_upwards ; Branch if dest < src (upwards copy)
; Copy downwards. Adjust the pointers to the end of the memory regions.
lda ptr1+1
add ptr3+1
sta ptr1+1
lda ptr2+1
add ptr3+1
sta ptr2+1
; handle fractions of a page size first
ldy ptr3 ; count, low byte
bne @entry ; something to copy?
beq PageSizeCopy ; here like bra...
@copyByte:
lda (ptr1),y
sta (ptr2),y
@entry:
dey
bne @copyByte
lda (ptr1),y ; copy remaining byte
sta (ptr2),y
PageSizeCopy: ; assert Y = 0
ldx ptr3+1 ; number of pages
beq done ; none? -> done
@initBase:
dec ptr1+1 ; adjust base...
dec ptr2+1
dey ; in entry case: 0 -> FF
lda (ptr1),y ; need to copy this 'intro byte'
sta (ptr2),y ; to 'land' later on Y=0! (as a result of the '.repeat'-block!)
dey ; FF ->FE
@copyBytes:
.repeat 2 ; Unroll this a bit to make it faster...
lda (ptr1),y
sta (ptr2),y
dey
.endrepeat
@copyEntry: ; in entry case: 0 -> FF
bne @copyBytes
lda (ptr1),y ; Y = 0, copy last byte
sta (ptr2),y
dex ; one page to copy less
bne @initBase ; still a page to copy?
; Done, return dest
done: jmp popax ; Pop ptr and return as result

@ -0,0 +1,95 @@
;
; void* __fastcall__ memset (void* ptr, int c, size_t n);
; void* __fastcall__ _bzero (void* ptr, size_t n);
; void __fastcall__ bzero (void* ptr, size_t n);
;
; Ullrich von Bassewitz, 29.05.1998
; Performance increase (about 20%) by
; Christian Krueger, 12.09.2009
;
; NOTE: bzero will return it's first argument as memset does. It is no problem
; to declare the return value as void, since it may be ignored. _bzero
; (note the leading underscore) is declared with the proper return type,
; because the compiler will replace memset by _bzero if the fill value
; is zero, and the optimizer looks at the return type to see if the value
; in a/x is of any use.
;
.export _memset, _bzero, __bzero
.import popax
.importzp sp, ptr1, ptr2, ptr3
_bzero:
__bzero:
sta ptr3
stx ptr3+1 ; Save n
ldx #0 ; Fill with zeros
beq common
_memset:
sta ptr3 ; Save n
stx ptr3+1
jsr popax ; Get c
tax
; Common stuff for memset and bzero from here
common: ; Fill value is in X!
ldy #1
lda (sp),y
sta ptr1+1 ; save high byte of ptr
dey ; Y = 0
lda (sp),y ; Get ptr
sta ptr1
lsr ptr3+1 ; divide number of
ror ptr3 ; bytes by two to increase
bcc evenCount ; speed (ptr3 = ptr3/2)
oddCount:
; y is still 0 here
txa ; restore fill value
sta (ptr1),y ; save value and increase
inc ptr1 ; dest. pointer
bne evenCount
inc ptr1+1
evenCount:
lda ptr1 ; build second pointer section
clc
adc ptr3 ; ptr2 = ptr1 + (length/2) <- ptr3
sta ptr2
lda ptr1+1
adc ptr3+1
sta ptr2+1
txa ; restore fill value
ldx ptr3+1 ; Get high byte of n
beq L2 ; Jump if zero
; Set 256/512 byte blocks
; y is still 0 here
L1: .repeat 2 ; Unroll this a bit to make it faster
sta (ptr1),y ; Set byte in lower section
sta (ptr2),y ; Set byte in upper section
iny
.endrepeat
bne L1
inc ptr1+1
inc ptr2+1
dex ; Next 256 byte block
bne L1 ; Repeat if any
; Set the remaining bytes if any
L2: ldy ptr3 ; Get the low byte of n
bne L3 ; something to set?
jmp popax ; no -> Pop ptr and return as result
L3a: sta (ptr1),y ; set bytes in low
sta (ptr2),y ; and high section
L3: dey
bne L3a
sta (ptr1),y ; Set remaining byte(s)
sta (ptr2),y
jmp popax ; Pop ptr and return as result

@ -0,0 +1,55 @@
;
; Ullrich von Bassewitz, 31.05.1998
;
; char* strcat (char* dest, const char* src);
;
.export _strcat
.import popax
.importzp ptr1, ptr2, tmp3
_strcat:
sta ptr1 ; Save src
stx ptr1+1
jsr popax ; Get dest
sta ptr2
stx ptr2+1
sta tmp3 ; Remember for function return
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 tmp3 ; X does still contain high byte
rts

@ -0,0 +1,48 @@
;
; 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
Loop: lda (ptr1),y ; Get next char
beq EOS ; Jump on end of string
cmp tmp1 ; Found?
beq Found ; Jump if yes
iny
bne Loop
inc ptr1+1
bne Loop ; Branch always
; End of string. Check if we're searching for the terminating zero
EOS: lda tmp1 ; Get the char we're searching for
bne NotFound ; Jump if not searching for terminator
; Found. Calculate pointer to c.
Found: ldx ptr1+1 ; Load high byte of pointer
tya ; Low byte offset
clc
adc ptr1
bcc Found1
inx
Found1: rts
; Not found, return NULL
NotFound:
lda #0
tax
rts

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

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

@ -0,0 +1,30 @@
;
; Ullrich von Bassewitz, 31.05.1998
;
; char* strcpy (char* dest, const char* src);
;
.export _strcpy
.import popax
.importzp ptr1, ptr2
_strcpy:
sta ptr1 ; Save src
stx ptr1+1
jsr popax ; Get dest
sta ptr2
stx ptr2+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 ptr2 ; X still contains high byte
rts

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

@ -0,0 +1,85 @@
;
; Ullrich von Bassewitz, 18.07.2000
;
; char* __fastcall__ strdup (const char* S);
;
; Note: The code knowns which zero page locations are used by malloc.
;
.importzp sp, tmp1, ptr4
.import pushax, decsp4, incsp4
.import _strlen, _malloc, _memcpy
.export _strdup
.macpack cpu
.macpack generic
_strdup:
; Since we need some place to store the intermediate results, allocate a
; stack frame. To make this somewhat more efficient, create the stackframe
; as needed for the final call to the memcpy function.
pha ; decsp will destroy A (but not X)
jsr decsp4 ; Target/source
; Store the pointer into the source slot
ldy #1
txa
sta (sp),y
pla
.if (.cpu .bitand CPU_ISET_65SC02)
sta (sp)
.else
dey
sta (sp),y
.endif
; Get length of S (which is still in a/x)
jsr _strlen
; Calculate strlen(S)+1 (the space needed)
add #1
bcc @L1
inx
; Save the space we're about to allocate in ptr4
@L1: sta ptr4
stx ptr4+1
; Allocate memory. _malloc will not use ptr4
jsr _malloc
; Store the result into the target stack slot
ldy #2
sta (sp),y ; Store low byte
sta tmp1
txa ; Get high byte
iny
sta (sp),y ; Store high byte
; Check for a NULL pointer
ora tmp1
beq OutOfMemory
; Copy the string. memcpy will return the target string which is exactly
; what we need here. It will also drop the allocated stack frame.
lda ptr4
ldx ptr4+1 ; Load size
jmp _memcpy ; Copy string, drop stackframe
; Out of memory, return NULL (A = 0)
OutOfMemory:
tax
jmp incsp4 ; Drop stack frame

@ -0,0 +1,35 @@
;
; 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
; The given error code is invalid
@L1: lda #<EINVAL
sta __errno
lda #>EINVAL ; = 0
sta __errno+1
; lda #$00 ; A contains zero: "Unknown error"
; Load the pointer to the error message and return
@L2: asl a ; * 2
tay
ldx __sys_errlist+1,y
lda __sys_errlist,y
rts

@ -0,0 +1,224 @@
/*****************************************************************************/
/* */
/* strftime.c */
/* */
/* Convert broken down time to a string in a user specified format */
/* */
/* */
/* */
/* (C) 2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
#include <stdio.h>
#include <time.h>
/* Use static local variables for speed */
#pragma staticlocals (on);
/*****************************************************************************/
/* Code */
/*****************************************************************************/
size_t __fastcall__ strftime (char* buf, size_t bufsize, const char* format,
const struct tm* tm)
{
static const char* days[7] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
static const char* months[12] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
unsigned count;
unsigned len;
char c;
char arg[40];
const char* argptr;
/* Copy until we reach the end of the format string or a format specifier */
count = 0;
while (1) {
if (count >= bufsize) {
/* Not enough buffer space available */
return 0;
}
if ((c = *format++) == '\0') {
/* End of format string reached */
*buf = '\0';
return count;
}
if (c == '%') {
/* Format specifier */
argptr = arg;
switch (*format++) {
case '%':
arg[0] = '%';
arg[1] = '\0';
break;
case 'A':
argptr = days[tm->tm_wday];
break;
case 'B':
argptr = months[tm->tm_mon];
break;
case 'D':
sprintf (arg, "%02d/%02d/%02d", tm->tm_mon + 1,
tm->tm_mday, tm->tm_year % 100);
break;
case 'F':
/* C99 */
sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900,
tm->tm_mon + 1, tm->tm_mday);
break;
case 'H':
sprintf (arg, "%02d", tm->tm_hour);
break;
case 'I':
sprintf (arg, "%02d", tm->tm_hour % 12);
break;
case 'M':
sprintf (arg, "%02d", tm->tm_min);
break;
case 'P':
/* GNU extension */
argptr = (tm->tm_hour >= 12)? "pm" : "am";
break;
case 'S':
sprintf (arg, "%02d", tm->tm_sec);
break;
case 'U':
sprintf (arg, "%02d", (tm->tm_yday + 7 - tm->tm_wday) / 7);
break;
case 'W':
sprintf (arg, "%02d",
(tm->tm_yday + 7 - (tm->tm_wday? tm->tm_wday - 1 : 6)) / 7);
break;
case 'X':
sprintf (arg, "%02d:%02d:%02d", tm->tm_hour,
tm->tm_min, tm->tm_sec);
break;
case 'Y':
sprintf (arg, "%4d", tm->tm_year + 1900);
break;
case 'Z':
argptr = tm->tm_isdst? _tz.dstname : _tz.tzname;
break;
case 'a':
sprintf (arg, "%.3s", days[tm->tm_wday]);
break;
case 'b':
sprintf (arg, "%.3s", months[tm->tm_mon]);
break;
case 'c':
sprintf (arg, "%.3s %.3s%3d %02d:%02d:%02d %d",
days[tm->tm_wday], months[tm->tm_mon],
tm->tm_mday, tm->tm_hour, tm->tm_min,
tm->tm_sec, tm->tm_year + 1900);
break;
case 'd':
sprintf (arg, "%02d", tm->tm_mday);
break;
case 'j':
sprintf (arg, "%03d", tm->tm_yday + 1);
break;
case 'm':
sprintf (arg, "%02d", tm->tm_mon + 1);
break;
case 'p':
argptr = (tm->tm_hour >= 12)? "PM" : "AM";
break;
case 'w':
sprintf (arg, "%d", tm->tm_wday);
break;
case 'x':
sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900,
tm->tm_mon + 1, tm->tm_mday);
break;
case 'y':
sprintf (arg, "%02d", tm->tm_year % 100);
break;
default:
/* Unknown format specifier, convert to empty string */
arg[0] = '\0';
break;
}
/* Check if we have enough space to copy the argument string */
len = strlen (argptr);
count += len;
if (count < bufsize) {
memcpy (buf, argptr, len);
buf += len;
}
} else {
/* No format character, just copy */
*buf++ = c;
++count;
}
}
}

@ -0,0 +1,60 @@
;
; 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
.importzp ptr1, ptr2, tmp1
.include "ctype.inc"
_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 #CT_LOWER ; lower case char?
beq L1 ; jump if no
txa ; get character back
clc
adc #<('A'-'a') ; 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 #CT_LOWER ; lower case char?
beq L2 ; jump if no
txa ; get character back
clc
adc #<('A'-'a') ; 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

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

@ -0,0 +1,47 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; char* strlower (char* s);
; char* strlwr (char* s);
;
; Non-ANSI
;
.export _strlower, _strlwr
.import popax
.import __ctype
.importzp ptr1, ptr2
.include "ctype.inc"
_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 #CT_UPPER ; upper case char?
beq L1 ; jump if no
txa ; get character back into accu
sec
sbc #<('A'-'a') ; 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

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

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

@ -0,0 +1,69 @@
;
; Ullrich von Bassewitz, 2003-05-04
;
; char* __fastcall__ strncpy (char* dest, const char* src, unsigned size);
;
.export _strncpy
.import popax
.importzp ptr1, ptr2, tmp1, tmp2, tmp3
.proc _strncpy
eor #$FF
sta tmp1
txa
eor #$FF
sta tmp2 ; Store -size - 1
jsr popax ; get src
sta ptr1
stx ptr1+1
jsr popax ; get dest
sta ptr2
stx ptr2+1
stx tmp3 ; remember for function return
; Copy src -> dest up to size bytes
ldx tmp1 ; Load low byte of ones complement of size
ldy #$00
L1: inx
bne L2
inc tmp2
beq L9
L2: lda (ptr1),y ; Copy one character
sta (ptr2),y
beq L5 ; Bail out if terminator reached (A = 0)
iny
bne L1
inc ptr1+1
inc ptr2+1 ; Bump high bytes
bne L1 ; Branch always
; Fill the remaining bytes.
L3: inx ; Counter low byte
beq L6 ; Branch on overflow
L4: sta (ptr2),y ; Clear one byte
L5: iny ; Bump pointer
bne L3
inc ptr2+1 ; Bump high byte
bne L3 ; Branch always
; Bump the counter high byte
L6: inc tmp2
bne L4
; Done, return dest
L9: lda ptr2 ; Get low byte
ldx tmp3 ; Get unchanged high byte
rts
.endproc

@ -0,0 +1,103 @@
;
; Christian Groessler, 10.02.2009
; derived from strncmp.s and stricmp.s
;
; int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count);
; int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count);
;
.export _strnicmp, _strncasecmp
.import popax, __ctype
.importzp ptr1, ptr2, ptr3, tmp1
.include "ctype.inc"
_strnicmp:
_strncasecmp:
; 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 (ptr2),y
tax
lda __ctype,x ; get character classification
and #CT_LOWER ; lower case char?
beq L1 ; jump if no
txa ; get character back
sec
sbc #<('a'-'A') ; 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 #CT_LOWER ; lower case char?
beq L2 ; jump if no
txa ; get character back
sec
sbc #<('a'-'A') ; make upper case char
tax
L2: cpx tmp1 ; compare characters
bne NotEqual ; Jump if strings different
txa ; 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 L3
ldx #$FF ; Make result negative
rts
L3: ldx #$01 ; Make result positive
rts

@ -0,0 +1,61 @@
;
; Ullrich von Bassewitz, 17.07.2002
;
; const char* __fastcall__ _stroserror (unsigned char errcode);
; /* Map an operating system error number to an error message. */
;
.export __stroserror
.import __sys_oserrlist
.importzp ptr1, tmp1
.macpack generic
; The table is built as a list of entries
;
; .byte entrylen
; .byte errorcode
; .asciiz errormsg
;
; and terminated by an entry with length zero that is returned if the
; error code could not be found.
__stroserror:
sta tmp1 ; Save the error code
ldy #<__sys_oserrlist
sty ptr1
ldy #>__sys_oserrlist
sty ptr1+1 ; Setup pointer to message table
@L1: ldy #0
lda (ptr1),y ; Get the length
beq Done ; Bail out if end of list reached
iny
lda (ptr1),y ; Compare the error code
cmp tmp1
beq Done ; Jump if found
; Not found, move pointer to next entry
dey
clc
lda ptr1
adc (ptr1),y
sta ptr1
bcc @L1
inc ptr1+1
bcs @L1 ; Branch always
; We've found the code or reached the end of the list
Done: ldx ptr1+1
lda ptr1
add #2 ; Add a total of #2
bcc @L1
inx ; Bump high byte
@L1: rts

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

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

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

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

@ -0,0 +1,9 @@
;
; Ullrich von Bassewitz, 2009-09-17
;
; intmax_t __fastcall__ strtoimax (const char* nptr, char** endptr, int base);
;
.import _strtol
.export _strtoimax = _strtol

@ -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* __fastcall__ strtok (register 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;
}

@ -0,0 +1,228 @@
;
; File generated by cc65 v 2.13.3
;
.fopt compiler,"cc65 v 2.13.3"
.setcpu "65C02"
.smart on
.autoimport on
.case on
.debuginfo on
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch
.dbg file, "strtok.c", 1493, 1356265749
.dbg file, "../../include/string.h", 4883, 1234293382
.dbg file, "../../include/stddef.h", 2972, 1253259480
.import _strchr
.export _strtok
.segment "DATA"
_Last:
.word $0000
; ---------------------------------------------------------------
; __near__ unsigned char* __near__ __fastcall__ strtok (register __near__ unsigned char*, __near__ const unsigned char*)
; ---------------------------------------------------------------
.segment "CODE"
.proc _strtok: near
.segment "CODE"
;
; {
;
.dbg line, "strtok.c", 31
jsr pushax
ldy #$02
ldx #$04
jsr regswap2
;
; if (s1 == 0) {
;
.dbg line, "strtok.c", 36
jsr decsp3
lda regbank+4
ora regbank+4+1
bne L0004
;
; s1 = Last;
;
.dbg line, "strtok.c", 37
lda _Last
sta regbank+4
lda _Last+1
sta regbank+4+1
;
; if (*s1 == '\0') {
;
.dbg line, "strtok.c", 41
L0004: lda (regbank+4)
bne L0009
;
; return 0;
;
.dbg line, "strtok.c", 42
tax
jmp L0003
;
; while ((c = *s1) && strchr (s2, c) != 0) {
;
.dbg line, "strtok.c", 48
L0009: lda (regbank+4)
ldy #$02
sta (sp),y
tax
beq L000D
ldy #$04
lda (sp),y
tax
dey
lda (sp),y
jsr pushax
ldy #$04
lda (sp),y
ldx #$00
jsr _strchr
cpx #$00
bne L000E
cmp #$00
beq L000D
;
; ++s1;
;
.dbg line, "strtok.c", 49
L000E: inc regbank+4
bne L0009
inc regbank+4+1
;
; }
;
.dbg line, "strtok.c", 50
bra L0009
;
; if (c == '\0') {
;
.dbg line, "strtok.c", 51
L000D: ldy #$02
lda (sp),y
bne L0018
;
; Last = s1;
;
.dbg line, "strtok.c", 53
lda regbank+4
sta _Last
lda regbank+4+1
sta _Last+1
;
; return 0;
;
.dbg line, "strtok.c", 54
txa
bra L0003
;
; start = s1;
;
.dbg line, "strtok.c", 58
L0018: lda regbank+4
ldx regbank+4+1
jsr stax0sp
;
; while ((c = *s1) && strchr (s2, c) == 0) {
;
.dbg line, "strtok.c", 61
L001F: lda (regbank+4)
ldy #$02
sta (sp),y
tax
beq L0020
ldy #$04
lda (sp),y
tax
dey
lda (sp),y
jsr pushax
ldy #$04
lda (sp),y
ldx #$00
jsr _strchr
cpx #$00
bne L0020
cmp #$00
bne L0020
;
; ++s1;
;
.dbg line, "strtok.c", 62
inc regbank+4
bne L001F
inc regbank+4+1
;
; }
;
.dbg line, "strtok.c", 63
bra L001F
;
; if (c == '\0') {
;
.dbg line, "strtok.c", 64
L0020: ldy #$02
lda (sp),y
bne L002B
;
; Last = s1;
;
.dbg line, "strtok.c", 66
lda regbank+4
sta _Last
lda regbank+4+1
sta _Last+1
;
; } else {
;
.dbg line, "strtok.c", 67
bra L002F
;
; *s1 = '\0';
;
.dbg line, "strtok.c", 68
L002B: lda #$00
sta (regbank+4)
;
; Last = s1 + 1;
;
.dbg line, "strtok.c", 69
lda regbank+4
ldx regbank+4+1
ina
bne L0034
inx
L0034: sta _Last
stx _Last+1
;
; return start;
;
.dbg line, "strtok.c", 73
L002F: dey
lda (sp),y
tax
lda (sp)
;
; }
;
.dbg line, "strtok.c", 74
L0003: pha
ldy #$05
lda (sp),y
sta regbank+4
iny
lda (sp),y
sta regbank+5
pla
jmp incsp7
.dbg line
.endproc

@ -0,0 +1,128 @@
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
long __fastcall__ strtol (const char* nptr, char** endptr, int base)
/* Convert a string to a long int */
{
register const char* S = nptr;
unsigned long Val = 0;
unsigned char Minus = 0;
unsigned char Ovf = 0;
unsigned CvtCount = 0;
unsigned char DigitVal;
unsigned long MaxVal;
unsigned char MaxDigit;
/* Skip white space */
while (isspace (*S)) {
++S;
}
/* Check for leading + or - sign */
switch (*S) {
case '-':
Minus = 1;
/* FALLTHROUGH */
case '+':
++S;
}
/* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may
* have a 0x prefix.
*/
if (base == 0) {
if (*S == '0') {
++S;
if (*S == 'x' || *S == 'X') {
++S;
base = 16;
} else {
base = 8;
}
} else {
base = 10;
}
} else if (base == 16 && *S == '0' && (S[1] == 'x' || S[1] == 'X')) {
S += 2;
}
/* Determine the maximum valid number and (if the number is equal to this
* value) the maximum valid digit.
*/
if (Minus) {
MaxVal = LONG_MIN;
} else {
MaxVal = LONG_MAX;
}
MaxDigit = MaxVal % base;
MaxVal /= base;
/* Convert the number */
while (1) {
/* Convert the digit into a numeric value */
if (isdigit (*S)) {
DigitVal = *S - '0';
} else if (isupper (*S)) {
DigitVal = *S - ('A' - 10);
} else if (islower (*S)) {
DigitVal = *S - ('a' - 10);
} else {
/* Unknown character */
break;
}
/* Don't accept a character that doesn't match base */
if (DigitVal >= base) {
break;
}
/* Don't accept anything that makes the final value invalid */
if (Val > MaxVal || (Val == MaxVal && DigitVal > MaxDigit)) {
Ovf = 1;
}
/* Calculate the next value if digit is not invalid */
if (Ovf == 0) {
Val = (Val * base) + DigitVal;
++CvtCount;
}
/* Next character from input */
++S;
}
/* Store the end pointer. If no conversion was performed, the value of
* nptr is returned in endptr.
*/
if (endptr) {
if (CvtCount > 0) {
*endptr = (char*) S - 1;
} else {
*endptr = (char*) nptr;
}
}
/* Handle overflow */
if (Ovf) {
errno = ERANGE;
if (Minus) {
return LONG_MIN;
} else {
return LONG_MAX;
}
}
/* Return the result */
if (Minus) {
return -(long)Val;
} else {
return Val;
}
}

@ -0,0 +1,592 @@
;
; File generated by cc65 v 2.13.3
;
.fopt compiler,"cc65 v 2.13.3"
.setcpu "65C02"
.smart on
.autoimport on
.case on
.debuginfo on
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch
.dbg file, "strtol.c", 2969, 1356265749
.dbg file, "../../include/limits.h", 2978, 1039954353
.dbg file, "../../include/ctype.h", 7770, 1087856531
.dbg file, "../../include/errno.h", 3647, 1060696125
.dbg file, "../../include/stdlib.h", 5578, 1253048480
.import __ctype
.import __maperrno
.import __errno
.export _strtol
; ---------------------------------------------------------------
; long __near__ __fastcall__ strtol (__near__ const unsigned char*, __near__ __near__ unsigned char**, int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _strtol: near
.segment "CODE"
;
; {
;
.dbg line, "strtol.c", 10
jsr pushax
;
; register const char* S = nptr;
;
.dbg line, "strtol.c", 11
lda regbank+4
ldx regbank+5
jsr pushax
ldy #$07
lda (sp),y
tax
dey
lda (sp),y
sta regbank+4
stx regbank+4+1
;
; unsigned long Val = 0;
;
.dbg line, "strtol.c", 12
ldx #$00
txa
jsr push0ax
;
; unsigned char Minus = 0;
;
.dbg line, "strtol.c", 13
jsr pusha
;
; unsigned char Ovf = 0;
;
.dbg line, "strtol.c", 14
jsr pusha
;
; unsigned CvtCount = 0;
;
.dbg line, "strtol.c", 15
jsr push0
;
; while (isspace (*S)) {
;
.dbg line, "strtol.c", 22
jsr decsp6
L0009: lda (regbank+4)
tay
lda __ctype,y
and #$60
beq L000A
;
; ++S;
;
.dbg line, "strtol.c", 23
inc regbank+4
bne L0009
inc regbank+4+1
;
; }
;
.dbg line, "strtol.c", 24
bra L0009
;
; switch (*S) {
;
.dbg line, "strtol.c", 27
L000A: lda (regbank+4)
;
; }
;
.dbg line, "strtol.c", 33
cmp #$2B
beq L001F
cmp #$2D
bne L0019
;
; Minus = 1;
;
.dbg line, "strtol.c", 29
lda #$01
ldy #$09
sta (sp),y
;
; ++S;
;
.dbg line, "strtol.c", 32
L001F: inc regbank+4
bne L0019
inc regbank+4+1
;
; if (base == 0) {
;
.dbg line, "strtol.c", 38
L0019: ldy #$11
lda (sp),y
tax
dey
lda (sp),y
cpx #$00
bne L0022
cmp #$00
bne L0022
;
; if (*S == '0') {
;
.dbg line, "strtol.c", 39
lda (regbank+4)
cmp #$30
bne L0025
;
; ++S;
;
.dbg line, "strtol.c", 40
inc regbank+4
bne L0028
inc regbank+4+1
;
; if (*S == 'x' || *S == 'X') {
;
.dbg line, "strtol.c", 41
L0028: lda (regbank+4)
cmp #$78
beq L002A
lda (regbank+4)
cmp #$58
bne L0029
;
; ++S;
;
.dbg line, "strtol.c", 42
L002A: inc regbank+4
bne L002D
inc regbank+4+1
;
; base = 16;
;
.dbg line, "strtol.c", 43
L002D: tya
;
; } else {
;
.dbg line, "strtol.c", 44
bra L00B0
;
; base = 8;
;
.dbg line, "strtol.c", 45
L0029: lda #$08
ldy #$10
jsr staxysp
;
; } else {
;
.dbg line, "strtol.c", 47
bra L0037
;
; base = 10;
;
.dbg line, "strtol.c", 48
L0025: lda #$0A
L00B0: ldy #$10
jsr staxysp
;
; } else if (base == 16 && *S == '0' && (S[1] == 'x' || S[1] == 'X')) {
;
.dbg line, "strtol.c", 50
bra L0037
L0022: iny
lda (sp),y
tax
dey
lda (sp),y
cpx #$00
bne L0037
cmp #$10
bne L0037
lda (regbank+4)
cmp #$30
bne L0037
ldy #$01
lda (regbank+4),y
cmp #$78
beq L0038
lda (regbank+4),y
cmp #$58
bne L0037
;
; S += 2;
;
.dbg line, "strtol.c", 51
L0038: lda #$02
clc
adc regbank+4
sta regbank+4
bcc L0037
inc regbank+4+1
;
; if (Minus) {
;
.dbg line, "strtol.c", 57
L0037: ldy #$09
lda (sp),y
beq L0043
;
; MaxVal = LONG_MIN;
;
.dbg line, "strtol.c", 58
ldy #$01
lda #$00
sta (sp),y
iny
sta (sp),y
iny
sta (sp),y
lda #$80
;
; } else {
;
.dbg line, "strtol.c", 59
bra L00B1
;
; MaxVal = LONG_MAX;
;
.dbg line, "strtol.c", 60
L0043: ldy #$01
dea
sta (sp),y
iny
sta (sp),y
iny
sta (sp),y
lda #$7F
L00B1: iny
sta (sp),y
;
; MaxDigit = MaxVal % base;
;
.dbg line, "strtol.c", 62
jsr ldeaxysp
jsr pusheax
ldy #$15
lda (sp),y
tax
dey
lda (sp),y
jsr axlong
jsr tosumodeax
sta (sp)
;
; MaxVal /= base;
;
.dbg line, "strtol.c", 63
ldy #$04
jsr ldeaxysp
jsr pusheax
ldy #$15
lda (sp),y
tax
dey
lda (sp),y
jsr axlong
jsr tosudiveax
ldy #$01
jsr steaxysp
;
; if (isdigit (*S)) {
;
.dbg line, "strtol.c", 69
L004F: lda (regbank+4)
tay
lda __ctype,y
and #$04
beq L0052
;
; DigitVal = *S - '0';
;
.dbg line, "strtol.c", 70
lda (regbank+4)
sec
sbc #$30
;
; } else if (isupper (*S)) {
;
.dbg line, "strtol.c", 71
bra L00B3
L0052: lda (regbank+4)
tay
lda __ctype,y
and #$02
beq L0060
;
; DigitVal = *S - ('A' - 10);
;
.dbg line, "strtol.c", 72
lda (regbank+4)
sec
sbc #$37
;
; } else if (islower (*S)) {
;
.dbg line, "strtol.c", 73
bra L00B3
L0060: lda (regbank+4)
tay
lda __ctype,y
and #$01
jeq L0050
;
; DigitVal = *S - ('a' - 10);
;
.dbg line, "strtol.c", 74
lda (regbank+4)
sec
sbc #$57
L00B3: ldy #$05
sta (sp),y
;
; if (DigitVal >= base) {
;
.dbg line, "strtol.c", 81
lda (sp),y
jsr pusha0
ldy #$13
lda (sp),y
tax
dey
lda (sp),y
jsr tosicmp
;
; break;
;
.dbg line, "strtol.c", 82
bcs L0050
;
; if (Val > MaxVal || (Val == MaxVal && DigitVal > MaxDigit)) {
;
.dbg line, "strtol.c", 86
ldy #$0D
jsr ldeaxysp
jsr pusheax
ldy #$08
jsr ldeaxysp
jsr tosugteax
bne L0081
ldy #$0D
jsr ldeaxysp
jsr pusheax
ldy #$08
jsr ldeaxysp
jsr toseqeax
beq L0080
ldy #$05
lda (sp),y
sec
sbc (sp)
sta tmp1
lda tmp1
beq L0080
bcc L0080
;
; Ovf = 1;
;
.dbg line, "strtol.c", 87
L0081: lda #$01
ldy #$08
sta (sp),y
;
; if (Ovf == 0) {
;
.dbg line, "strtol.c", 91
L0080: ldy #$08
lda (sp),y
bne L0088
;
; Val = (Val * base) + DigitVal;
;
.dbg line, "strtol.c", 92
ldy #$0D
jsr ldeaxysp
jsr pusheax
ldy #$15
lda (sp),y
tax
dey
lda (sp),y
jsr axlong
jsr tosumuleax
jsr pusheax
ldy #$09
ldx #$00
lda (sp),y
jsr tosadd0ax
ldy #$0A
jsr steaxysp
;
; ++CvtCount;
;
.dbg line, "strtol.c", 93
ldy #$06
ldx #$00
lda #$01
jsr addeqysp
;
; ++S;
;
.dbg line, "strtol.c", 97
L0088: inc regbank+4
jne L004F
inc regbank+4+1
;
; }
;
.dbg line, "strtol.c", 98
jmp L004F
;
; if (endptr) {
;
.dbg line, "strtol.c", 103
L0050: ldy #$13
lda (sp),y
dey
ora (sp),y
beq L0098
;
; if (CvtCount > 0) {
;
.dbg line, "strtol.c", 104
ldy #$07
lda (sp),y
tax
dey
lda (sp),y
cpx #$00
bne L00AF
cmp #$00
beq L0092
;
; *endptr = (char*) S - 1;
;
.dbg line, "strtol.c", 105
L00AF: ldy #$13
lda (sp),y
tax
dey
lda (sp),y
sta sreg
stx sreg+1
lda regbank+4
ldx regbank+4+1
sec
sbc #$01
bcs L0097
dex
L0097: sta (sreg)
ldy #$01
txa
sta (sreg),y
;
; } else {
;
.dbg line, "strtol.c", 106
bra L0098
;
; *endptr = (char*) nptr;
;
.dbg line, "strtol.c", 107
L0092: ldy #$13
lda (sp),y
tax
dey
lda (sp),y
jsr pushax
ldy #$17
lda (sp),y
tax
dey
lda (sp),y
ldy #$00
jsr staxspidx
;
; if (Ovf) {
;
.dbg line, "strtol.c", 112
L0098: ldy #$08
lda (sp),y
beq L00A5
;
; errno = ERANGE;
;
.dbg line, "strtol.c", 113
jsr __maperrno
ldx #$00
lda #$0F
sta __errno
stz __errno+1
;
; if (Minus) {
;
.dbg line, "strtol.c", 114
ldy #$09
lda (sp),y
beq L00A1
;
; return LONG_MIN;
;
.dbg line, "strtol.c", 115
stz sreg
lda #$80
sta sreg+1
txa
bra L00AA
;
; return LONG_MAX;
;
.dbg line, "strtol.c", 117
L00A1: dex
stx sreg
lda #$7F
sta sreg+1
txa
bra L00AA
;
; if (Minus) {
;
.dbg line, "strtol.c", 122
L00A5: iny
lda (sp),y
beq L00A7
;
; return -(long)Val;
;
.dbg line, "strtol.c", 123
ldy #$0D
jsr ldeaxysp
jsr negeax
bra L00AA
;
; return Val;
;
.dbg line, "strtol.c", 125
L00A7: ldy #$0D
jsr ldeaxysp
;
; }
;
.dbg line, "strtol.c", 127
L00AA: pha
ldy #$0E
lda (sp),y
sta regbank+4
iny
lda (sp),y
sta regbank+5
pla
ldy #$16
jmp addysp
.dbg line
.endproc

@ -0,0 +1,119 @@
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base)
/* Convert a string to a long unsigned int */
{
register const char* S = nptr;
unsigned long Val = 0;
unsigned char Minus = 0;
unsigned char Ovf = 0;
unsigned CvtCount = 0;
unsigned char DigitVal;
unsigned long MaxVal;
unsigned char MaxDigit;
/* Skip white space */
while (isspace (*S)) {
++S;
}
/* Check for leading + or - sign */
switch (*S) {
case '-':
Minus = 1;
/* FALLTHROUGH */
case '+':
++S;
}
/* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may
* have a 0x prefix.
*/
if (base == 0) {
if (*S == '0') {
++S;
if (*S == 'x' || *S == 'X') {
++S;
base = 16;
} else {
base = 8;
}
} else {
base = 10;
}
} else if (base == 16 && *S == '0' && (S[1] == 'x' || S[1] == 'X')) {
S += 2;
}
/* Determine the maximum valid number and (if the number is equal to this
* value) the maximum valid digit.
*/
MaxDigit = ULONG_MAX % base;
MaxVal = ULONG_MAX / base;
/* Convert the number */
while (1) {
/* Convert the digit into a numeric value */
if (isdigit (*S)) {
DigitVal = *S - '0';
} else if (isupper (*S)) {
DigitVal = *S - ('A' - 10);
} else if (islower (*S)) {
DigitVal = *S - ('a' - 10);
} else {
/* Unknown character */
break;
}
/* Don't accept a character that doesn't match base */
if (DigitVal >= base) {
break;
}
/* Don't accept anything that makes the final value invalid */
if (Val > MaxVal || (Val == MaxVal && DigitVal > MaxDigit)) {
Ovf = 1;
}
/* Calculate the next value if digit is not invalid */
if (Ovf == 0) {
Val = (Val * base) + DigitVal;
++CvtCount;
}
/* Next character from input */
++S;
}
/* Store the end pointer. If no conversion was performed, the value of
* nptr is returned in endptr.
*/
if (endptr) {
if (CvtCount > 0) {
*endptr = (char*) S - 1;
} else {
*endptr = (char*) nptr;
}
}
/* Handle overflow */
if (Ovf) {
errno = ERANGE;
return ULONG_MAX;
}
/* Return the result */
if (Minus) {
return (unsigned long) -(long)Val;
} else {
return Val;
}
}

@ -0,0 +1,541 @@
;
; File generated by cc65 v 2.13.3
;
.fopt compiler,"cc65 v 2.13.3"
.setcpu "65C02"
.smart on
.autoimport on
.case on
.debuginfo on
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch
.dbg file, "strtoul.c", 2843, 1356265749
.dbg file, "../../include/limits.h", 2978, 1039954353
.dbg file, "../../include/ctype.h", 7770, 1087856531
.dbg file, "../../include/errno.h", 3647, 1060696125
.dbg file, "../../include/stdlib.h", 5578, 1253048480
.import __ctype
.import __maperrno
.import __errno
.export _strtoul
; ---------------------------------------------------------------
; unsigned long __near__ __fastcall__ strtoul (__near__ const unsigned char*, __near__ __near__ unsigned char**, int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _strtoul: near
.segment "CODE"
;
; {
;
.dbg line, "strtoul.c", 10
jsr pushax
;
; register const char* S = nptr;
;
.dbg line, "strtoul.c", 11
lda regbank+4
ldx regbank+5
jsr pushax
ldy #$07
lda (sp),y
tax
dey
lda (sp),y
sta regbank+4
stx regbank+4+1
;
; unsigned long Val = 0;
;
.dbg line, "strtoul.c", 12
ldx #$00
txa
jsr push0ax
;
; unsigned char Minus = 0;
;
.dbg line, "strtoul.c", 13
jsr pusha
;
; unsigned char Ovf = 0;
;
.dbg line, "strtoul.c", 14
jsr pusha
;
; unsigned CvtCount = 0;
;
.dbg line, "strtoul.c", 15
jsr push0
;
; while (isspace (*S)) {
;
.dbg line, "strtoul.c", 22
jsr decsp6
L0009: lda (regbank+4)
tay
lda __ctype,y
and #$60
beq L000A
;
; ++S;
;
.dbg line, "strtoul.c", 23
inc regbank+4
bne L0009
inc regbank+4+1
;
; }
;
.dbg line, "strtoul.c", 24
bra L0009
;
; switch (*S) {
;
.dbg line, "strtoul.c", 27
L000A: lda (regbank+4)
;
; }
;
.dbg line, "strtoul.c", 33
cmp #$2B
beq L001F
cmp #$2D
bne L0019
;
; Minus = 1;
;
.dbg line, "strtoul.c", 29
lda #$01
ldy #$09
sta (sp),y
;
; ++S;
;
.dbg line, "strtoul.c", 32
L001F: inc regbank+4
bne L0019
inc regbank+4+1
;
; if (base == 0) {
;
.dbg line, "strtoul.c", 38
L0019: ldy #$11
lda (sp),y
tax
dey
lda (sp),y
cpx #$00
bne L0022
cmp #$00
bne L0022
;
; if (*S == '0') {
;
.dbg line, "strtoul.c", 39
lda (regbank+4)
cmp #$30
bne L0025
;
; ++S;
;
.dbg line, "strtoul.c", 40
inc regbank+4
bne L0028
inc regbank+4+1
;
; if (*S == 'x' || *S == 'X') {
;
.dbg line, "strtoul.c", 41
L0028: lda (regbank+4)
cmp #$78
beq L002A
lda (regbank+4)
cmp #$58
bne L0029
;
; ++S;
;
.dbg line, "strtoul.c", 42
L002A: inc regbank+4
bne L002D
inc regbank+4+1
;
; base = 16;
;
.dbg line, "strtoul.c", 43
L002D: tya
;
; } else {
;
.dbg line, "strtoul.c", 44
bra L00A2
;
; base = 8;
;
.dbg line, "strtoul.c", 45
L0029: lda #$08
ldy #$10
jsr staxysp
;
; } else {
;
.dbg line, "strtoul.c", 47
bra L0037
;
; base = 10;
;
.dbg line, "strtoul.c", 48
L0025: lda #$0A
L00A2: ldy #$10
jsr staxysp
;
; } else if (base == 16 && *S == '0' && (S[1] == 'x' || S[1] == 'X')) {
;
.dbg line, "strtoul.c", 50
bra L0037
L0022: iny
lda (sp),y
tax
dey
lda (sp),y
cpx #$00
bne L0037
cmp #$10
bne L0037
lda (regbank+4)
cmp #$30
bne L0037
ldy #$01
lda (regbank+4),y
cmp #$78
beq L0038
lda (regbank+4),y
cmp #$58
bne L0037
;
; S += 2;
;
.dbg line, "strtoul.c", 51
L0038: lda #$02
clc
adc regbank+4
sta regbank+4
bcc L0037
inc regbank+4+1
;
; MaxDigit = ULONG_MAX % base;
;
.dbg line, "strtoul.c", 57
L0037: ldx #$FF
stx sreg
stx sreg+1
txa
jsr pusheax
ldy #$15
lda (sp),y
tax
dey
lda (sp),y
jsr axlong
jsr tosumodeax
sta (sp)
;
; MaxVal = ULONG_MAX / base;
;
.dbg line, "strtoul.c", 58
ldx #$FF
stx sreg
stx sreg+1
txa
jsr pusheax
ldy #$15
lda (sp),y
tax
dey
lda (sp),y
jsr axlong
jsr tosudiveax
ldy #$01
jsr steaxysp
;
; if (isdigit (*S)) {
;
.dbg line, "strtoul.c", 64
L0047: lda (regbank+4)
tay
lda __ctype,y
and #$04
beq L004A
;
; DigitVal = *S - '0';
;
.dbg line, "strtoul.c", 65
lda (regbank+4)
sec
sbc #$30
;
; } else if (isupper (*S)) {
;
.dbg line, "strtoul.c", 66
bra L00A4
L004A: lda (regbank+4)
tay
lda __ctype,y
and #$02
beq L0058
;
; DigitVal = *S - ('A' - 10);
;
.dbg line, "strtoul.c", 67
lda (regbank+4)
sec
sbc #$37
;
; } else if (islower (*S)) {
;
.dbg line, "strtoul.c", 68
bra L00A4
L0058: lda (regbank+4)
tay
lda __ctype,y
and #$01
jeq L0048
;
; DigitVal = *S - ('a' - 10);
;
.dbg line, "strtoul.c", 69
lda (regbank+4)
sec
sbc #$57
L00A4: ldy #$05
sta (sp),y
;
; if (DigitVal >= base) {
;
.dbg line, "strtoul.c", 76
lda (sp),y
jsr pusha0
ldy #$13
lda (sp),y
tax
dey
lda (sp),y
jsr tosicmp
;
; break;
;
.dbg line, "strtoul.c", 77
bcs L0048
;
; if (Val > MaxVal || (Val == MaxVal && DigitVal > MaxDigit)) {
;
.dbg line, "strtoul.c", 81
ldy #$0D
jsr ldeaxysp
jsr pusheax
ldy #$08
jsr ldeaxysp
jsr tosugteax
bne L0079
ldy #$0D
jsr ldeaxysp
jsr pusheax
ldy #$08
jsr ldeaxysp
jsr toseqeax
beq L0078
ldy #$05
lda (sp),y
sec
sbc (sp)
sta tmp1
lda tmp1
beq L0078
bcc L0078
;
; Ovf = 1;
;
.dbg line, "strtoul.c", 82
L0079: lda #$01
ldy #$08
sta (sp),y
;
; if (Ovf == 0) {
;
.dbg line, "strtoul.c", 86
L0078: ldy #$08
lda (sp),y
bne L0080
;
; Val = (Val * base) + DigitVal;
;
.dbg line, "strtoul.c", 87
ldy #$0D
jsr ldeaxysp
jsr pusheax
ldy #$15
lda (sp),y
tax
dey
lda (sp),y
jsr axlong
jsr tosumuleax
jsr pusheax
ldy #$09
ldx #$00
lda (sp),y
jsr tosadd0ax
ldy #$0A
jsr steaxysp
;
; ++CvtCount;
;
.dbg line, "strtoul.c", 88
ldy #$06
ldx #$00
lda #$01
jsr addeqysp
;
; ++S;
;
.dbg line, "strtoul.c", 92
L0080: inc regbank+4
jne L0047
inc regbank+4+1
;
; }
;
.dbg line, "strtoul.c", 93
jmp L0047
;
; if (endptr) {
;
.dbg line, "strtoul.c", 98
L0048: ldy #$13
lda (sp),y
dey
ora (sp),y
beq L0090
;
; if (CvtCount > 0) {
;
.dbg line, "strtoul.c", 99
ldy #$07
lda (sp),y
tax
dey
lda (sp),y
cpx #$00
bne L00A1
cmp #$00
beq L008A
;
; *endptr = (char*) S - 1;
;
.dbg line, "strtoul.c", 100
L00A1: ldy #$13
lda (sp),y
tax
dey
lda (sp),y
sta sreg
stx sreg+1
lda regbank+4
ldx regbank+4+1
sec
sbc #$01
bcs L008F
dex
L008F: sta (sreg)
ldy #$01
txa
sta (sreg),y
;
; } else {
;
.dbg line, "strtoul.c", 101
bra L0090
;
; *endptr = (char*) nptr;
;
.dbg line, "strtoul.c", 102
L008A: ldy #$13
lda (sp),y
tax
dey
lda (sp),y
jsr pushax
ldy #$17
lda (sp),y
tax
dey
lda (sp),y
ldy #$00
jsr staxspidx
;
; if (Ovf) {
;
.dbg line, "strtoul.c", 107
L0090: ldy #$08
lda (sp),y
beq L0093
;
; errno = ERANGE;
;
.dbg line, "strtoul.c", 108
jsr __maperrno
lda #$0F
sta __errno
stz __errno+1
;
; return ULONG_MAX;
;
.dbg line, "strtoul.c", 109
ldx #$FF
stx sreg
stx sreg+1
txa
bra L009D
;
; if (Minus) {
;
.dbg line, "strtoul.c", 113
L0093: iny
lda (sp),y
beq L009A
;
; return (unsigned long) -(long)Val;
;
.dbg line, "strtoul.c", 114
ldy #$0D
jsr ldeaxysp
jsr negeax
bra L009D
;
; return Val;
;
.dbg line, "strtoul.c", 116
L009A: ldy #$0D
jsr ldeaxysp
;
; }
;
.dbg line, "strtoul.c", 118
L009D: pha
ldy #$0E
lda (sp),y
sta regbank+4
iny
lda (sp),y
sta regbank+5
pla
ldy #$16
jmp addysp
.dbg line
.endproc

@ -0,0 +1,9 @@
;
; Ullrich von Bassewitz, 2009-09-17
;
; uintmax_t __fastcall__ strtoumax (const char* nptr, char** endptr, int base);
;
.import _strtoul
.export _strtoumax = _strtoul

@ -0,0 +1,47 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; char* strupper (char* s);
; char* strupr (char* s);
;
; Non-ANSI
;
.export _strupper, _strupr
.import popax
.import __ctype
.importzp ptr1, ptr2
.include "ctype.inc"
_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 #CT_LOWER ; lower case char?
beq L1 ; jump if no
txa ; get character back into accu
clc
adc #<('A'-'a') ; 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

@ -0,0 +1,20 @@
/*
* strxfrm.c
*
* Ullrich von Bassewitz, 11.12.1998
*/
#include <string.h>
size_t __fastcall__ strxfrm (char* dest, const char* src, size_t count)
{
strncpy (dest, src, count);
return strlen (src);
}

@ -0,0 +1,82 @@
;
; File generated by cc65 v 2.13.3
;
.fopt compiler,"cc65 v 2.13.3"
.setcpu "65C02"
.smart on
.autoimport on
.case on
.debuginfo on
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch
.dbg file, "strxfrm.c", 222, 1356265749
.dbg file, "../../include/string.h", 4883, 1234293382
.dbg file, "../../include/stddef.h", 2972, 1253259480
.import _strlen
.import _strncpy
.export _strxfrm
; ---------------------------------------------------------------
; unsigned int __near__ __fastcall__ strxfrm (__near__ unsigned char*, __near__ const unsigned char*, unsigned int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _strxfrm: near
.segment "CODE"
;
; {
;
.dbg line, "strxfrm.c", 14
jsr pushax
;
; strncpy (dest, src, count);
;
.dbg line, "strxfrm.c", 15
jsr decsp4
ldy #$09
lda (sp),y
tax
dey
lda (sp),y
ldy #$02
sta (sp),y
iny
txa
sta (sp),y
ldy #$07
lda (sp),y
tax
dey
lda (sp),y
sta (sp)
ldy #$01
txa
sta (sp),y
ldy #$05
lda (sp),y
tax
dey
lda (sp),y
jsr _strncpy
;
; return strlen (src);
;
.dbg line, "strxfrm.c", 16
ldy #$03
lda (sp),y
tax
dey
lda (sp),y
jsr _strlen
;
; }
;
.dbg line, "strxfrm.c", 17
jmp incsp6
.dbg line
.endproc

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int tolower (int c);
;
.export _tolower
.import __ctype
_tolower:
cpx #$00 ; Outside valid range?
bne L9 ; If so, return the argument unchanged
tay ; Get C into Y
lda __ctype,y ; Get character classification
lsr a
lsr a ; Get bit 1 (upper case char) into carry
tya ; Get char back into A
bcc L9 ; Jump if no upper case char
sbc #<('A'-'a') ; Make lower case char (carry already set)
L9: rts

@ -0,0 +1,21 @@
;
; Ullrich von Bassewitz, 02.06.1998
;
; int toupper (int c);
;
.export _toupper
.import __ctype
_toupper:
cpx #$00 ; Outside valid range?
bne L9 ; If so, return the argument unchanged
tay ; Get c into Y
lda __ctype,y ; Get character classification
lsr a ; Get bit 0 (lower char) into carry
tya ; Get C back into A
bcc L9 ; Jump if not lower char
clc
adc #<('A'-'a') ; make upper case char
L9: rts ; CC are set

Binary file not shown.

@ -29,7 +29,8 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include --cpu $(
# Object files
OBJS = crt0.o \
redbus.o
redbus.o \
ctype.o
#--------------------------------------------------------------------------
# Targets

@ -0,0 +1,161 @@
;
; Stefan Haubenthal with minor changes from Ullrich von Bassewitz, 2003-05-02
;
; Character specification table.
;
.include "ctype.inc"
; The tables are readonly, put them into the rodata segment
.rodata
; The following 256 byte wide table specifies attributes for the isxxx type
; of functions. Doing it by a table means some overhead in space, but it
; has major advantages:
;
; * It is fast. If it were'nt for the slow parameter passing of cc65, one
; could even define macros for the isxxx functions (this is usually
; done on other platforms).
;
; * It is highly portable. The only unportable part is the table itself,
; all real code goes into the common library.
;
; * We save some code in the isxxx functions.
__ctype:
.repeat 2
.byte CT_CTRL ; 0/00 ___ctrl_@___
.byte CT_CTRL ; 1/01 ___ctrl_A___
.byte CT_CTRL ; 2/02 ___ctrl_B___
.byte CT_CTRL ; 3/03 ___ctrl_C___
.byte CT_CTRL ; 4/04 ___ctrl_D___
.byte CT_CTRL ; 5/05 ___ctrl_E___
.byte CT_CTRL ; 6/06 ___ctrl_F___
.byte CT_CTRL ; 7/07 ___ctrl_G___
.byte CT_CTRL ; 8/08 ___ctrl_H___
.byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB
; 9/09 ___ctrl_I___
.byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___
.byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___
.byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___
.byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___
.byte CT_CTRL ; 14/0e ___ctrl_N___
.byte CT_CTRL ; 15/0f ___ctrl_O___
.byte CT_CTRL ; 16/10 ___ctrl_P___
.byte CT_CTRL ; 17/11 ___ctrl_Q___
.byte CT_CTRL ; 18/12 ___ctrl_R___
.byte CT_CTRL ; 19/13 ___ctrl_S___
.byte CT_CTRL ; 20/14 ___ctrl_T___
.byte CT_CTRL ; 21/15 ___ctrl_U___
.byte CT_CTRL ; 22/16 ___ctrl_V___
.byte CT_CTRL ; 23/17 ___ctrl_W___
.byte CT_CTRL ; 24/18 ___ctrl_X___
.byte CT_CTRL ; 25/19 ___ctrl_Y___
.byte CT_CTRL ; 26/1a ___ctrl_Z___
.byte CT_CTRL ; 27/1b ___ctrl_[___
.byte CT_CTRL ; 28/1c ___ctrl_\___
.byte CT_CTRL ; 29/1d ___ctrl_]___
.byte CT_CTRL ; 30/1e ___ctrl_^___
.byte CT_CTRL ; 31/1f ___ctrl_____
.byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___
.byte CT_NONE ; 33/21 _____!_____
.byte CT_NONE ; 34/22 _____"_____
.byte CT_NONE ; 35/23 _____#_____
.byte CT_NONE ; 36/24 _____$_____
.byte CT_NONE ; 37/25 _____%_____
.byte CT_NONE ; 38/26 _____&_____
.byte CT_NONE ; 39/27 _____'_____
.byte CT_NONE ; 40/28 _____(_____
.byte CT_NONE ; 41/29 _____)_____
.byte CT_NONE ; 42/2a _____*_____
.byte CT_NONE ; 43/2b _____+_____
.byte CT_NONE ; 44/2c _____,_____
.byte CT_NONE ; 45/2d _____-_____
.byte CT_NONE ; 46/2e _____._____
.byte CT_NONE ; 47/2f _____/_____
.byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____
.byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____
.byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____
.byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____
.byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____
.byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____
.byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____
.byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____
.byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____
.byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____
.byte CT_NONE ; 58/3a _____:_____
.byte CT_NONE ; 59/3b _____;_____
.byte CT_NONE ; 60/3c _____<_____
.byte CT_NONE ; 61/3d _____=_____
.byte CT_NONE ; 62/3e _____>_____
.byte CT_NONE ; 63/3f _____?_____
.byte CT_NONE ; 64/40 _____@_____
.byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____
.byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____
.byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____
.byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____
.byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____
.byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____
.byte CT_UPPER ; 71/47 _____G_____
.byte CT_UPPER ; 72/48 _____H_____
.byte CT_UPPER ; 73/49 _____I_____
.byte CT_UPPER ; 74/4a _____J_____
.byte CT_UPPER ; 75/4b _____K_____
.byte CT_UPPER ; 76/4c _____L_____
.byte CT_UPPER ; 77/4d _____M_____
.byte CT_UPPER ; 78/4e _____N_____
.byte CT_UPPER ; 79/4f _____O_____
.byte CT_UPPER ; 80/50 _____P_____
.byte CT_UPPER ; 81/51 _____Q_____
.byte CT_UPPER ; 82/52 _____R_____
.byte CT_UPPER ; 83/53 _____S_____
.byte CT_UPPER ; 84/54 _____T_____
.byte CT_UPPER ; 85/55 _____U_____
.byte CT_UPPER ; 86/56 _____V_____
.byte CT_UPPER ; 87/57 _____W_____
.byte CT_UPPER ; 88/58 _____X_____
.byte CT_UPPER ; 89/59 _____Y_____
.byte CT_UPPER ; 90/5a _____Z_____
.byte CT_NONE ; 91/5b _____[_____
.byte CT_NONE ; 92/5c _____\_____
.byte CT_NONE ; 93/5d _____]_____
.byte CT_NONE ; 94/5e _____^_____
.byte CT_NONE ; 95/5f _UNDERLINE_
.byte CT_NONE ; 96/60 ___grave___
.byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____
.byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____
.byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____
.byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____
.byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____
.byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____
.byte CT_LOWER ; 103/67 _____g_____
.byte CT_LOWER ; 104/68 _____h_____
.byte CT_LOWER ; 105/69 _____i_____
.byte CT_LOWER ; 106/6a _____j_____
.byte CT_LOWER ; 107/6b _____k_____
.byte CT_LOWER ; 108/6c _____l_____
.byte CT_LOWER ; 109/6d _____m_____
.byte CT_LOWER ; 110/6e _____n_____
.byte CT_LOWER ; 111/6f _____o_____
.byte CT_LOWER ; 112/70 _____p_____
.byte CT_LOWER ; 113/71 _____q_____
.byte CT_LOWER ; 114/72 _____r_____
.byte CT_LOWER ; 115/73 _____s_____
.byte CT_LOWER ; 116/74 _____t_____
.byte CT_LOWER ; 117/75 _____u_____
.byte CT_LOWER ; 118/76 _____v_____
.byte CT_LOWER ; 119/77 _____w_____
.byte CT_LOWER ; 120/78 _____x_____
.byte CT_LOWER ; 121/79 _____y_____
.byte CT_LOWER ; 122/7a _____z_____
.byte CT_NONE ; 123/7b _____{_____
.byte CT_NONE ; 124/7c _____|_____
.byte CT_NONE ; 125/7d _____}_____
.byte CT_NONE ; 126/7e _____~_____
.byte CT_OTHER_WS ; 127/7f ____DEL____
.endrepeat
Loading…
Cancel
Save