mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
Added a --extended-libc option and some headers to allow porting external programs.
This commit is contained in:
parent
765bb97ee7
commit
7a888fc90a
15 changed files with 412 additions and 58 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -18,3 +18,5 @@ gintdemo.g1a
|
||||||
|
|
||||||
# Configuration files
|
# Configuration files
|
||||||
gcc.cfg
|
gcc.cfg
|
||||||
|
Makefile.cfg
|
||||||
|
|
||||||
|
|
15
Makefile
15
Makefile
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
#---
|
#---
|
||||||
|
|
||||||
|
include Makefile.cfg
|
||||||
|
|
||||||
#---
|
#---
|
||||||
# Project variables.
|
# Project variables.
|
||||||
|
@ -48,7 +48,10 @@ obj-lib-spec = build/display_font_system.bmp.o
|
||||||
obj-std-spec =
|
obj-std-spec =
|
||||||
|
|
||||||
# Configuration files
|
# Configuration files
|
||||||
config = gcc.cfg
|
config = gcc.cfg
|
||||||
|
ifeq ($(wildcard $(config)),)
|
||||||
|
$(error "Configuration files are missing. Did you ./configure ?")
|
||||||
|
endif
|
||||||
|
|
||||||
# Target folder
|
# Target folder
|
||||||
folder := $(shell fxsdk --folder)
|
folder := $(shell fxsdk --folder)
|
||||||
|
@ -127,16 +130,13 @@ endef
|
||||||
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
||||||
|
|
||||||
$(config):
|
|
||||||
$(error "Configuration files are missing. Did you ./configure?")
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||||
$(if $(VERBOSE),,@) mkdir -p $@
|
$(if $(VERBOSE),,@) mkdir -p $@
|
||||||
|
|
||||||
$(obj-std) $(obj-lib) $(demo-obj): | build
|
$(obj-std) $(obj-lib) $(demo-obj): | build
|
||||||
|
|
||||||
$(target-std): $(config) $(obj-std)
|
$(target-std): $(obj-std)
|
||||||
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
||||||
|
@ -217,6 +217,9 @@ install: $(target-std) $(target-lib)
|
||||||
install -m 644 -T demo/gintdemo.ld $(folder)/linker.ld
|
install -m 644 -T demo/gintdemo.ld $(folder)/linker.ld
|
||||||
mkdir -p $(folder)/gint
|
mkdir -p $(folder)/gint
|
||||||
install -m 644 include/*.h $(folder)/gint
|
install -m 644 include/*.h $(folder)/gint
|
||||||
|
ifdef config_ext
|
||||||
|
install -m 644 include/extended/*.h $(folder)/gint
|
||||||
|
endif
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m All installed!\n'
|
@ printf '\e[32;1mmsg \u00bb\e[0m All installed!\n'
|
||||||
|
|
||||||
install_demo:
|
install_demo:
|
||||||
|
|
2
TODO
2
TODO
|
@ -12,6 +12,8 @@ Simple improvements:
|
||||||
- core: Add VBR handlers debugging information (if possible)
|
- core: Add VBR handlers debugging information (if possible)
|
||||||
- events: Introduce KeyRepeat events
|
- events: Introduce KeyRepeat events
|
||||||
- library: Implement C99's inttypes.h for Cake's UpdateExe
|
- library: Implement C99's inttypes.h for Cake's UpdateExe
|
||||||
|
- string: Use cmp/str to implement memchr() (assembler examples)
|
||||||
|
- string: Do some tests for memcmp()
|
||||||
Larger improvements:
|
Larger improvements:
|
||||||
- errno: Introduce errno and use it more or less everywhere
|
- errno: Introduce errno and use it more or less everywhere
|
||||||
- bopti: Monochrome bitmaps blending modes
|
- bopti: Monochrome bitmaps blending modes
|
||||||
|
|
50
configure
vendored
50
configure
vendored
|
@ -5,8 +5,16 @@ conf[ATEXIT_MAX]=16
|
||||||
conf[RTC_CB_ARRAY_SIZE]=5
|
conf[RTC_CB_ARRAY_SIZE]=5
|
||||||
conf[EVENTS_QUEUE_SIZE]=64
|
conf[EVENTS_QUEUE_SIZE]=64
|
||||||
conf[GINT_NO_SYSCALLS]=
|
conf[GINT_NO_SYSCALLS]=
|
||||||
|
conf[GINT_EXTENDED_LIBC]=
|
||||||
fail=false
|
fail=false
|
||||||
output="gcc.cfg"
|
output_gcc="gcc.cfg"
|
||||||
|
output_make="Makefile.cfg"
|
||||||
|
|
||||||
|
error="\e[31;1merror:\e[0m"
|
||||||
|
Cr="$(tput setaf 1)$(tput bold)"
|
||||||
|
Cg="$(tput setaf 2)$(tput bold)"
|
||||||
|
Cp="$(tput setaf 5)$(tput setaf 62)$(tput bold)"
|
||||||
|
C0="$(tput setaf 0)$(tput sgr 0)"
|
||||||
|
|
||||||
help()
|
help()
|
||||||
{
|
{
|
||||||
|
@ -14,16 +22,19 @@ help()
|
||||||
Configuration script for the gint library.
|
Configuration script for the gint library.
|
||||||
|
|
||||||
Options that affect the behavior of the library:
|
Options that affect the behavior of the library:
|
||||||
--no-syscalls [default: false]
|
$Cr--no-syscalls$C0 [default:$Cp false$C0]
|
||||||
Never use syscalls. Expect some trouble with the malloc() function...
|
Never use syscalls. Expect some trouble with the malloc() function...
|
||||||
Do not trigger this option unless you know what you are doing.
|
Do not enable this option unless you know what you are doing.
|
||||||
|
$Cr--extended-libc$C0 [default:$Cp false$C0]
|
||||||
|
Enable specific C99 headers/features that are normally not required by
|
||||||
|
calculator programs. May allow porting programs from other platforms.
|
||||||
|
|
||||||
Options that customize size limits:
|
Options that customize size limits:
|
||||||
--atexit-max=<integer> [default: 16]
|
$Cr--atexit-max=$C0$Cg<integer>$C0 [default:$Cp 16$C0]
|
||||||
Number of exit handlers that can be registered by atexit().
|
Number of exit handlers that can be registered by atexit().
|
||||||
--rtc-callbacks=<integer> [default: 5]
|
$Cr--rtc-callbacks=$C0$Cg<integer>$C0 [default:$Cp 5$C0]
|
||||||
Number of RTC callbacks that can be registered.
|
Number of RTC callbacks that can be registered.
|
||||||
--events-queue-size=<integer> [default: 64]
|
$Cr--events-queue-size=$C0$Cg<integer>$C0 [default:$Cp 64$C0]
|
||||||
Number of events simultaneously stored in the event queue.
|
Number of events simultaneously stored in the event queue.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -33,34 +44,36 @@ EOF
|
||||||
for arg; do case "$arg" in
|
for arg; do case "$arg" in
|
||||||
-h | --help) help;;
|
-h | --help) help;;
|
||||||
--no-syscalls) conf[GINT_NO_SYSCALLS]=true;;
|
--no-syscalls) conf[GINT_NO_SYSCALLS]=true;;
|
||||||
|
--extended-libc) conf[GINT_EXTENDED_LIBC]=true;;
|
||||||
|
|
||||||
--atexit-max=*)
|
--atexit-max=*)
|
||||||
size=${arg#*=}
|
size=${arg#*=}
|
||||||
if [[ $size == +([0-9]) ]]; then
|
if [[ $size == +([0-9]) ]]; then
|
||||||
conf[ATEXIT_MAX]=$size
|
conf[ATEXIT_MAX]=$size
|
||||||
else echo "error: --atexit-max expects an integer value"
|
else echo -e "$error --atexit-max expects an integer value"
|
||||||
fail=true; fi;;
|
fail=true; fi;;
|
||||||
--rtc-callbacks=*)
|
--rtc-callbacks=*)
|
||||||
size=${arg#*=}
|
size=${arg#*=}
|
||||||
if [[ $size == +([0-9]) ]]; then
|
if [[ $size == +([0-9]) ]]; then
|
||||||
conf[RTC_CB_ARRAY_SIZE]=$size
|
conf[RTC_CB_ARRAY_SIZE]=$size
|
||||||
else echo "error: --rtc-callbacks expects an integer value"
|
else echo -e "$error --rtc-callbacks expects an integer value"
|
||||||
fail=true; fi;;
|
fail=true; fi;;
|
||||||
--events-queue-size=*)
|
--events-queue-size=*)
|
||||||
size=${arg#*=}
|
size=${arg#*=}
|
||||||
if [[ $size == +([0-9]) ]]; then
|
if [[ $size == +([0-9]) ]]; then
|
||||||
conf[EVENTS_QUEUE_SIZE]=$size
|
conf[EVENTS_QUEUE_SIZE]=$size
|
||||||
else echo "error: --events-queue-size expects an integer value"
|
else echo -e "$error --events-queue-size expects an integer"\
|
||||||
|
"value"
|
||||||
fail=true; fi;;
|
fail=true; fi;;
|
||||||
|
|
||||||
--atexit-max | --rtc-callbacks | --events-queue-size)
|
--atexit-max | --rtc-callbacks | --events-queue-size)
|
||||||
echo "error: syntax for $arg is $arg=<integer-value>";;
|
echo -e "$error syntax for $arg is $arg=<integer-value>";;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "error: unrecognized argument '$arg'"; fail=true;;
|
echo -e "$error unrecognized argument '$arg'"; fail=true;;
|
||||||
esac; done
|
esac; done
|
||||||
|
|
||||||
output_config()
|
output_config_gcc()
|
||||||
{
|
{
|
||||||
echo "-D ATEXIT_MAX=${conf[ATEXIT_MAX]}"
|
echo "-D ATEXIT_MAX=${conf[ATEXIT_MAX]}"
|
||||||
echo "-D RTC_CB_ARRAY_SIZE=${conf[RTC_CB_ARRAY_SIZE]}"
|
echo "-D RTC_CB_ARRAY_SIZE=${conf[RTC_CB_ARRAY_SIZE]}"
|
||||||
|
@ -68,11 +81,20 @@ output_config()
|
||||||
if [ "${conf[GINT_NO_SYSCALLS]}" != "" ]; then
|
if [ "${conf[GINT_NO_SYSCALLS]}" != "" ]; then
|
||||||
echo "-D GINT_NO_SYSCALLS"
|
echo "-D GINT_NO_SYSCALLS"
|
||||||
fi
|
fi
|
||||||
|
if [ "${conf[GINT_EXTENDED_LIBC]}" != "" ]; then
|
||||||
|
echo "-D GINT_EXTENDED_LIBC"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
output_config_make()
|
||||||
|
{
|
||||||
|
[ "${conf[GINT_EXTENDED_LIBC]}" != "" ] && echo "config_ext=true"
|
||||||
}
|
}
|
||||||
|
|
||||||
if $fail; then
|
if $fail; then
|
||||||
echo "Configuration has not been modified."
|
echo "Configuration has not been modified."
|
||||||
else
|
else
|
||||||
output_config > $output
|
output_config_gcc > $output_gcc
|
||||||
echo "Configuration details have been output to file $output."
|
output_config_make > $output_make
|
||||||
|
echo "Configuration saved in $output_gcc and $output_make."
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -9,27 +9,76 @@
|
||||||
#ifndef _CTYPE_H
|
#ifndef _CTYPE_H
|
||||||
#define _CTYPE_H 1
|
#define _CTYPE_H 1
|
||||||
|
|
||||||
// Character definition macros.
|
#include <stdint.h>
|
||||||
#define isalnum(c) (isdigit(c) || isalpha(c))
|
|
||||||
#define isalpha(c) (islower(c) || isupper(c))
|
|
||||||
|
|
||||||
#define iscntrl(c) ((c) <= 0x1f || (c) == 0x7f)
|
//---
|
||||||
#define isdigit(c) ((c) >= '0' && (c) <= '9')
|
// Character classes.
|
||||||
#define isgraph(c) ((c) > ' ' && (c) < 0x7f)
|
//---
|
||||||
#define islower(c) ((c) >= 'a' && (c) <= 'z')
|
|
||||||
#define isprint(c) ((c) >= ' ' && (c) < 0x7f)
|
|
||||||
#define ispunct(c) (((c) >= '!' && (c) <= '/') || \
|
|
||||||
((c) >= ':' && (c) <= '@') || \
|
|
||||||
((c) >= '[' && (c) <= '`') || \
|
|
||||||
((c) >= '{' && (c) <= '~'))
|
|
||||||
#define isspace(c) (((c) >= '\t' && (c) <= '\r') || (c) == ' ')
|
|
||||||
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
|
|
||||||
#define isxdigit(c) (((c) >= '0' && (c) <= '9') || \
|
|
||||||
((c) >= 'A' && (c) <= 'F') || \
|
|
||||||
((c) >= 'a' && (c) <= 'f'))
|
|
||||||
|
|
||||||
// Character manipulation macros.
|
extern uint8_t ctype_classes[0x80];
|
||||||
#define tolower(c) (isupper(c) ? (c) | 32 : (c))
|
|
||||||
#define toupper(c) (islower(c) ? (c) & ~32 : (c))
|
__attribute__((always_inline)) static inline int isalnum(int c) {
|
||||||
|
return ctype_classes[c] & 0xf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isalpha(int c) {
|
||||||
|
return ctype_classes[c] & 0x30;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int iscntrl(int c) {
|
||||||
|
return ctype_classes[c] & 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isdigit(int c) {
|
||||||
|
return ctype_classes[c] & 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isgraph(int c) {
|
||||||
|
return ctype_classes[c] & 0xf4;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int islower(int c) {
|
||||||
|
return ctype_classes[c] & 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isprint(int c) {
|
||||||
|
return ctype_classes[c] & 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int ispunct(int c) {
|
||||||
|
return ctype_classes[c] & 0x04;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isspace(int c) {
|
||||||
|
return ctype_classes[c] & 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isupper(int c) {
|
||||||
|
return ctype_classes[c] & 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isxdigit(int c) {
|
||||||
|
return ctype_classes[c] & 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isascii(int c) {
|
||||||
|
return (c >= 0 && c <= 0x7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int isblank(int c) {
|
||||||
|
return (c == '\t' || c == ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Character manipulation.
|
||||||
|
//---
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int tolower(int c) {
|
||||||
|
return c | isupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline int toupper(int c) {
|
||||||
|
return c & ~(islower(c) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _CTYPE_H
|
#endif // _CTYPE_H
|
||||||
|
|
46
include/extended/endian.h
Normal file
46
include/extended/endian.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef _ENDIAN_H
|
||||||
|
#define _ENDIAN_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Assembler-optimized byte-ordering functions.
|
||||||
|
//---
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint16_t swap16(uint16_t word)
|
||||||
|
{
|
||||||
|
uint16_t result;
|
||||||
|
__asm__("swap.b %1, %0": "=r"(result): "r"(word));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint32_t swap32(uint32_t longw)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
__asm__(
|
||||||
|
"swap.b %1, r0 \n\t"
|
||||||
|
"swap.w r0, r0 \n\t"
|
||||||
|
"swap.b r0, %0 \n\t"
|
||||||
|
: "=r"(result)
|
||||||
|
: "r"(longw)
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Conversion of values of different endianness.
|
||||||
|
//---
|
||||||
|
|
||||||
|
#define htobe16(host16) (host16)
|
||||||
|
#define htole16(host16) (swap16(host16))
|
||||||
|
#define be16toh(be16) (be16)
|
||||||
|
#define le16toh(le16) (swap16(le16))
|
||||||
|
|
||||||
|
#define htobe32(host32) (host32)
|
||||||
|
#define htole32(host32) (swap32(host32))
|
||||||
|
#define be32toh(be32) (be32)
|
||||||
|
#define le32toh(le32) (swap32(le32))
|
||||||
|
|
||||||
|
#endif // _ENDIAN_H
|
|
@ -17,18 +17,34 @@
|
||||||
//---
|
//---
|
||||||
|
|
||||||
/*
|
/*
|
||||||
memcpy() O(byte_number)
|
memcpy() O(byte_count)
|
||||||
Copies a memory area. The two areas must not overlap (if they do, use
|
Copies a memory area. The two areas must not overlap (if they do, use
|
||||||
memmove()). A smart copy is performed when possible. To enhance
|
memmove()). A smart copy is performed when possible. To enhance
|
||||||
performance, make sure than destination and source are both 4-aligned.
|
performance, make sure than destination and source are both 4-aligned.
|
||||||
*/
|
*/
|
||||||
void *memcpy(void *destination, const void *source, size_t byte_number);
|
void *memcpy(void *destination, const void *source, size_t byte_count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
memset() O(byte_number)
|
memset() O(byte_count)
|
||||||
Sets the contents of a memory area. A smart copy is performed.
|
Sets the contents of a memory area. A smart copy is performed.
|
||||||
*/
|
*/
|
||||||
void *memset(void *destination, int byte, size_t byte_number);
|
void *memset(void *destination, int byte, size_t byte_count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
memchr() O(byte_count)
|
||||||
|
Looks for a byte in a memory area. Returns the address of the first
|
||||||
|
occurrence if found, NULL otherwise.
|
||||||
|
*/
|
||||||
|
void *memchr(const void *area, int byte, size_t byte_count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
memcmp() O(byte_count)
|
||||||
|
Compares two memory areas. Returns 0 if all bytes are equal in both
|
||||||
|
areas, a negative number if the first unequal byte is lower in the
|
||||||
|
first area, and a positive number otherwise.
|
||||||
|
A smart comparison is performed when possible.
|
||||||
|
*/
|
||||||
|
int memcmp(const void *area1, const void *area2, size_t byte_count);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,12 +58,25 @@ void *memset(void *destination, int byte, size_t byte_number);
|
||||||
*/
|
*/
|
||||||
size_t strlen(const char *str);
|
size_t strlen(const char *str);
|
||||||
|
|
||||||
|
/*
|
||||||
|
strnlen() O(len(str))
|
||||||
|
Returns the minimum of the length of the string and n. This function
|
||||||
|
never access more than n bytes at the beginning of the string.
|
||||||
|
*/
|
||||||
|
size_t strnlen(const char *str, size_t n);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
strcpy() O(len(source))
|
strcpy() O(len(source))
|
||||||
Copies a string to another.
|
Copies a string to another.
|
||||||
*/
|
*/
|
||||||
char *strcpy(char *destination, const char *source);
|
char *strcpy(char *destination, const char *source);
|
||||||
|
|
||||||
|
/*
|
||||||
|
strncpy() O(min(len(source), size))
|
||||||
|
Copies part of a string to another.
|
||||||
|
*/
|
||||||
|
char *strncpy(char *destination, const char *source, size_t size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
strchr() O(len(str))
|
strchr() O(len(str))
|
||||||
Searches a character in a string.
|
Searches a character in a string.
|
||||||
|
@ -55,9 +84,11 @@ char *strcpy(char *destination, const char *source);
|
||||||
const char *strchr(const char *str, int value);
|
const char *strchr(const char *str, int value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
strncpy() O(min(len(source), size))
|
strcmp() O(max(len(str1), len(str2)))
|
||||||
Copies part of a string to another.
|
Compares two strings. Returns 0 if they are identical, a negative
|
||||||
|
number if the first unequal byte is lower in str1 than in str2, and a
|
||||||
|
positive number otherwise.
|
||||||
*/
|
*/
|
||||||
char *strncpy(char *destination, const char *source, size_t size);
|
int strcmp(const char *str1, const char *str2);
|
||||||
|
|
||||||
#endif // _STRING_H
|
#endif // _STRING_H
|
||||||
|
|
64
src/string/ctype.c
Normal file
64
src/string/ctype.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
cntrl = 0x01,
|
||||||
|
space = 0x02,
|
||||||
|
punct = 0x04,
|
||||||
|
print = 0x08,
|
||||||
|
upper = 0x20,
|
||||||
|
lower = 0x10,
|
||||||
|
digit = 0x40,
|
||||||
|
xdigt = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t ctype_classes[0x80] = {
|
||||||
|
// Control characters.
|
||||||
|
cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl,
|
||||||
|
cntrl | space, // Tabulation
|
||||||
|
cntrl | space, cntrl | space, cntrl | space, cntrl | space,
|
||||||
|
cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl,
|
||||||
|
cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl,
|
||||||
|
|
||||||
|
// Space and some punctuation.
|
||||||
|
space | print,
|
||||||
|
punct | print, punct | print, punct | print, punct | print,
|
||||||
|
punct | print, punct | print, punct | print, punct | print,
|
||||||
|
punct | print, punct | print, punct | print, punct | print,
|
||||||
|
punct | print, punct | print, punct | print,
|
||||||
|
|
||||||
|
// Decimal digits.
|
||||||
|
digit | xdigt | print, digit | xdigt | print, digit | xdigt | print,
|
||||||
|
digit | xdigt | print, digit | xdigt | print, digit | xdigt | print,
|
||||||
|
digit | xdigt | print, digit | xdigt | print, digit | xdigt | print,
|
||||||
|
digit | xdigt | print,
|
||||||
|
|
||||||
|
// Some punctuation.
|
||||||
|
punct | print, punct | print, punct | print, punct | print,
|
||||||
|
punct | print, punct | print, punct | print,
|
||||||
|
|
||||||
|
// Uppercase alphabet.
|
||||||
|
upper | xdigt | print, upper | xdigt | print, upper | xdigt | print,
|
||||||
|
upper | xdigt | print, upper | xdigt | print, upper | xdigt | print,
|
||||||
|
upper | print, upper | print, upper | print, upper | print,
|
||||||
|
upper | print, upper | print, upper | print, upper | print,
|
||||||
|
upper | print, upper | print, upper | print, upper | print,
|
||||||
|
upper | print, upper | print, upper | print, upper | print,
|
||||||
|
upper | print, upper | print, upper | print, upper | print,
|
||||||
|
|
||||||
|
// Other punctuation symbols.
|
||||||
|
punct | print, punct | print, punct | print, punct | print,
|
||||||
|
punct | print, punct | print,
|
||||||
|
|
||||||
|
// Lowercase alphabet.
|
||||||
|
lower | xdigt | print, lower | xdigt | print, lower | xdigt | print,
|
||||||
|
lower | xdigt | print, lower | xdigt | print, lower | xdigt | print,
|
||||||
|
lower | print, lower | print, lower | print, lower | print,
|
||||||
|
lower | print, lower | print, lower | print, lower | print,
|
||||||
|
lower | print, lower | print, lower | print, lower | print,
|
||||||
|
lower | print, lower | print, lower | print, lower | print,
|
||||||
|
lower | print, lower | print, lower | print, lower | print,
|
||||||
|
|
||||||
|
// Last punctuation characters and DEL.
|
||||||
|
punct | print, punct | print, punct | print, punct | print,
|
||||||
|
cntrl
|
||||||
|
};
|
20
src/string/memchr.c
Normal file
20
src/string/memchr.c
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
memchr() O(byte_count)
|
||||||
|
Looks for a byte in a memory area. Returns the address of the first
|
||||||
|
occurrence if found, NULL otherwise.
|
||||||
|
*/
|
||||||
|
void *memchr(const void *area, int byte, size_t byte_count)
|
||||||
|
{
|
||||||
|
const uint8_t *mem = area;
|
||||||
|
|
||||||
|
while(byte_count--)
|
||||||
|
{
|
||||||
|
if(*mem == byte) return (void *)mem;
|
||||||
|
mem++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
84
src/string/memcmp.c
Normal file
84
src/string/memcmp.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int raw_cmp(const uint8_t *mem1, const uint8_t *mem2, size_t byte_count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
memcmp() O(byte_count)
|
||||||
|
Compares two memory areas. Returns 0 if all bytes are equal in both
|
||||||
|
areas, a negative number if the first unequal byte is lower in the
|
||||||
|
first area, and a positive number otherwise.
|
||||||
|
A smart comparison is performed when possible.
|
||||||
|
*/
|
||||||
|
int memcmp(const void *area1, const void *area2, size_t byte_count)
|
||||||
|
{
|
||||||
|
const uint8_t *mem1 = (const uint8_t *)area1;
|
||||||
|
const uint8_t *mem2 = (const uint8_t *)area2;
|
||||||
|
|
||||||
|
// Trying to do long-based comparisons.
|
||||||
|
if(((intptr_t)area1 & 3) == ((intptr_t)area2 & 3))
|
||||||
|
{
|
||||||
|
// Getting to a 4-byte offset.
|
||||||
|
while((intptr_t)mem1 & 3)
|
||||||
|
{
|
||||||
|
if(*mem1 != *mem2) return *mem1 - *mem2;
|
||||||
|
mem1++, mem2++;
|
||||||
|
byte_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing groups of four bytes.
|
||||||
|
while(byte_count >= 4)
|
||||||
|
{
|
||||||
|
uint32_t long1 = *((uint32_t *)mem1);
|
||||||
|
uint32_t long2 = *((uint32_t *)mem2);
|
||||||
|
if(long1 != long2) return raw_cmp(mem1, mem2, 4);
|
||||||
|
mem1 += 4, mem2 += 4;
|
||||||
|
byte_count -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing the last bytes.
|
||||||
|
return raw_cmp(mem1, mem2, byte_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Well, maybe we can do a word-based operation?
|
||||||
|
else if(((intptr_t)area1 & 1) == ((intptr_t)area2 & 3))
|
||||||
|
{
|
||||||
|
// Getting to the word offset.
|
||||||
|
if((intptr_t)mem1 & 1)
|
||||||
|
{
|
||||||
|
if(*mem1 != *mem2) return *mem1 - *mem2;
|
||||||
|
mem1++, mem2++;
|
||||||
|
byte_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing groups of two bytes.
|
||||||
|
while(byte_count >= 2)
|
||||||
|
{
|
||||||
|
uint16_t word1 = *((uint16_t *)mem1);
|
||||||
|
uint16_t word2 = *((uint16_t *)mem2);
|
||||||
|
if(word1 != word2) return raw_cmp(mem1, mem2, 2);
|
||||||
|
mem1 += 2, mem2 += 2;
|
||||||
|
byte_count -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing the last byte.
|
||||||
|
if(!byte_count) return 0;
|
||||||
|
return *mem1 - *mem2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's too bad, we'll have to compare everything manually.
|
||||||
|
else return raw_cmp(mem1, mem2, byte_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int raw_cmp(const uint8_t *mem1, const uint8_t *mem2, size_t byte_count)
|
||||||
|
{
|
||||||
|
while(byte_count)
|
||||||
|
{
|
||||||
|
if(*mem1 != *mem2) return *mem1 - *mem2;
|
||||||
|
mem1++;
|
||||||
|
mem2++;
|
||||||
|
byte_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
memcpy()
|
memcpy() O(n)
|
||||||
Copies a memory area. A smart copy is performed if possible.
|
Copies a memory area. A smart copy is performed if possible.
|
||||||
*/
|
*/
|
||||||
void *memcpy(void *d, const void *s, size_t n)
|
void *memcpy(void *d, const void *s, size_t n)
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
memset()
|
memset() O(byte_count)
|
||||||
Sets the contents of a memory area. A smart copy is performed.
|
Sets the contents of a memory area. A smart copy is performed.
|
||||||
*/
|
*/
|
||||||
void *memset(void *d, int byte, size_t byte_number)
|
void *memset(void *d, int byte, size_t byte_count)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)d;
|
uint8_t *dest = (uint8_t *)d;
|
||||||
unsigned short word = (byte << 8) | byte;
|
unsigned short word = (byte << 8) | byte;
|
||||||
|
@ -13,12 +13,12 @@ void *memset(void *d, int byte, size_t byte_number)
|
||||||
|
|
||||||
// When the area is small, simply copying using byte operations. The
|
// When the area is small, simply copying using byte operations. The
|
||||||
// minimum length used for long operations must be at least 3.
|
// minimum length used for long operations must be at least 3.
|
||||||
if(byte_number < 8)
|
if(byte_count < 8)
|
||||||
{
|
{
|
||||||
while(byte_number)
|
while(byte_count)
|
||||||
{
|
{
|
||||||
*dest++ = byte;
|
*dest++ = byte;
|
||||||
byte_number--;
|
byte_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
@ -28,20 +28,20 @@ void *memset(void *d, int byte, size_t byte_number)
|
||||||
while((intptr_t)dest & 3)
|
while((intptr_t)dest & 3)
|
||||||
{
|
{
|
||||||
*dest++ = byte;
|
*dest++ = byte;
|
||||||
byte_number--;
|
byte_count--;
|
||||||
}
|
}
|
||||||
// Copying using long operations.
|
// Copying using long operations.
|
||||||
while(byte_number >= 4)
|
while(byte_count >= 4)
|
||||||
{
|
{
|
||||||
*((uint32_t *)dest) = longword;
|
*((uint32_t *)dest) = longword;
|
||||||
dest += 4;
|
dest += 4;
|
||||||
byte_number -= 4;
|
byte_count -= 4;
|
||||||
}
|
}
|
||||||
// Ending the copy.
|
// Ending the copy.
|
||||||
while(byte_number)
|
while(byte_count)
|
||||||
{
|
{
|
||||||
*dest++ = byte;
|
*dest++ = byte;
|
||||||
byte_number--;
|
byte_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
|
18
src/string/strcmp.c
Normal file
18
src/string/strcmp.c
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
strcmp() O(max(len(str1), len(str2)))
|
||||||
|
Compares two strings. Returns 0 if they are identical, a negative
|
||||||
|
number if the first unequal byte is lower in str1 than in str2, and a
|
||||||
|
positive number otherwise.
|
||||||
|
*/
|
||||||
|
int strcmp(const char *str1, const char *str2)
|
||||||
|
{
|
||||||
|
while(*str1 && *str2 && *str1 == *str2)
|
||||||
|
{
|
||||||
|
str1++;
|
||||||
|
str2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *str1 - *str2;
|
||||||
|
}
|
13
src/string/strnlen.c
Normal file
13
src/string/strnlen.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
strnlen() O(len(str))
|
||||||
|
Returns the minimum of the length of the string and n. This function
|
||||||
|
never access more than n bytes at the beginning of the string.
|
||||||
|
*/
|
||||||
|
size_t strnlen(const char *str, size_t n)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while(len < n && str[len]) len++;
|
||||||
|
return len;
|
||||||
|
}
|
Loading…
Reference in a new issue