libc.obj:

- Formatted by clang-format (WebKit-style).
- Removed unnecessary errno linux. 
- Added KOS error codes. 
- String functions have been replaced with more optimal ones for x86. 
- Changed wrappers for 70 sysfunction.

git-svn-id: svn://kolibrios.org@9765 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
turbocat 2022-04-15 09:00:55 +00:00
parent dff8056cd6
commit cde4fa851d
68 changed files with 1628 additions and 1762 deletions

View File

@ -1,21 +1,21 @@
#include <ctype.h> #include <ctype.h>
unsigned short __is[129] = { unsigned short __is[129] = {
0, /* EOF */ 0, /* EOF */
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004, 0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004,
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x140, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x140, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
0x459, 0x459, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x459, 0x459, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x0D0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253, 0x0D0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
0x253, 0x253, 0x253, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x253, 0x253, 0x253, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x0D0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073, 0x0D0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
0x073, 0x073, 0x073, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x004 0x073, 0x073, 0x073, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x004
}; };

View File

@ -2,6 +2,7 @@
int tolower(int c) int tolower(int c)
{ {
if (isupper(c)) return c | 32; if (isupper(c))
return c; return c | 32;
return c;
} }

View File

@ -2,6 +2,7 @@
int toupper(int c) int toupper(int c)
{ {
if (islower(c)) return c & 0x5f; if (islower(c))
return c; return c & 0x5f;
return c;
} }

View File

@ -4,103 +4,101 @@
#include "ctype/tolower.c" #include "ctype/tolower.c"
#include "ctype/toupper.c" #include "ctype/toupper.c"
#include "sys/rewinddir.c"
#include "sys/readdir.c"
#include "sys/seekdir.c"
#include "sys/opendir.c"
#include "sys/telldir.c"
#include "sys/closedir.c" #include "sys/closedir.c"
#include "sys/dir.c" #include "sys/dir.c"
#include "sys/opendir.c"
#include "sys/readdir.c"
#include "sys/rewinddir.c"
#include "sys/seekdir.c"
#include "sys/socket.c" #include "sys/socket.c"
#include "sys/telldir.c"
#include "stdio/clearerr.c" #include "stdio/clearerr.c"
#include "stdio/gets.c" #include "stdio/conio.c"
#include "stdio/setbuf.c" #include "stdio/debug_printf.c"
#include "stdio/fclose.c"
#include "stdio/feof.c"
#include "stdio/ferror.c"
#include "stdio/fflush.c"
#include "stdio/fgetc.c" #include "stdio/fgetc.c"
#include "stdio/fgetpos.c"
#include "stdio/fgets.c"
#include "stdio/fopen.c" #include "stdio/fopen.c"
#include "stdio/format_print.c" #include "stdio/format_print.c"
#include "stdio/vprintf.c"
#include "stdio/feof.c"
#include "stdio/fwrite.c"
#include "stdio/fread.c"
#include "stdio/fseek.c"
#include "stdio/fgetpos.c"
#include "stdio/fclose.c"
#include "stdio/snprintf.c"
#include "stdio/rename.c"
#include "stdio/getchar.c"
#include "stdio/remove.c"
#include "stdio/ferror.c"
#include "stdio/tmpfile.c"
#include "stdio/fputs.c"
#include "stdio/fputc.c"
#include "stdio/fgets.c"
#include "stdio/fflush.c"
#include "stdio/format_scan.c" #include "stdio/format_scan.c"
#include "stdio/printf.c"
#include "stdio/fscanf.c"
#include "stdio/debug_printf.c"
#include "stdio/fsetpos.c"
#include "stdio/setvbuf.c"
#include "stdio/sscanf.c"
#include "stdio/scanf.c"
#include "stdio/freopen.c"
#include "stdio/puts.c"
#include "stdio/sprintf.c"
#include "stdio/vsnprintf.c"
#include "stdio/conio.c"
#include "stdio/perror.c"
#include "stdio/ftell.c"
#include "stdio/tmpnam.c"
#include "stdio/rewind.c"
#include "stdio/vfprintf.c"
#include "stdio/fprintf.c" #include "stdio/fprintf.c"
#include "stdio/fputc.c"
#include "stdio/fputs.c"
#include "stdio/fread.c"
#include "stdio/freopen.c"
#include "stdio/fscanf.c"
#include "stdio/fseek.c"
#include "stdio/fsetpos.c"
#include "stdio/ftell.c"
#include "stdio/fwrite.c"
#include "stdio/getchar.c"
#include "stdio/gets.c"
#include "stdio/perror.c"
#include "stdio/printf.c"
#include "stdio/puts.c"
#include "stdio/remove.c"
#include "stdio/rename.c"
#include "stdio/rewind.c"
#include "stdio/scanf.c"
#include "stdio/setbuf.c"
#include "stdio/setvbuf.c"
#include "stdio/snprintf.c"
#include "stdio/sprintf.c"
#include "stdio/sscanf.c"
#include "stdio/tmpfile.c"
#include "stdio/tmpnam.c"
#include "stdio/ungetc.c" #include "stdio/ungetc.c"
#include "stdio/vfprintf.c"
#include "stdio/vprintf.c"
#include "stdio/vsnprintf.c"
#include "string/strerror.c"
#include "string/strxfrm.c"
#include "string/strrchr.c"
#include "string/strcspn.c"
#include "string/strlen.c"
#include "string/strrev.c"
#include "string/memccpy.c" #include "string/memccpy.c"
#include "string/strchr.c"
#include "string/strcoll.c"
#include "string/strpbrk.c"
#include "string/strstr.c"
#include "string/memcmp.c"
#include "string/strspn.c"
#include "string/strcpy.c"
#include "string/strncpy.c"
#include "string/strdup.c"
#include "string/strcat.c"
#include "string/memchr.c" #include "string/memchr.c"
#include "string/strncmp.c" #include "string/memcmp.c"
#include "string/strncat.c"
#include "string/strtok.c"
#include "string/strcmp.c"
#include "string/memset.c"
#include "string/memcpy.c" #include "string/memcpy.c"
#include "string/memmove.c" #include "string/strcat.c"
#include "string/strchr.c"
#include "string/strcmp.c"
#include "string/strcoll.c"
#include "string/strcpy.c"
#include "string/strcspn.c"
#include "string/strdup.c"
#include "string/strerror.c"
#include "string/strlen.c"
#include "string/strncat.c"
#include "string/strncmp.c"
#include "string/strncpy.c"
#include "string/strpbrk.c"
#include "string/strrchr.c"
#include "string/strrev.c"
#include "string/strspn.c"
#include "string/strstr.c"
#include "string/strtok.c"
#include "string/strxfrm.c"
#include "stdlib/calloc.c"
#include "stdlib/malloc.c"
#include "stdlib/atoll.c"
#include "stdlib/free.c"
#include "stdlib/llabs.c"
#include "stdlib/exit.c"
#include "stdlib/atoi.c"
#include "stdlib/labs.c"
#include "stdlib/realloc.c"
#include "stdlib/abs.c" #include "stdlib/abs.c"
#include "stdlib/atol.c"
#include "stdlib/itoa.c"
#include "stdlib/strtol.c"
#include "stdlib/rand.c"
#include "stdlib/qsort.c"
#include "stdlib/assert.c" #include "stdlib/assert.c"
#include "stdlib/strtod.c"
#include "stdlib/atof.c" #include "stdlib/atof.c"
#include "stdlib/atoi.c"
#include "stdlib/atol.c"
#include "stdlib/atoll.c"
#include "stdlib/calloc.c"
#include "stdlib/exit.c"
#include "stdlib/free.c"
#include "stdlib/itoa.c"
#include "stdlib/labs.c"
#include "stdlib/llabs.c"
#include "stdlib/malloc.c"
#include "stdlib/qsort.c"
#include "stdlib/rand.c"
#include "stdlib/realloc.c"
#include "stdlib/strtod.c"
#include "stdlib/strtol.c"
#include "math/acosh.c" #include "math/acosh.c"
#include "math/asinh.c" #include "math/asinh.c"
@ -112,11 +110,11 @@
#include "math/sinh.c" #include "math/sinh.c"
#include "math/tanh.c" #include "math/tanh.c"
#include "time/asctime.c"
#include "time/difftime.c" #include "time/difftime.c"
#include "time/localtime.c" #include "time/localtime.c"
#include "time/mktime.c" #include "time/mktime.c"
#include "time/time.c" #include "time/time.c"
#include "time/asctime.c"
#include "misc/basename.c" #include "misc/basename.c"
#include "misc/dirname.c" #include "misc/dirname.c"
@ -140,184 +138,183 @@ __asm__(
".include \"math/pow10.s\"\n\t" ".include \"math/pow10.s\"\n\t"
".include \"math/sqrt.s\"\n\t" ".include \"math/sqrt.s\"\n\t"
".include \"math/sin.s\"\n\t" ".include \"math/sin.s\"\n\t"
".include \"math/tan.s\"\n\t" ".include \"math/tan.s\"\n\t");
);
__asm__( __asm__(
".include \"string/memmove.s\"\n\t"
".include \"string/memset.s\"\n\t"
".include \"setjmp/longjmp.s\"\n\t" ".include \"setjmp/longjmp.s\"\n\t"
".include \"setjmp/setjmp.s\"" ".include \"setjmp/setjmp.s\"");
);
#include "libtcc1/libtcc1.c" #include "libtcc1/libtcc1.c"
#include "stdlib/___chkstk_ms.c" #include "stdlib/___chkstk_ms.c"
ksys_dll_t EXPORTS[] = { ksys_dll_t EXPORTS[] = {
{"clearerr", &clearerr}, { "clearerr", &clearerr },
{"debug_printf", &debug_printf}, { "debug_printf", &debug_printf },
{"fclose", &fclose}, { "fclose", &fclose },
{"feof", &feof}, { "feof", &feof },
{"ferror", &ferror}, { "ferror", &ferror },
{"fflush", &fflush}, { "fflush", &fflush },
{"fgetc", &fgetc}, { "fgetc", &fgetc },
{"fgetpos", &fgetpos}, { "fgetpos", &fgetpos },
{"fgets", &fgets}, { "fgets", &fgets },
{"fopen", &fopen}, { "fopen", &fopen },
{"fprintf", &fprintf}, { "fprintf", &fprintf },
{"fputc", &fputc}, { "fputc", &fputc },
{"fputs", &fputs}, { "fputs", &fputs },
{"fread", &fread}, { "fread", &fread },
{"freopen", &freopen}, { "freopen", &freopen },
{"fscanf", &fscanf}, { "fscanf", &fscanf },
{"fseek", &fseek}, { "fseek", &fseek },
{"fsetpos", &fsetpos}, { "fsetpos", &fsetpos },
{"ftell", &ftell}, { "ftell", &ftell },
{"fwrite", &fwrite}, { "fwrite", &fwrite },
{"getchar", &getchar}, { "getchar", &getchar },
{"gets", &gets}, { "gets", &gets },
{"perror", &perror}, { "perror", &perror },
{"printf", &printf}, { "printf", &printf },
{"puts", &puts}, { "puts", &puts },
{"remove", &remove}, { "remove", &remove },
{"rename", &rename}, { "rename", &rename },
{"rewind", &rewind}, { "rewind", &rewind },
{"scanf", &scanf}, { "scanf", &scanf },
{"setbuf", &setbuf}, { "setbuf", &setbuf },
{"setvbuf", &setvbuf}, { "setvbuf", &setvbuf },
{"snprintf", &snprintf}, { "snprintf", &snprintf },
{"sprintf", &sprintf}, { "sprintf", &sprintf },
{"sscanf", &sscanf}, { "sscanf", &sscanf },
{"tmpfile", &tmpfile}, { "tmpfile", &tmpfile },
{"tmpnam", &tmpnam}, { "tmpnam", &tmpnam },
{"vfscanf", &vfscanf}, { "vfscanf", &vfscanf },
{"vprintf", &vprintf}, { "vprintf", &vprintf },
{"vfscanf", &vfscanf}, { "vfscanf", &vfscanf },
{"vsprintf", &vsprintf}, { "vsprintf", &vsprintf },
{"vsnprintf", &vsnprintf}, { "vsnprintf", &vsnprintf },
{"vsscanf", &vsscanf}, { "vsscanf", &vsscanf },
{"ungetc", &ungetc}, { "ungetc", &ungetc },
{"abs", &abs}, { "abs", &abs },
{"atoi", &atoi}, { "atoi", &atoi },
{"atol", &atol}, { "atol", &atol },
{"atoll", &atoll}, { "atoll", &atoll },
{"atof", &atof}, { "atof", &atof },
{"calloc", &calloc}, { "calloc", &calloc },
{"exit", &exit}, { "exit", &exit },
{"free", &free}, { "free", &free },
{"itoa", &itoa}, { "itoa", &itoa },
{"labs", &labs}, { "labs", &labs },
{"llabs", &llabs}, { "llabs", &llabs },
{"malloc", &malloc}, { "malloc", &malloc },
{"realloc", &realloc}, { "realloc", &realloc },
{"strtol", &strtol}, { "strtol", &strtol },
{"srand", &srand}, { "srand", &srand },
{"rand", &rand}, { "rand", &rand },
{"qsort", &qsort}, { "qsort", &qsort },
{"strtod", &strtod}, { "strtod", &strtod },
{"__assert_fail", &__assert_fail}, { "__assert_fail", &__assert_fail },
{"memchr", &memchr}, { "memchr", &memchr },
{"memcmp", &memcmp}, { "memcmp", &memcmp },
{"strncat", &strncat}, { "strncat", &strncat },
{"strchr", &strchr}, { "strchr", &strchr },
{"strcat", &strcat}, { "strcat", &strcat },
{"strcmp", &strcmp}, { "strcmp", &strcmp },
{"strcoll", &strcoll}, { "strcoll", &strcoll },
{"strcpy", &strcpy}, { "strcpy", &strcpy },
{"strcspn", &strcspn}, { "strcspn", &strcspn },
{"strdup", &strdup}, { "strdup", &strdup },
{"strerror", &strerror}, { "strerror", &strerror },
{"strlen", &strlen}, { "strlen", &strlen },
{"strncat", &strncat}, { "strncat", &strncat },
{"strncmp", &strncmp}, { "strncmp", &strncmp },
{"strncpy", &strncpy}, { "strncpy", &strncpy },
{"strrchr", &strrchr}, { "strrchr", &strrchr },
{"strrev", &strrev}, { "strrev", &strrev },
{"strspn", &strspn}, { "strspn", &strspn },
{"strstr", &strstr}, { "strstr", &strstr },
{"strtok", &strtok}, { "strtok", &strtok },
{"strxfrm", &strxfrm}, { "strxfrm", &strxfrm },
{"_errno", &_errno}, { "__errno", &__errno },
{"closedir", &closedir}, { "closedir", &closedir },
{"opendir", &opendir}, { "opendir", &opendir },
{"readdir", &readdir}, { "readdir", &readdir },
{"rewinddir", &rewinddir}, { "rewinddir", &rewinddir },
{"seekdir", &seekdir}, { "seekdir", &seekdir },
{"telldir", &telldir}, { "telldir", &telldir },
{"getcwd", &getcwd}, { "getcwd", &getcwd },
{"mkdir", &mkdir}, { "mkdir", &mkdir },
{"rmdir", &rmdir}, { "rmdir", &rmdir },
{"setcwd", &setcwd}, { "setcwd", &setcwd },
{"getcwd", &getcwd}, { "getcwd", &getcwd },
{"socket", &socket}, { "socket", &socket },
{"close", &close}, { "close", &close },
{"bind", &bind}, { "bind", &bind },
{"listen", &listen}, { "listen", &listen },
{"connect", &connect}, { "connect", &connect },
{"accept", &accept}, { "accept", &accept },
{"send", &send}, { "send", &send },
{"recv", &recv}, { "recv", &recv },
{"setsockopt", &setsockopt}, { "setsockopt", &setsockopt },
{"socketpair", &socketpair}, { "socketpair", &socketpair },
{"acosh", &acosh}, { "acosh", &acosh },
{"asinh", &asinh}, { "asinh", &asinh },
{"atanh", &atanh}, { "atanh", &atanh },
{"acosh", &acosh}, { "acosh", &acosh },
{"frexp", &frexp}, { "frexp", &frexp },
{"hypot", &hypot}, { "hypot", &hypot },
{"ldexp", &ldexp}, { "ldexp", &ldexp },
{"cosh", &cosh}, { "cosh", &cosh },
{"sinh", &sinh}, { "sinh", &sinh },
{"tanh", &tanh}, { "tanh", &tanh },
{"acos", &acos}, { "acos", &acos },
{"asin", &asin}, { "asin", &asin },
{"atan", &atan}, { "atan", &atan },
{"atan2", &atan2}, { "atan2", &atan2 },
{"ceil", &ceil}, { "ceil", &ceil },
{"cos", &cos}, { "cos", &cos },
{"sin", &sin}, { "sin", &sin },
{"tan", &tan}, { "tan", &tan },
{"sqrt", &sqrt}, { "sqrt", &sqrt },
{"exp", &exp}, { "exp", &exp },
{"fabs", &fabs}, { "fabs", &fabs },
{"floor", &floor}, { "floor", &floor },
{"fmod", &fmod}, { "fmod", &fmod },
{"log", &log}, { "log", &log },
{"modf", &modf}, { "modf", &modf },
{"modfl", &modfl}, { "modfl", &modfl },
{"pow", &pow}, { "pow", &pow },
{"pow2", &pow2}, { "pow2", &pow2 },
{"pow10", &pow10}, { "pow10", &pow10 },
{"longjmp", &longjmp}, { "longjmp", &longjmp },
{"setjmp", &setjmp}, { "setjmp", &setjmp },
{"__is", &__is}, { "__is", &__is },
{"tolower", &tolower}, { "tolower", &tolower },
{"toupper", &toupper}, { "toupper", &toupper },
{"con_set_title", &con_set_title}, { "con_set_title", &con_set_title },
{"con_init", &con_init}, { "con_init", &con_init },
{"con_init_opt", &con_init_opt}, { "con_init_opt", &con_init_opt },
{"con_write_asciiz", &con_write_asciiz}, { "con_write_asciiz", &con_write_asciiz },
{"con_write_string", &con_write_string}, { "con_write_string", &con_write_string },
{"con_printf", &con_printf}, { "con_printf", &con_printf },
{"con_exit", &con_exit}, { "con_exit", &con_exit },
{"con_get_flags", &con_get_flags}, { "con_get_flags", &con_get_flags },
{"con_set_flags", &con_set_flags}, { "con_set_flags", &con_set_flags },
{"con_kbhit", &con_kbhit}, { "con_kbhit", &con_kbhit },
{"con_getch", &con_getch}, { "con_getch", &con_getch },
{"con_getch2", &con_getch2}, { "con_getch2", &con_getch2 },
{"con_gets", &con_gets}, { "con_gets", &con_gets },
{"con_gets2", &con_gets2}, { "con_gets2", &con_gets2 },
{"con_get_font_height", &con_get_font_height}, { "con_get_font_height", &con_get_font_height },
{"con_get_cursor_height", &con_get_cursor_height}, { "con_get_cursor_height", &con_get_cursor_height },
{"con_set_cursor_height", &con_set_cursor_height}, { "con_set_cursor_height", &con_set_cursor_height },
{"con_cls", &con_cls}, { "con_cls", &con_cls },
{"con_get_cursor_pos", &con_get_cursor_pos}, { "con_get_cursor_pos", &con_get_cursor_pos },
{"con_set_cursor_pos", &con_set_cursor_pos}, { "con_set_cursor_pos", &con_set_cursor_pos },
{"mktime", &mktime}, { "mktime", &mktime },
{"time", &time}, { "time", &time },
{"localtime", &localtime}, { "localtime", &localtime },
{"asctime", &asctime}, { "asctime", &asctime },
{"difftime", &difftime}, { "difftime", &difftime },
{"basename", &basename}, { "basename", &basename },
{"dirname", &dirname}, { "dirname", &dirname },
NULL, NULL,
}; };

View File

@ -31,7 +31,7 @@ Boston, MA 02111-1307, USA.
//#include <stdint.h> //#include <stdint.h>
#define TCC_TARGET_I386 #define TCC_TARGET_I386
#define W_TYPE_SIZE 32 #define W_TYPE_SIZE 32
#define BITS_PER_UNIT 8 #define BITS_PER_UNIT 8
typedef int Wtype; typedef int Wtype;
@ -44,40 +44,38 @@ struct DWstruct {
Wtype low, high; Wtype low, high;
}; };
typedef union typedef union {
{ struct DWstruct s;
struct DWstruct s; DWtype ll;
DWtype ll;
} DWunion; } DWunion;
typedef long double XFtype; typedef long double XFtype;
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) #define WORD_SIZE (sizeof(Wtype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) #define HIGH_WORD_COEFF (((UDWtype)1) << WORD_SIZE)
/* the following deal with IEEE single-precision numbers */ /* the following deal with IEEE single-precision numbers */
#define EXCESS 126 #define EXCESS 126
#define SIGNBIT 0x80000000 #define SIGNBIT 0x80000000
#define HIDDEN (1 << 23) #define HIDDEN (1 << 23)
#define SIGN(fp) ((fp) & SIGNBIT) #define SIGN(fp) ((fp)&SIGNBIT)
#define EXP(fp) (((fp) >> 23) & 0xFF) #define EXP(fp) (((fp) >> 23) & 0xFF)
#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) #define MANT(fp) (((fp)&0x7FFFFF) | HIDDEN)
#define PACK(s,e,m) ((s) | ((e) << 23) | (m)) #define PACK(s, e, m) ((s) | ((e) << 23) | (m))
/* the following deal with IEEE double-precision numbers */ /* the following deal with IEEE double-precision numbers */
#define EXCESSD 1022 #define EXCESSD 1022
#define HIDDEND (1 << 20) #define HIDDEND (1 << 20)
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) #define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
#define SIGND(fp) ((fp.l.upper) & SIGNBIT) #define SIGND(fp) ((fp.l.upper) & SIGNBIT)
#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | (fp.l.lower >> 22))
(fp.l.lower >> 22)) #define HIDDEND_LL ((long long)1 << 52)
#define HIDDEND_LL ((long long)1 << 52) #define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL - 1)) | HIDDEND_LL)
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL) #define PACKD_LL(s, e, m) (((long long)((s) + ((e) << 20)) << 32) | (m))
#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m))
/* the following deal with x86 long double-precision numbers */ /* the following deal with x86 long double-precision numbers */
#define EXCESSLD 16382 #define EXCESSLD 16382
#define EXPLD(fp) (fp.l.upper & 0x7fff) #define EXPLD(fp) (fp.l.upper & 0x7fff)
#define SIGNLD(fp) ((fp.l.upper) & 0x8000) #define SIGNLD(fp) ((fp.l.upper) & 0x8000)
/* only for x86 */ /* only for x86 */
union ldouble_long { union ldouble_long {
@ -115,252 +113,226 @@ union float_long {
/* XXX: use gcc/tcc intrinsic ? */ /* XXX: use gcc/tcc intrinsic ? */
#if defined(TCC_TARGET_I386) #if defined(TCC_TARGET_I386)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \ __asm__("subl %5,%1\n\tsbbl %3,%0" \
: "=r" ((USItype) (sh)), \ : "=r"((USItype)(sh)), \
"=&r" ((USItype) (sl)) \ "=&r"((USItype)(sl)) \
: "0" ((USItype) (ah)), \ : "0"((USItype)(ah)), \
"g" ((USItype) (bh)), \ "g"((USItype)(bh)), \
"1" ((USItype) (al)), \ "1"((USItype)(al)), \
"g" ((USItype) (bl))) "g"((USItype)(bl)))
#define umul_ppmm(w1, w0, u, v) \ #define umul_ppmm(w1, w0, u, v) \
__asm__ ("mull %3" \ __asm__("mull %3" \
: "=a" ((USItype) (w0)), \ : "=a"((USItype)(w0)), \
"=d" ((USItype) (w1)) \ "=d"((USItype)(w1)) \
: "%0" ((USItype) (u)), \ : "%0"((USItype)(u)), \
"rm" ((USItype) (v))) "rm"((USItype)(v)))
#define udiv_qrnnd(q, r, n1, n0, dv) \ #define udiv_qrnnd(q, r, n1, n0, dv) \
__asm__ ("divl %4" \ __asm__("divl %4" \
: "=a" ((USItype) (q)), \ : "=a"((USItype)(q)), \
"=d" ((USItype) (r)) \ "=d"((USItype)(r)) \
: "0" ((USItype) (n0)), \ : "0"((USItype)(n0)), \
"1" ((USItype) (n1)), \ "1"((USItype)(n1)), \
"rm" ((USItype) (dv))) "rm"((USItype)(dv)))
#define count_leading_zeros(count, x) \ #define count_leading_zeros(count, x) \
do { \ do { \
USItype __cbtmp; \ USItype __cbtmp; \
__asm__ ("bsrl %1,%0" \ __asm__("bsrl %1,%0" \
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \ : "=r"(__cbtmp) \
(count) = __cbtmp ^ 31; \ : "rm"((USItype)(x))); \
} while (0) (count) = __cbtmp ^ 31; \
} while (0)
#else #else
#error unsupported CPU type #error unsupported CPU type
#endif #endif
/* most of this code is taken from libgcc2.c from gcc */ /* most of this code is taken from libgcc2.c from gcc */
UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) UDWtype __udivmoddi4(UDWtype n, UDWtype d, UDWtype* rp)
{ {
DWunion ww; DWunion ww;
DWunion nn, dd; DWunion nn, dd;
DWunion rr; DWunion rr;
UWtype d0, d1, n0, n1, n2; UWtype d0, d1, n0, n1, n2;
UWtype q0, q1; UWtype q0, q1;
UWtype b, bm; UWtype b, bm;
nn.ll = n; nn.ll = n;
dd.ll = d; dd.ll = d;
d0 = dd.s.low; d0 = dd.s.low;
d1 = dd.s.high; d1 = dd.s.high;
n0 = nn.s.low; n0 = nn.s.low;
n1 = nn.s.high; n1 = nn.s.high;
#if !defined(UDIV_NEEDS_NORMALIZATION) #if !defined(UDIV_NEEDS_NORMALIZATION)
if (d1 == 0) if (d1 == 0) {
{ if (d0 > n1) {
if (d0 > n1) /* 0q = nn / 0D */
{
/* 0q = nn / 0D */
udiv_qrnnd (q0, n0, n1, n0, d0); udiv_qrnnd(q0, n0, n1, n0, d0);
q1 = 0; q1 = 0;
/* Remainder in n0. */ /* Remainder in n0. */
} } else {
else /* qq = NN / 0d */
{
/* qq = NN / 0d */
if (d0 == 0) if (d0 == 0)
d0 = 1 / d0; /* Divide intentionally by zero. */ d0 = 1 / d0; /* Divide intentionally by zero. */
udiv_qrnnd (q1, n1, 0, n1, d0); udiv_qrnnd(q1, n1, 0, n1, d0);
udiv_qrnnd (q0, n0, n1, n0, d0); udiv_qrnnd(q0, n0, n1, n0, d0);
/* Remainder in n0. */ /* Remainder in n0. */
} }
if (rp != 0) if (rp != 0) {
{ rr.s.low = n0;
rr.s.low = n0; rr.s.high = 0;
rr.s.high = 0; *rp = rr.ll;
*rp = rr.ll; }
}
} }
#else /* UDIV_NEEDS_NORMALIZATION */ #else /* UDIV_NEEDS_NORMALIZATION */
if (d1 == 0) if (d1 == 0) {
{ if (d0 > n1) {
if (d0 > n1) /* 0q = nn / 0D */
{
/* 0q = nn / 0D */
count_leading_zeros (bm, d0); count_leading_zeros(bm, d0);
if (bm != 0) if (bm != 0) {
{ /* Normalize, i.e. make the most significant bit of the
/* Normalize, i.e. make the most significant bit of the denominator set. */
denominator set. */
d0 = d0 << bm; d0 = d0 << bm;
n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
n0 = n0 << bm; n0 = n0 << bm;
} }
udiv_qrnnd (q0, n0, n1, n0, d0); udiv_qrnnd(q0, n0, n1, n0, d0);
q1 = 0; q1 = 0;
/* Remainder in n0 >> bm. */ /* Remainder in n0 >> bm. */
} } else {
else /* qq = NN / 0d */
{
/* qq = NN / 0d */
if (d0 == 0) if (d0 == 0)
d0 = 1 / d0; /* Divide intentionally by zero. */ d0 = 1 / d0; /* Divide intentionally by zero. */
count_leading_zeros (bm, d0); count_leading_zeros(bm, d0);
if (bm == 0) if (bm == 0) {
{ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
/* From (n1 >= d0) /\ (the most significant bit of d0 is set), conclude (the most significant bit of n1 is set) /\ (the
conclude (the most significant bit of n1 is set) /\ (the leading quotient digit q1 = 1).
leading quotient digit q1 = 1).
This special case is necessary, not an optimization. This special case is necessary, not an optimization.
(Shifts counts of W_TYPE_SIZE are undefined.) */ (Shifts counts of W_TYPE_SIZE are undefined.) */
n1 -= d0; n1 -= d0;
q1 = 1; q1 = 1;
} } else {
else /* Normalize. */
{
/* Normalize. */
b = W_TYPE_SIZE - bm; b = W_TYPE_SIZE - bm;
d0 = d0 << bm; d0 = d0 << bm;
n2 = n1 >> b; n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b); n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm; n0 = n0 << bm;
udiv_qrnnd (q1, n1, n2, n1, d0); udiv_qrnnd(q1, n1, n2, n1, d0);
} }
/* n1 != d0... */ /* n1 != d0... */
udiv_qrnnd (q0, n0, n1, n0, d0); udiv_qrnnd(q0, n0, n1, n0, d0);
/* Remainder in n0 >> bm. */ /* Remainder in n0 >> bm. */
} }
if (rp != 0) if (rp != 0) {
{ rr.s.low = n0 >> bm;
rr.s.low = n0 >> bm; rr.s.high = 0;
rr.s.high = 0; *rp = rr.ll;
*rp = rr.ll; }
}
} }
#endif /* UDIV_NEEDS_NORMALIZATION */ #endif /* UDIV_NEEDS_NORMALIZATION */
else else {
{ if (d1 > n1) {
if (d1 > n1) /* 00 = nn / DD */
{
/* 00 = nn / DD */
q0 = 0; q0 = 0;
q1 = 0; q1 = 0;
/* Remainder in n1n0. */ /* Remainder in n1n0. */
if (rp != 0) if (rp != 0) {
{ rr.s.low = n0;
rr.s.low = n0; rr.s.high = n1;
rr.s.high = n1; *rp = rr.ll;
*rp = rr.ll; }
} } else {
} /* 0q = NN / dd */
else
{
/* 0q = NN / dd */
count_leading_zeros (bm, d1); count_leading_zeros(bm, d1);
if (bm == 0) if (bm == 0) {
{ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
/* From (n1 >= d1) /\ (the most significant bit of d1 is set), conclude (the most significant bit of n1 is set) /\ (the
conclude (the most significant bit of n1 is set) /\ (the quotient digit q0 = 0 or 1).
quotient digit q0 = 0 or 1).
This special case is necessary, not an optimization. */ This special case is necessary, not an optimization. */
/* The condition on the next line takes advantage of that /* The condition on the next line takes advantage of that
n1 >= d1 (true due to program flow). */ n1 >= d1 (true due to program flow). */
if (n1 > d1 || n0 >= d0) if (n1 > d1 || n0 >= d0) {
{ q0 = 1;
q0 = 1; sub_ddmmss(n1, n0, n1, n0, d1, d0);
sub_ddmmss (n1, n0, n1, n0, d1, d0); } else
} q0 = 0;
else
q0 = 0;
q1 = 0; q1 = 0;
if (rp != 0) if (rp != 0) {
{ rr.s.low = n0;
rr.s.low = n0; rr.s.high = n1;
rr.s.high = n1; *rp = rr.ll;
*rp = rr.ll; }
} } else {
} UWtype m1, m0;
else /* Normalize. */
{
UWtype m1, m0;
/* Normalize. */
b = W_TYPE_SIZE - bm; b = W_TYPE_SIZE - bm;
d1 = (d1 << bm) | (d0 >> b); d1 = (d1 << bm) | (d0 >> b);
d0 = d0 << bm; d0 = d0 << bm;
n2 = n1 >> b; n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b); n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm; n0 = n0 << bm;
udiv_qrnnd (q0, n1, n2, n1, d1); udiv_qrnnd(q0, n1, n2, n1, d1);
umul_ppmm (m1, m0, q0, d0); umul_ppmm(m1, m0, q0, d0);
if (m1 > n1 || (m1 == n1 && m0 > n0)) if (m1 > n1 || (m1 == n1 && m0 > n0)) {
{ q0--;
q0--; sub_ddmmss(m1, m0, m1, m0, d1, d0);
sub_ddmmss (m1, m0, m1, m0, d1, d0); }
}
q1 = 0; q1 = 0;
/* Remainder in (n1n0 - m1m0) >> bm. */ /* Remainder in (n1n0 - m1m0) >> bm. */
if (rp != 0) if (rp != 0) {
{ sub_ddmmss(n1, n0, n1, n0, m1, m0);
sub_ddmmss (n1, n0, n1, n0, m1, m0); rr.s.low = (n1 << b) | (n0 >> bm);
rr.s.low = (n1 << b) | (n0 >> bm); rr.s.high = n1 >> bm;
rr.s.high = n1 >> bm; *rp = rr.ll;
*rp = rr.ll; }
} }
} }
}
} }
ww.s.low = q0; ww.s.low = q0;
ww.s.high = q1; ww.s.high = q1;
return ww.ll; return ww.ll;
} }
#define __negdi2(a) (-(a)) #define __negdi2(a) (-(a))
@ -376,15 +348,15 @@ long long __divdi3(long long u, long long v)
if (uu.s.high < 0) { if (uu.s.high < 0) {
c = ~c; c = ~c;
uu.ll = __negdi2 (uu.ll); uu.ll = __negdi2(uu.ll);
} }
if (vv.s.high < 0) { if (vv.s.high < 0) {
c = ~c; c = ~c;
vv.ll = __negdi2 (vv.ll); vv.ll = __negdi2(vv.ll);
} }
w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); w = __udivmoddi4(uu.ll, vv.ll, (UDWtype*)0);
if (c) if (c)
w = __negdi2 (w); w = __negdi2(w);
return w; return w;
} }
@ -409,27 +381,27 @@ long long __moddi3(long long u, long long v)
if (uu.s.high < 0) { if (uu.s.high < 0) {
c = ~c; c = ~c;
uu.ll = __negdi2 (uu.ll); uu.ll = __negdi2(uu.ll);
} }
if (vv.s.high < 0) if (vv.s.high < 0)
vv.ll = __negdi2 (vv.ll); vv.ll = __negdi2(vv.ll);
__udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w); __udivmoddi4(uu.ll, vv.ll, (UDWtype*)&w);
if (c) if (c)
w = __negdi2 (w); w = __negdi2(w);
return w; return w;
} }
unsigned long long __udivdi3(unsigned long long u, unsigned long long v) unsigned long long __udivdi3(unsigned long long u, unsigned long long v)
{ {
return __udivmoddi4 (u, v, (UDWtype *) 0); return __udivmoddi4(u, v, (UDWtype*)0);
} }
unsigned long long __umoddi3(unsigned long long u, unsigned long long v) unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
{ {
UDWtype w; UDWtype w;
__udivmoddi4 (u, v, &w); __udivmoddi4(u, v, &w);
return w; return w;
} }
@ -495,11 +467,17 @@ long long __tcc_cvt_ftol(long double x)
{ {
unsigned c0, c1; unsigned c0, c1;
long long ret; long long ret;
__asm__ __volatile__ ("fnstcw %0" : "=m" (c0)); __asm__ __volatile__("fnstcw %0"
: "=m"(c0));
c1 = c0 | 0x0C00; c1 = c0 | 0x0C00;
__asm__ __volatile__ ("fldcw %0" : : "m" (c1)); __asm__ __volatile__("fldcw %0"
__asm__ __volatile__ ("fistpll %0" : "=m" (ret)); :
__asm__ __volatile__ ("fldcw %0" : : "m" (c0)); : "m"(c1));
__asm__ __volatile__("fistpll %0"
: "=m"(ret));
__asm__ __volatile__("fldcw %0"
:
: "m"(c0));
return ret; return ret;
} }
#endif #endif
@ -552,7 +530,7 @@ long double __floatundixf(unsigned long long a)
} }
} }
unsigned long long __fixunssfdi (float a1) unsigned long long __fixunssfdi(float a1)
{ {
register union float_long fl1; register union float_long fl1;
register int exp; register int exp;
@ -561,13 +539,13 @@ unsigned long long __fixunssfdi (float a1)
fl1.f = a1; fl1.f = a1;
if (fl1.l == 0) if (fl1.l == 0)
return (0); return (0);
exp = EXP (fl1.l) - EXCESS - 24; exp = EXP(fl1.l) - EXCESS - 24;
l = MANT(fl1.l); l = MANT(fl1.l);
if (exp >= 41) if (exp >= 41)
return (unsigned long long)-1; return (unsigned long long)-1;
else if (exp >= 0) else if (exp >= 0)
return (unsigned long long)l << exp; return (unsigned long long)l << exp;
else if (exp >= -23) else if (exp >= -23)
@ -576,7 +554,7 @@ unsigned long long __fixunssfdi (float a1)
return 0; return 0;
} }
unsigned long long __fixunsdfdi (double a1) unsigned long long __fixunsdfdi(double a1)
{ {
register union double_long dl1; register union double_long dl1;
register int exp; register int exp;
@ -585,14 +563,14 @@ unsigned long long __fixunsdfdi (double a1)
dl1.d = a1; dl1.d = a1;
if (dl1.ll == 0) if (dl1.ll == 0)
return (0); return (0);
exp = EXPD (dl1) - EXCESSD - 53; exp = EXPD(dl1) - EXCESSD - 53;
l = MANTD_LL(dl1); l = MANTD_LL(dl1);
if (exp >= 12) if (exp >= 12)
return (unsigned long long)-1; return (unsigned long long)-1;
else if (exp >= 0) else if (exp >= 0)
return l << exp; return l << exp;
else if (exp >= -52) else if (exp >= -52)
@ -601,7 +579,7 @@ unsigned long long __fixunsdfdi (double a1)
return 0; return 0;
} }
unsigned long long __fixunsxfdi (long double a1) unsigned long long __fixunsxfdi(long double a1)
{ {
register union ldouble_long dl1; register union ldouble_long dl1;
register int exp; register int exp;
@ -610,37 +588,40 @@ unsigned long long __fixunsxfdi (long double a1)
dl1.ld = a1; dl1.ld = a1;
if (dl1.l.lower == 0 && dl1.l.upper == 0) if (dl1.l.lower == 0 && dl1.l.upper == 0)
return (0); return (0);
exp = EXPLD (dl1) - EXCESSLD - 64; exp = EXPLD(dl1) - EXCESSLD - 64;
l = dl1.l.lower; l = dl1.l.lower;
if (exp > 0) if (exp > 0)
return (unsigned long long)-1; return (unsigned long long)-1;
else if (exp >= -63) else if (exp >= -63)
return l >> -exp; return l >> -exp;
else else
return 0; return 0;
} }
long long __fixsfdi (float a1) long long __fixsfdi(float a1)
{ {
long long ret; int s; long long ret;
int s;
ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret; return s ? ret : -ret;
} }
long long __fixdfdi (double a1) long long __fixdfdi(double a1)
{ {
long long ret; int s; long long ret;
int s;
ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret; return s ? ret : -ret;
} }
long long __fixxfdi (long double a1) long long __fixxfdi(long double a1)
{ {
long long ret; int s; long long ret;
int s;
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret; return s ? ret : -ret;
} }
@ -648,33 +629,35 @@ long long __fixxfdi (long double a1)
#if defined(TCC_TARGET_X86_64) && !defined(_WIN64) #if defined(TCC_TARGET_X86_64) && !defined(_WIN64)
#ifndef __TINYC__ #ifndef __TINYC__
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#else #else
/* Avoid including stdlib.h because it is not easily available when /* Avoid including stdlib.h because it is not easily available when
cross compiling */ cross compiling */
#include <stddef.h> /* size_t definition is needed for a x86_64-tcc to parse memset() */ #include <stddef.h> /* size_t definition is needed for a x86_64-tcc to parse memset() */
void *malloc(unsigned long long); void* malloc(unsigned long long);
void *memset(void *s, int c, size_t n); void* memset(void* s, int c, size_t n);
void free(void*); void free(void*);
void abort(void); void abort(void);
#endif #endif
enum __va_arg_type { enum __va_arg_type {
__va_gen_reg, __va_float_reg, __va_stack __va_gen_reg,
__va_float_reg,
__va_stack
}; };
//This should be in sync with the declaration on our include/stdarg.h // This should be in sync with the declaration on our include/stdarg.h
/* GCC compatible definition of va_list. */ /* GCC compatible definition of va_list. */
typedef struct { typedef struct {
unsigned int gp_offset; unsigned int gp_offset;
unsigned int fp_offset; unsigned int fp_offset;
union { union {
unsigned int overflow_offset; unsigned int overflow_offset;
char *overflow_arg_area; char* overflow_arg_area;
}; };
char *reg_save_area; char* reg_save_area;
} __va_list_struct; } __va_list_struct;
#undef __va_start #undef __va_start
@ -682,17 +665,17 @@ typedef struct {
#undef __va_copy #undef __va_copy
#undef __va_end #undef __va_end
void __va_start(__va_list_struct *ap, void *fp) void __va_start(__va_list_struct* ap, void* fp)
{ {
memset(ap, 0, sizeof(__va_list_struct)); memset(ap, 0, sizeof(__va_list_struct));
*ap = *(__va_list_struct *)((char *)fp - 16); *ap = *(__va_list_struct*)((char*)fp - 16);
ap->overflow_arg_area = (char *)fp + ap->overflow_offset; ap->overflow_arg_area = (char*)fp + ap->overflow_offset;
ap->reg_save_area = (char *)fp - 176 - 16; ap->reg_save_area = (char*)fp - 176 - 16;
} }
void *__va_arg(__va_list_struct *ap, void* __va_arg(__va_list_struct* ap,
enum __va_arg_type arg_type, enum __va_arg_type arg_type,
int size, int align) int size, int align)
{ {
size = (size + 7) & ~7; size = (size + 7) & ~7;
align = (align + 7) & ~7; align = (align + 7) & ~7;
@ -731,30 +714,30 @@ void *__va_arg(__va_list_struct *ap,
/* Flushing for tccrun */ /* Flushing for tccrun */
#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386) #if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386)
void __clear_cache(void *beginning, void *end) void __clear_cache(void* beginning, void* end)
{ {
} }
#elif defined(TCC_TARGET_ARM) #elif defined(TCC_TARGET_ARM)
#define _GNU_SOURCE #define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h> #include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
void __clear_cache(void *beginning, void *end) void __clear_cache(void* beginning, void* end)
{ {
/* __ARM_NR_cacheflush is kernel private and should not be used in user space. /* __ARM_NR_cacheflush is kernel private and should not be used in user space.
* However, there is no ARM asm parser in tcc so we use it for now */ * However, there is no ARM asm parser in tcc so we use it for now */
#if 1 #if 1
syscall(__ARM_NR_cacheflush, beginning, end, 0); syscall(__ARM_NR_cacheflush, beginning, end, 0);
#else #else
__asm__ ("push {r7}\n\t" __asm__("push {r7}\n\t"
"mov r7, #0xf0002\n\t" "mov r7, #0xf0002\n\t"
"mov r2, #0\n\t" "mov r2, #0\n\t"
"swi 0\n\t" "swi 0\n\t"
"pop {r7}\n\t" "pop {r7}\n\t"
"ret"); "ret");
#endif #endif
} }

View File

@ -1,8 +1,7 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h> #include <math.h>
double double acosh(double x)
acosh(double x)
{ {
return log(x + sqrt(x*x - 1)); return log(x + sqrt(x * x - 1));
} }

View File

@ -1,9 +1,7 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h> #include <math.h>
double double asinh(double x)
asinh(double x)
{ {
return x>0 ? log(x + sqrt(x*x + 1)) : -log(sqrt(x*x+1)-x); return x > 0 ? log(x + sqrt(x * x + 1)) : -log(sqrt(x * x + 1) - x);
} }

View File

@ -30,7 +30,7 @@ doit:
fpatan fpatan
ret ret
isanan: isanan:
movl $1, _errno movl $1, __errno
fstp %st(0) fstp %st(0)
fstp %st(0) fstp %st(0)
fldl nan fldl nan

View File

@ -1,8 +1,7 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h> #include <math.h>
double double atanh(double x)
atanh(double x)
{ {
return log((1+x)/(1-x)) / 2.0; return log((1 + x) / (1 - x)) / 2.0;
} }

View File

@ -3,6 +3,6 @@
double cosh(double x) double cosh(double x)
{ {
const double ebig = exp(fabs(x)); const double ebig = exp(fabs(x));
return (ebig + 1.0/ebig) / 2.0; return (ebig + 1.0 / ebig) / 2.0;
} }

View File

@ -1,26 +1,25 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h> #include <math.h>
double double frexp(double x, int* exptr)
frexp(double x, int *exptr)
{ {
union { union {
double d; double d;
unsigned char c[8]; unsigned char c[8];
} u; } u;
u.d = x; u.d = x;
/* /*
* The format of the number is: * The format of the number is:
* Sign, 12 exponent bits, 51 mantissa bits * Sign, 12 exponent bits, 51 mantissa bits
* The exponent is 1023 biased and there is an implicit zero. * The exponent is 1023 biased and there is an implicit zero.
* We get the exponent from the upper bits and set the exponent * We get the exponent from the upper bits and set the exponent
* to 0x3fe (1022). * to 0x3fe (1022).
*/ */
*exptr = (int)(((u.c[7] & 0x7f) << 4) | (u.c[6] >> 4)) - 1022; *exptr = (int)(((u.c[7] & 0x7f) << 4) | (u.c[6] >> 4)) - 1022;
u.c[7] &= 0x80; u.c[7] &= 0x80;
u.c[7] |= 0x3f; u.c[7] |= 0x3f;
u.c[6] &= 0x0f; u.c[6] &= 0x0f;
u.c[6] |= 0xe0; u.c[6] |= 0xe0;
return u.d; return u.d;
} }

View File

@ -17,8 +17,8 @@
*/ */
/// #include <float.h> /// #include <float.h>
#include <math.h>
#include <errno.h> #include <errno.h>
#include <math.h>
/* Approximate square roots of DBL_MAX and DBL_MIN. Numbers /* Approximate square roots of DBL_MAX and DBL_MIN. Numbers
between these two shouldn't neither overflow nor underflow between these two shouldn't neither overflow nor underflow
@ -26,75 +26,71 @@
#define __SQRT_DBL_MAX 1.3e+154 #define __SQRT_DBL_MAX 1.3e+154
#define __SQRT_DBL_MIN 2.3e-162 #define __SQRT_DBL_MIN 2.3e-162
double double hypot(double x, double y)
hypot(double x, double y)
{ {
double abig = fabs(x), asmall = fabs(y); double abig = fabs(x), asmall = fabs(y);
double ratio; double ratio;
/* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */ /* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */
if (abig < asmall) if (abig < asmall) {
{ double temp = abig;
double temp = abig;
abig = asmall; abig = asmall;
asmall = temp; asmall = temp;
} }
/* Trivial case. */ /* Trivial case. */
if (asmall == 0.) if (asmall == 0.)
return abig; return abig;
/* Scale the numbers as much as possible by using its ratio. /* Scale the numbers as much as possible by using its ratio.
For example, if both ABIG and ASMALL are VERY small, then For example, if both ABIG and ASMALL are VERY small, then
X^2 + Y^2 might be VERY inaccurate due to loss of X^2 + Y^2 might be VERY inaccurate due to loss of
significant digits. Dividing ASMALL by ABIG scales them significant digits. Dividing ASMALL by ABIG scales them
to a certain degree, so that accuracy is better. */ to a certain degree, so that accuracy is better. */
if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX) if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX)
return abig * sqrt(1.0 + ratio*ratio); return abig * sqrt(1.0 + ratio * ratio);
else else {
{ /* Slower but safer algorithm due to Moler and Morrison. Never
/* Slower but safer algorithm due to Moler and Morrison. Never produces any intermediate result greater than roughly the
produces any intermediate result greater than roughly the larger of X and Y. Should converge to machine-precision
larger of X and Y. Should converge to machine-precision accuracy in 3 iterations. */
accuracy in 3 iterations. */
double r = ratio*ratio, t, s, p = abig, q = asmall; double r = ratio * ratio, t, s, p = abig, q = asmall;
do { do {
t = 4. + r; t = 4. + r;
if (t == 4.) if (t == 4.)
break; break;
s = r / t; s = r / t;
p += 2. * s * p; p += 2. * s * p;
q *= s; q *= s;
r = (q / p) * (q / p); r = (q / p) * (q / p);
} while (1); } while (1);
return p; return p;
} }
} }
#ifdef TEST #ifdef TEST
#include <stdio.h> #include <stdio.h>
int int main(void)
main(void)
{ {
printf("hypot(3, 4) =\t\t\t %25.17e\n", hypot(3., 4.)); printf("hypot(3, 4) =\t\t\t %25.17e\n", hypot(3., 4.));
printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", hypot(3.e+150, 4.e+150)); printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", hypot(3.e+150, 4.e+150));
printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", hypot(3.e+306, 4.e+306)); printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", hypot(3.e+306, 4.e+306));
printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n", printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n",
hypot(3.e-320, 4.e-320)); hypot(3.e-320, 4.e-320));
printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n", printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n",
hypot(0.7*DBL_MAX, 0.7*DBL_MAX)); hypot(0.7 * DBL_MAX, 0.7 * DBL_MAX));
printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", hypot(DBL_MAX, 1.0)); printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", hypot(DBL_MAX, 1.0));
printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", hypot(1.0, DBL_MAX)); printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", hypot(1.0, DBL_MAX));
printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", hypot(0.0, DBL_MAX)); printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", hypot(0.0, DBL_MAX));
return 0; return 0;
} }
#endif #endif

View File

@ -2,31 +2,27 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <math.h> #include <math.h>
double double ldexp(double v, int e)
ldexp(double v, int e)
{ {
double two = 2.0; double two = 2.0;
if (e < 0) if (e < 0) {
{ e = -e; /* This just might overflow on two-complement machines. */
e = -e; /* This just might overflow on two-complement machines. */ if (e < 0)
if (e < 0) return 0.0; return 0.0;
while (e > 0) while (e > 0) {
{ if (e & 1)
if (e & 1) v /= two; v /= two;
two *= two; two *= two;
e >>= 1; e >>= 1;
}
} else if (e > 0) {
while (e > 0) {
if (e & 1)
v *= two;
two *= two;
e >>= 1;
}
} }
} return v;
else if (e > 0)
{
while (e > 0)
{
if (e & 1) v *= two;
two *= two;
e >>= 1;
}
}
return v;
} }

View File

@ -3,14 +3,11 @@
double sinh(double x) double sinh(double x)
{ {
if(x >= 0.0) if (x >= 0.0) {
{ const double epos = exp(x);
const double epos = exp(x); return (epos - 1.0 / epos) / 2.0;
return (epos - 1.0/epos) / 2.0; } else {
} const double eneg = exp(-x);
else return (1.0 / eneg - eneg) / 2.0;
{ }
const double eneg = exp(-x);
return (1.0/eneg - eneg) / 2.0;
}
} }

View File

@ -3,15 +3,13 @@
double tanh(double x) double tanh(double x)
{ {
if (x > 50) if (x > 50)
return 1; return 1;
else if (x < -50) else if (x < -50)
return -1; return -1;
else else {
{ const double ebig = exp(x);
const double ebig = exp(x); const double esmall = 1.0 / ebig;
const double esmall = 1.0/ebig; return (ebig - esmall) / (ebig + esmall);
return (ebig - esmall) / (ebig + esmall); }
}
} }

View File

@ -1,13 +1,15 @@
#include <string.h>
#include <libgen.h> #include <libgen.h>
#include <string.h>
char *basename(char *s) char* basename(char* s)
{ {
size_t i; size_t i;
if (!s || !*s) return "."; if (!s || !*s)
i = strlen(s)-1; return ".";
for (; i&&s[i]=='/'; i--) s[i] = 0; i = strlen(s) - 1;
for (; i&&s[i-1]!='/'; i--); for (; i && s[i] == '/'; i--)
return s+i; s[i] = 0;
for (; i && s[i - 1] != '/'; i--)
;
return s + i;
} }

View File

@ -1,14 +1,21 @@
#include <string.h>
#include <libgen.h> #include <libgen.h>
#include <string.h>
char *dirname(char *s) char* dirname(char* s)
{ {
size_t i; size_t i;
if (!s || !*s) return "."; if (!s || !*s)
i = strlen(s)-1; return ".";
for (; s[i]=='/'; i--) if (!i) return "/"; i = strlen(s) - 1;
for (; s[i]!='/'; i--) if (!i) return "."; for (; s[i] == '/'; i--)
for (; s[i]=='/'; i--) if (!i) return "/"; if (!i)
s[i+1] = 0; return "/";
for (; s[i] != '/'; i--)
if (!i)
return ".";
for (; s[i] == '/'; i--)
if (!i)
return "/";
s[i + 1] = 0;
return s; return s;
} }

View File

@ -1 +1 @@
void ___chkstk_ms() {} void ___chkstk_ms() { }

View File

@ -2,5 +2,5 @@
int abs(int a) int abs(int a)
{ {
return a>0 ? a : -a; return a > 0 ? a : -a;
} }

View File

@ -1,14 +1,13 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize("O0") #pragma GCC optimize("O0")
void __assert_fail(const char *expr, const char *file, int line, const char *func) void __assert_fail(const char* expr, const char* file, int line, const char* func)
{ {
fprintf(stdout, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line); fprintf(stdout, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
exit(0); exit(0);
} }
#pragma GCC pop_options #pragma GCC pop_options

View File

@ -1,7 +1,7 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <stdlib.h> #include <stdlib.h>
double atof(const char *ascii) double atof(const char* ascii)
{ {
return strtod(ascii, 0); return strtod(ascii, 0);
} }

View File

@ -1,21 +1,25 @@
#include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
/* /*
** atoi(s) - convert s to integer. ** atoi(s) - convert s to integer.
*/ */
int atoi(const char *s) int atoi(const char* s)
{ {
int sign, n; int sign, n;
while(isspace(*s)) ++s; while (isspace(*s))
++s;
sign = 1; sign = 1;
switch(*s) { switch (*s) {
case '-': sign = -1; case '-':
case '+': ++s; sign = -1;
case '+':
++s;
} }
n = 0; n = 0;
while(isdigit(*s)) n = 10 * n + *s++ - '0'; while (isdigit(*s))
n = 10 * n + *s++ - '0';
return (sign * n); return (sign * n);
} }

View File

@ -1,17 +1,20 @@
#include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
long atol(const char *s) long atol(const char* s)
{ {
long n=0; long n = 0;
int neg=0; int neg = 0;
while (isspace(*s)) s++; while (isspace(*s))
switch (*s) { s++;
case '-': neg=1; switch (*s) {
case '+': s++; case '-':
} neg = 1;
/* Compute n as a negative number to avoid overflow on LONG_MIN */ case '+':
while (isdigit(*s)) s++;
n = 10*n - (*s++ - '0'); }
return neg ? n : -n; /* Compute n as a negative number to avoid overflow on LONG_MIN */
while (isdigit(*s))
n = 10 * n - (*s++ - '0');
return neg ? n : -n;
} }

View File

@ -1,17 +1,20 @@
#include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
long long atoll(const char *s) long long atoll(const char* s)
{ {
long long n=0; long long n = 0;
int neg=0; int neg = 0;
while (isspace(*s)) s++; while (isspace(*s))
switch (*s) { s++;
case '-': neg=1; switch (*s) {
case '+': s++; case '-':
} neg = 1;
/* Compute n as a negative number to avoid overflow on LLONG_MIN */ case '+':
while (isdigit(*s)) s++;
n = 10*n - (*s++ - '0'); }
return neg ? n : -n; /* Compute n as a negative number to avoid overflow on LLONG_MIN */
while (isdigit(*s))
n = 10 * n - (*s++ - '0');
return neg ? n : -n;
} }

View File

@ -1,13 +1,14 @@
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <sys/ksys.h> #include <sys/ksys.h>
void *calloc(size_t num, size_t size) { void* calloc(size_t num, size_t size)
void *ptr = _ksys_alloc(num*size); {
if(!ptr){ void* ptr = _ksys_alloc(num * size);
errno = ENOMEM; if (!ptr) {
__errno = ENOMEM;
return NULL; return NULL;
} }
memset(ptr, 0, num*size); memset(ptr, 0, num * size);
return ptr; return ptr;
} }

View File

@ -5,7 +5,7 @@
void exit(int status) void exit(int status)
{ {
if(__con_is_load){ if (__con_is_load) {
con_exit(status); con_exit(status);
} }
_ksys_exit(); _ksys_exit();

View File

@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/ksys.h> #include <sys/ksys.h>
void free(void *ptr) { void free(void* ptr)
{
_ksys_free(ptr); _ksys_free(ptr);
} }

View File

@ -1,23 +1,23 @@
#include <string.h> #include <string.h>
#include <sys/ksys.h> #include <sys/ksys.h>
char *__reverse(char *str) char* __reverse(char* str)
{ {
char tmp, *src, *dst; char tmp, *src, *dst;
size_t len; size_t len;
if (str != NULL){ if (str != NULL) {
len = strlen (str); len = strlen(str);
if (len > 1) { if (len > 1) {
src = str; src = str;
dst = src + len - 1; dst = src + len - 1;
while (src < dst) { while (src < dst) {
tmp = *src; tmp = *src;
*src++ = *dst; *src++ = *dst;
*dst-- = tmp; *dst-- = tmp;
} }
} }
} }
return str; return str;
} }
/* itoa from K&R */ /* itoa from K&R */
@ -25,13 +25,13 @@ void itoa(int n, char s[])
{ {
int i, sign; int i, sign;
if ((sign = n) < 0) /* record sign */ if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */ n = -n; /* make n positive */
i = 0; i = 0;
do { /* generate digits in reverse order */ do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */ s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */ } while ((n /= 10) > 0); /* delete it */
if (sign < 0) if (sign < 0)
s[i++] = '-'; s[i++] = '-';

View File

@ -2,5 +2,5 @@
long labs(long a) long labs(long a)
{ {
return a>0 ? a : -a; return a > 0 ? a : -a;
} }

View File

@ -2,5 +2,5 @@
long long llabs(long long a) long long llabs(long long a)
{ {
return a>0 ? a : -a; return a > 0 ? a : -a;
} }

View File

@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/ksys.h> #include <sys/ksys.h>
void *malloc(size_t size) { void* malloc(size_t size)
{
return _ksys_alloc(size); return _ksys_alloc(size);
} }

View File

@ -29,13 +29,13 @@
* The MTHREShold is where we stop finding a better median. * The MTHREShold is where we stop finding a better median.
*/ */
#define THRESH 4 /* threshold for insertion */ #define THRESH 4 /* threshold for insertion */
#define MTHRESH 6 /* threshold for median */ #define MTHRESH 6 /* threshold for median */
static int (*qcmp)(const void *, const void *); /* the comparison routine */ static int (*qcmp)(const void*, const void*); /* the comparison routine */
static int qsz; /* size of each record */ static int qsz; /* size of each record */
static int thresh; /* THRESHold in chars */ static int thresh; /* THRESHold in chars */
static int mthresh; /* MTHRESHold in chars */ static int mthresh; /* MTHRESHold in chars */
/* /*
* qst: * qst:
@ -52,117 +52,101 @@ static int mthresh; /* MTHRESHold in chars */
* (And there are only three places where this is done). * (And there are only three places where this is done).
*/ */
static void static void qst(char* base, char* max)
qst(char *base, char *max)
{ {
char c, *i, *j, *jj; char c, *i, *j, *jj;
int ii; int ii;
char *mid, *tmp; char *mid, *tmp;
int lo, hi; int lo, hi;
/*
* At the top here, lo is the number of characters of elements in the
* current partition. (Which should be max - base).
* Find the median of the first, last, and middle element and make
* that the middle element. Set j to largest of first and middle.
* If max is larger than that guy, then it's that guy, else compare
* max with loser of first and take larger. Things are set up to
* prefer the middle, then the first in case of ties.
*/
lo = max - base; /* number of elements as chars */
do {
mid = i = base + qsz * ((lo / qsz) >> 1);
if (lo >= mthresh)
{
j = (qcmp((jj = base), i) > 0 ? jj : i);
if (qcmp(j, (tmp = max - qsz)) > 0)
{
/* switch to first loser */
j = (j == jj ? i : jj);
if (qcmp(j, tmp) < 0)
j = tmp;
}
if (j != i)
{
ii = qsz;
do {
c = *i;
*i++ = *j;
*j++ = c;
} while (--ii);
}
}
/* /*
* Semi-standard quicksort partitioning/swapping * At the top here, lo is the number of characters of elements in the
* current partition. (Which should be max - base).
* Find the median of the first, last, and middle element and make
* that the middle element. Set j to largest of first and middle.
* If max is larger than that guy, then it's that guy, else compare
* max with loser of first and take larger. Things are set up to
* prefer the middle, then the first in case of ties.
*/ */
for (i = base, j = max - qsz; ; ) lo = max - base; /* number of elements as chars */
{ do {
while (i < mid && qcmp(i, mid) <= 0) mid = i = base + qsz * ((lo / qsz) >> 1);
i += qsz; if (lo >= mthresh) {
while (j > mid) j = (qcmp((jj = base), i) > 0 ? jj : i);
{ if (qcmp(j, (tmp = max - qsz)) > 0) {
if (qcmp(mid, j) <= 0) /* switch to first loser */
{ j = (j == jj ? i : jj);
j -= qsz; if (qcmp(j, tmp) < 0)
continue; j = tmp;
} }
tmp = i + qsz; /* value of i after swap */ if (j != i) {
if (i == mid) ii = qsz;
{ do {
/* j <-> mid, new mid is j */ c = *i;
mid = jj = j; *i++ = *j;
} *j++ = c;
else } while (--ii);
{ }
/* i <-> j */ }
jj = j; /*
j -= qsz; * Semi-standard quicksort partitioning/swapping
} */
goto swap; for (i = base, j = max - qsz;;) {
} while (i < mid && qcmp(i, mid) <= 0)
if (i == mid) i += qsz;
{ while (j > mid) {
break; if (qcmp(mid, j) <= 0) {
} j -= qsz;
else continue;
{ }
/* i <-> mid, new mid is i */ tmp = i + qsz; /* value of i after swap */
jj = mid; if (i == mid) {
tmp = mid = i; /* value of i after swap */ /* j <-> mid, new mid is j */
j -= qsz; mid = jj = j;
} } else {
swap: /* i <-> j */
ii = qsz; jj = j;
do { j -= qsz;
c = *i; }
*i++ = *jj; goto swap;
*jj++ = c; }
} while (--ii); if (i == mid) {
i = tmp; break;
} } else {
/* /* i <-> mid, new mid is i */
* Look at sizes of the two partitions, do the smaller jj = mid;
* one first by recursion, then do the larger one by tmp = mid = i; /* value of i after swap */
* making sure lo is its size, base and max are update j -= qsz;
* correctly, and branching back. But only repeat }
* (recursively or by branching) if the partition is swap:
* of at least size THRESH. ii = qsz;
*/ do {
i = (j = mid) + qsz; c = *i;
if ((lo = j - base) <= (hi = max - i)) *i++ = *jj;
{ *jj++ = c;
if (lo >= thresh) } while (--ii);
qst(base, j); i = tmp;
base = i; }
lo = hi; /*
} * Look at sizes of the two partitions, do the smaller
else * one first by recursion, then do the larger one by
{ * making sure lo is its size, base and max are update
if (hi >= thresh) * correctly, and branching back. But only repeat
qst(i, max); * (recursively or by branching) if the partition is
max = j; * of at least size THRESH.
} */
} while (lo >= thresh); i = (j = mid) + qsz;
if ((lo = j - base) <= (hi = max - i)) {
if (lo >= thresh)
qst(base, j);
base = i;
lo = hi;
} else {
if (hi >= thresh)
qst(i, max);
max = j;
}
} while (lo >= thresh);
} }
/* /*
@ -172,67 +156,59 @@ qst(char *base, char *max)
* It's not... * It's not...
*/ */
void void qsort(void* base0, size_t n, size_t size, int (*compar)(const void*, const void*))
qsort(void *base0, size_t n, size_t size, int (*compar)(const void *, const void *))
{ {
char *base = (char *)base0; char* base = (char*)base0;
char c, *i, *j, *lo, *hi; char c, *i, *j, *lo, *hi;
char *min, *max; char *min, *max;
if (n <= 1) if (n <= 1)
return; return;
qsz = size; qsz = size;
qcmp = compar; qcmp = compar;
thresh = qsz * THRESH; thresh = qsz * THRESH;
mthresh = qsz * MTHRESH; mthresh = qsz * MTHRESH;
max = base + n * qsz; max = base + n * qsz;
if (n >= THRESH) if (n >= THRESH) {
{ qst(base, max);
qst(base, max); hi = base + thresh;
hi = base + thresh; } else {
} hi = max;
else
{
hi = max;
}
/*
* First put smallest element, which must be in the first THRESH, in
* the first position as a sentinel. This is done just by searching
* the first THRESH elements (or the first n if n < THRESH), finding
* the min, and swapping it into the first position.
*/
for (j = lo = base; (lo += qsz) < hi; )
if (qcmp(j, lo) > 0)
j = lo;
if (j != base)
{
/* swap j into place */
for (i = base, hi = base + qsz; i < hi; )
{
c = *j;
*j++ = *i;
*i++ = c;
} }
} /*
/* * First put smallest element, which must be in the first THRESH, in
* With our sentinel in place, we now run the following hyper-fast * the first position as a sentinel. This is done just by searching
* insertion sort. For each remaining element, min, from [1] to [n-1], * the first THRESH elements (or the first n if n < THRESH), finding
* set hi to the index of the element AFTER which this one goes. * the min, and swapping it into the first position.
* Then, do the standard insertion sort shift on a character at a time */
* basis for each element in the frob. for (j = lo = base; (lo += qsz) < hi;)
*/ if (qcmp(j, lo) > 0)
for (min = base; (hi = min += qsz) < max; ) j = lo;
{ if (j != base) {
while (qcmp(hi -= qsz, min) > 0) /* swap j into place */
/* void */; for (i = base, hi = base + qsz; i < hi;) {
if ((hi += qsz) != min) { c = *j;
for (lo = min + qsz; --lo >= min; ) *j++ = *i;
{ *i++ = c;
c = *lo; }
for (i = j = lo; (j -= qsz) >= hi; i = j) }
*i = *j; /*
*i = c; * With our sentinel in place, we now run the following hyper-fast
} * insertion sort. For each remaining element, min, from [1] to [n-1],
* set hi to the index of the element AFTER which this one goes.
* Then, do the standard insertion sort shift on a character at a time
* basis for each element in the frob.
*/
for (min = base; (hi = min += qsz) < max;) {
while (qcmp(hi -= qsz, min) > 0)
/* void */;
if ((hi += qsz) != min) {
for (lo = min + qsz; --lo >= min;) {
c = *lo;
for (i = j = lo; (j -= qsz) >= hi; i = j)
*i = *j;
*i = c;
}
}
} }
}
} }

View File

@ -1,15 +1,15 @@
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
static uint64_t seed; static uint64_t seed;
void srand(unsigned s) void srand(unsigned s)
{ {
seed = s-1; seed = s - 1;
} }
int rand(void) int rand(void)
{ {
seed = 6364136223846793005ULL*seed + 1; seed = 6364136223846793005ULL * seed + 1;
return seed>>33; return seed >> 33;
} }

View File

@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/ksys.h> #include <sys/ksys.h>
void *realloc(void *ptr, size_t newsize) { void* realloc(void* ptr, size_t newsize)
{
return _ksys_realloc(ptr, newsize); return _ksys_realloc(ptr, newsize);
} }

View File

@ -1,17 +1,19 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h> #include <math.h>
#define unconst(__v, __t) __extension__ ({union { const __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;}) #ifndef unconst
#define unconst(__v, __t) __extension__({union { const __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p; })
#endif
double strtod(const char *s, char **sret) double strtod(const char* s, char** sret)
{ {
long double r; /* result */ long double r; /* result */
int e; /* exponent */ int e; /* exponent */
long double d; /* scale */ long double d; /* scale */
int sign; /* +- 1.0 */ int sign; /* +- 1.0 */
int esign; int esign;
int i; int i;
int flags=0; int flags = 0;
r = 0.0; r = 0.0;
sign = 1.0; sign = 1.0;
@ -23,27 +25,23 @@ double strtod(const char *s, char **sret)
if (*s == '+') if (*s == '+')
s++; s++;
else if (*s == '-') else if (*s == '-') {
{
sign = -1; sign = -1;
s++; s++;
} }
while ((*s >= '0') && (*s <= '9')) while ((*s >= '0') && (*s <= '9')) {
{
flags |= 1; flags |= 1;
r *= 10.0; r *= 10.0;
r += *s - '0'; r += *s - '0';
s++; s++;
} }
if (*s == '.') if (*s == '.') {
{
d = 0.1L; d = 0.1L;
s++; s++;
while ((*s >= '0') && (*s <= '9')) while ((*s >= '0') && (*s <= '9')) {
{
flags |= 2; flags |= 2;
r += d * (*s - '0'); r += d * (*s - '0');
s++; s++;
@ -51,33 +49,28 @@ double strtod(const char *s, char **sret)
} }
} }
if (flags == 0) if (flags == 0) {
{
if (sret) if (sret)
*sret = unconst(s, char *); *sret = unconst(s, char*);
return 0; return 0;
} }
if ((*s == 'e') || (*s == 'E')) if ((*s == 'e') || (*s == 'E')) {
{
s++; s++;
if (*s == '+') if (*s == '+')
s++; s++;
else if (*s == '-') else if (*s == '-') {
{
s++; s++;
esign = -1; esign = -1;
} }
if ((*s < '0') || (*s > '9')) if ((*s < '0') || (*s > '9')) {
{
if (sret) if (sret)
*sret = unconst(s, char *); *sret = unconst(s, char*);
return r; return r;
} }
while ((*s >= '0') && (*s <= '9')) while ((*s >= '0') && (*s <= '9')) {
{
e *= 10; e *= 10;
e += *s - '0'; e += *s - '0';
s++; s++;
@ -91,6 +84,6 @@ double strtod(const char *s, char **sret)
r *= 10.0; r *= 10.0;
if (sret) if (sret)
*sret = unconst(s, char *); *sret = unconst(s, char*);
return r * sign; return r * sign;
} }

View File

@ -1,73 +1,72 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int getdigit(char ch, int base) int getdigit(char ch, int base)
{ {
if (isdigit(ch)) ch-= '0'; if (isdigit(ch))
else ch -= '0';
if (isalpha(ch) && ch <= 'Z') ch = 10 + ch - 'A'; else if (isalpha(ch) && ch <= 'Z')
else ch = 10 + ch - 'A';
if (isalpha(ch)) ch = 10 + ch - 'a'; else if (isalpha(ch))
else ch = 10 + ch - 'a';
return -1; else
return -1;
if (ch / base != 0) return -1; if (ch / base != 0)
return -1;
return ch; return ch;
} }
long int strtol(const char* str, char** endptr, int base)
long int strtol (const char* str, char** endptr, int base)
{ {
long int res = 0; long int res = 0;
int sign = 1; int sign = 1;
if (base > 36) if (base > 36) {
{ errno = EINVAL;
errno = EINVAL; goto bye;
goto bye; }
}
while (isspace(*str)) str++; while (isspace(*str))
str++;
if (*str == '-') { sign = -1; str++; } if (*str == '-') {
else sign = -1;
if (*str == '+') str++; str++;
} else if (*str == '+')
str++;
if (base == 0 || base == 16) if (base == 0 || base == 16) {
{ if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) {
if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) base = 16;
{ str += 2;
base = 16; }
str += 2; }
}
}
if (base == 0 && *str == '0') base = 8; if (base == 0 && *str == '0')
base = 8;
if (base == 0) base = 10; if (base == 0)
base = 10;
int digit;
int digit; while ((digit = getdigit(*str, base)) >= 0) {
while ((digit = getdigit(*str, base)) >= 0) res = base * res + digit;
{ str++;
res = base * res + digit; if (res < 0) {
str++; errno = ERANGE;
if (res < 0) if (sign > 0)
{ res = LONG_MAX;
errno = ERANGE; else
if (sign > 0) res = LONG_MIN;
res = LONG_MAX; }
else }
res = LONG_MIN;
}
}
bye: bye:
if (endptr) if (endptr)
*endptr = (char*)str; *endptr = (char*)str;
return res * sign; return res * sign;
} }

View File

@ -1,24 +1,20 @@
/* memchr( const void *, int, size_t ) #include <assert.h>
#include "unconst.h"
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
void * memchr( const void * s, int c, size_t n ) void* memchr(const void* s, int c, size_t n)
{ {
const unsigned char * p = ( const unsigned char * ) s; int d0;
register void* __res;
while ( n-- ) if (!n)
{ return NULL;
if ( *p == ( unsigned char ) c ) __asm__ __volatile__(
{ "repne\n\t"
return ( void * ) p; "scasb\n\t"
} "je 1f\n\t"
"movl $1,%0\n"
++p; "1:\tdecl %0"
} : "=D"(__res), "=&c"(d0)
: "a"(c), "0"(s), "1"(n));
return NULL; return __res;
} }

View File

@ -1,26 +1,15 @@
/* memcmp( const void *, const void *, size_t ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <assert.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
int memcmp( const void * s1, const void * s2, size_t n ) int memcmp(const void* s1, const void* s2, size_t n)
{ {
const unsigned char * p1 = ( const unsigned char * ) s1; if (n != 0) {
const unsigned char * p2 = ( const unsigned char * ) s2; const unsigned char *p1 = s1, *p2 = s2;
do {
while ( n-- ) if (*p1++ != *p2++)
{ return (*--p1 - *--p2);
if ( *p1 != *p2 ) } while (--n != 0);
{
return *p1 - *p2;
}
++p1;
++p2;
} }
return 0; return 0;
} }

View File

@ -1,20 +1,19 @@
/* memcpy( void *, const void *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
void * memcpy( void * s1, const void * s2, size_t n ) void* memcpy(void* _dest, const void* _src, size_t _n)
{ {
char * dest = ( char * ) s1; int d0, d1, d2;
const char * src = ( const char * ) s2; __asm__ __volatile__(
"rep ; movsl\n\t"
while ( n-- ) "testb $2,%b4\n\t"
{ "je 1f\n\t"
*dest++ = *src++; "movsw\n"
} "1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
return s1; "movsb\n"
"2:"
: "=&c"(d0), "=&D"(d1), "=&S"(d2)
: "0"(_n / 4), "q"(_n), "1"((long)_dest), "2"((long)_src)
: "memory");
return (_dest);
} }

View File

@ -1,33 +0,0 @@
/* memmove( void *, const void *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
void * memmove( void * s1, const void * s2, size_t n )
{
char * dest = ( char * ) s1;
const char * src = ( const char * ) s2;
if ( dest <= src )
{
while ( n-- )
{
*dest++ = *src++;
}
}
else
{
src += n;
dest += n;
while ( n-- )
{
*--dest = *--src;
}
}
return s1;
}

View File

@ -0,0 +1,34 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
.global memmove
memmove:
pushl %ebp
movl %esp,%ebp
pushl %esi
pushl %edi
movl 8(%ebp),%edi
movl 12(%ebp),%esi
movl 16(%ebp),%ecx
jecxz memmove.L2
cld
cmpl %esi,%edi
jb memmove.L3
std
addl %ecx,%esi
addl %ecx,%edi
decl %esi
decl %edi
memmove.L3:
rep
movsb
memmove.L2:
cld
popl %edi
popl %esi
movl 8(%ebp),%eax
leave
ret

View File

@ -1,20 +0,0 @@
/* memset( void *, int, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
#include <stdint.h>
void * memset( void * s, int c, size_t n )
{
unsigned char * p = ( unsigned char * ) s;
while ( n-- )
{
*p++ = ( unsigned char ) c;
}
return s;
}

View File

@ -0,0 +1,51 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
.text
.align 4
.global memset
memset:
pushl %ebp
movl %esp,%ebp
pushl %edi
movl 8(%ebp),%edi
movl 12(%ebp),%eax
movl 16(%ebp),%ecx
cld
# We will handle memsets of <= 15 bytes one byte at a time.
# This avoids some extra overhead for small memsets, and
# knowing we are setting > 15 bytes eliminates some annoying
# checks in the "long move" case.
cmpl $15,%ecx
jle memset.L3
# Otherwise, tile the byte value out into %eax.
# 0x41 -> 0x41414141, etc.
movb %al,%ah
movl %eax,%edx
sall $16,%eax
movw %dx,%ax
jmp memset.L2
# Handle any cruft necessary to get %edi long-aligned.
memset.L1: stosb
decl %ecx
memset.L2: testl $3,%edi
jnz memset.L1
# Now slam out all of the longs.
movl %ecx,%edx
shrl $2,%ecx
rep
stosl
# Finally, handle any trailing cruft. We know the high three bytes
# of %ecx must be zero, so just put the "slop count" in the low byte.
movb %dl,%cl
andb $3,%cl
memset.L3: rep
stosb
popl %edi
movl 8(%ebp),%eax
leave
ret

View File

@ -1,27 +1,18 @@
/* strcat( char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strcat( char * s1, const char * s2 ) char* strcat(char* s, const char* append)
{ {
char * rc = s1; int d0, d1, d2, d3;
__asm__ __volatile__(
if ( *s1 ) "repne\n\t"
{ "scasb\n\t"
while ( *++s1 ) "decl %1\n"
{ "1:\tlodsb\n\t"
/* EMPTY */ "stosb\n\t"
} "testb %%al,%%al\n\t"
} "jne 1b"
: "=&S"(d0), "=&D"(d1), "=&a"(d2), "=&c"(d3)
while ( ( *s1++ = *s2++ ) ) : "0"(append), "1"(s), "2"(0), "3"(0xffffffff)
{ : "memory");
/* EMPTY */ return s;
}
return rc;
} }

View File

@ -1,20 +1,21 @@
/* strchr( const char *, int ) #include "unconst.h"
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strchr( const char * s, int c ) char* strchr(const char* s, int c)
{ {
do int d0;
{ register char* __res;
if ( *s == ( char ) c ) __asm__ __volatile__(
{ "movb %%al,%%ah\n"
return ( char * ) s; "1:\tlodsb\n\t"
} "cmpb %%ah,%%al\n\t"
} while ( *s++ ); "je 2f\n\t"
"testb %%al,%%al\n\t"
return NULL; "jne 1b\n\t"
"movl $1,%1\n"
"2:\tmovl %1,%0\n\t"
"decl %0"
: "=a"(__res), "=&S"(d0)
: "1"((unsigned)s), "0"(c));
return __res;
} }

View File

@ -1,14 +1,21 @@
/* strcmp( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <errno.h>
#include <string.h> #include <string.h>
#include <sys/ksys.h>
int strcmp(const char * s1, const char * s2) int strcmp(const char* s1, const char* s2)
{ {
return __strcmp(s1, s2); int d0, d1;
register int __res;
__asm__ __volatile__(
"1:\tlodsb\n\t"
"scasb\n\t"
"jne 2f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"jmp 3f\n"
"2:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"3:"
: "=a"(__res), "=&S"(d0), "=&D"(d1)
: "1"(s1), "2"(s2));
return __res;
} }

View File

@ -1,13 +1,7 @@
/* strcoll( const char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
int strcoll( const char * s1, const char * s2 ) int strcoll(const char* s1, const char* s2)
{ {
/* FIXME: This should access _PDCLIB_lc_collate. */ return strcmp(s1, s2);
return strcmp( s1, s2 );
} }

View File

@ -1,19 +1,16 @@
/* strcpy( char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strcpy( char * s1, const char * s2 ) char* strcpy(char* to, const char* from)
{ {
char * rc = s1; int d0, d1, d2;
__asm__ __volatile__(
while ( ( *s1++ = *s2++ ) ) "1:\tlodsb\n\t"
{ "stosb\n\t"
/* EMPTY */ "testb %%al,%%al\n\t"
} "jne 1b"
: "=&S"(d0), "=&D"(d1), "=&a"(d2)
return rc; : "0"(from), "1"(to)
: "memory");
return to;
} }

View File

@ -1,30 +1,17 @@
/* strcspn( const char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
size_t strcspn( const char * s1, const char * s2 ) size_t strcspn(const char* s1, const char* s2)
{ {
size_t len = 0; const char *p, *spanp;
const char * p; char c, sc;
while ( s1[len] ) for (p = s1;;) {
{ c = *p++;
p = s2; spanp = s2;
do {
while ( *p ) if ((sc = *spanp++) == c)
{ return p - 1 - s1;
if ( s1[len] == *p++ ) } while (sc != 0);
{
return len;
}
}
++len;
} }
return len;
} }

View File

@ -1,9 +1,9 @@
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
char* strdup(const char *str) char* strdup(const char* str)
{ {
char *buf = malloc(strlen(str) + 1); char* buf = malloc(strlen(str) + 1);
buf[strlen(str)] = '\0'; buf[strlen(str)] = '\0';
strcpy(buf, str); strcpy(buf, str);
return buf; return buf;

View File

@ -3,66 +3,34 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
int _errno; int __errno;
char* strerror(int err) char* strerror(int err)
{ {
char *msg; char *msg;
switch(err){ switch(err){
case 0: msg = "No errors"; break; case 0: msg = "No errors"; break;
case EPERM: msg = "Operation not permitted"; break;
case ENOENT: msg = "No such file or directory"; break;
case ESRCH: msg = "No such process"; break;
case EINTR: msg = "Interrupted system call"; break;
case EIO: msg = "Input/output error"; break;
case ENXIO: msg = "Device not configured"; break;
case E2BIG: msg = "Argument list too long"; break;
case ENOEXEC: msg = "Exec format error"; break;
case EBADF: msg = "Bad file descriptor"; break;
case ECHILD: msg = "No child processes"; break;
case EDEADLK: msg = "Resource deadlock avoided"; break;
case ENOMEM: msg = "Cannot allocate memory"; break;
case EACCES: msg = "Permission denied"; break;
case EFAULT: msg = "Bad address"; break;
case ENOTBLK: msg = "Block device required"; break;
case EBUSY: msg = "Device / Resource busy"; break;
case EEXIST: msg = "File exists"; break;
case EXDEV: msg = "Cross-device link"; break;
case ENODEV: msg = "Operation not supported by device"; break;
case ENOTDIR: msg = "Not a directory"; break;
case EISDIR: msg = "Is a directory"; break;
case EINVAL: msg = "Invalid argument"; break;
case ENFILE: msg = "Too many open files in system"; break;
case EMFILE: msg = "Too many open files"; break;
case ENOTTY: msg = "Inappropriate ioctl for device"; break;
case ETXTBSY: msg = "Text file busy"; break;
case EFBIG: msg = "File too large"; break;
case ENOSPC: msg = "No space left on device"; break;
case ESPIPE: msg = "Illegal seek"; break;
case EROFS: msg = "Read-only file system"; break;
case EMLINK: msg = "Too many links"; break;
case EPIPE: msg = "Broken pipe"; break;
// math software case ENOTSUP: msg = "Function is not supported"; break;
case EUNKNFS: msg = "Unknown file system"; break;
case ENOTFOUND: msg = "File not found"; break;
case EEOF: msg = "End of file"; break;
case EFAULT: msg = "Bad address"; break;
case EDQUOT: msg = "Disc quota exceeded"; break;
case EFS: msg = "File system error"; break;
case EACCES: msg = "Permission denied"; break;
case EDEV: msg = "Device error"; break;
case ENOMEMFS: msg = "File system requires more memory"; break;
case ENOMEM: msg = "Not enough memory"; break;
case ENOEXEC: msg = "Exec format error"; break;
case EPROCLIM: msg = "Too many processes"; break;
case EINVAL: msg = "Invalid argument"; break;
case EDOM: msg = "Numerical argument out of domain"; break; case EDOM: msg = "Numerical argument out of domain"; break;
case ERANGE: msg = "Result too large"; break; case ERANGE: msg = "Result too large"; break;
case EILSEQ: msg = "Illegal byte sequence"; break;
// should be rearranged
case EHOSTDOWN: msg = "Host is down"; break;
case EHOSTUNREACH: msg = "No route to host"; break;
case ENOTEMPTY: msg = "Directory not empty"; break;
// quotas & mush
case EPROCLIM: msg = "Too many processes"; break;
case EUSERS: msg = "Too many users"; break;
case EDQUOT: msg = "Disc quota exceeded"; break;
// Intelligent device errors
case EPWROFF: msg = "Device power is off"; break;
case EDEVERR: msg = "Device error, e.g. paper out"; break;
case EOVERFLOW: msg = "Value too large to be stored in data type"; break;
// Socket errors
case ENOBUFS: msg = "Broken buffer"; break; case ENOBUFS: msg = "Broken buffer"; break;
case EINPROGRESS: msg = "Operation now in progress"; break; case EINPROGRESS: msg = "Operation now in progress"; break;
case EOPNOTSUPP: msg = "Operation not supported on transport endpoint"; break; case EOPNOTSUPP: msg = "Operation not supported on transport endpoint"; break;

View File

@ -1,19 +1,16 @@
/* strlen( const char * ) /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
size_t strlen( const char * s ) size_t strlen(const char* str)
{ {
size_t rc = 0; int d0;
register int __res;
while ( s[rc] ) __asm__ __volatile__(
{ "repne\n\t"
++rc; "scasb\n\t"
} "notl %0\n\t"
"decl %0"
return rc; : "=c"(__res), "=&D"(d0)
: "1"(str), "a"(0), "0"(0xffffffff));
return __res;
} }

View File

@ -1,29 +1,23 @@
/* strncat( char *, const char *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strncat( char * s1, const char * s2, size_t n ) char* strncat(char* dst, const char* src, size_t n)
{ {
char * rc = s1; int d0, d1, d2, d3;
__asm__ __volatile__(
while ( *s1 ) "repne\n\t"
{ "scasb\n\t"
++s1; "decl %1\n\t"
} "movl %8,%3\n"
"1:\tdecl %3\n\t"
while ( n && ( *s1++ = *s2++ ) ) "js 2f\n\t"
{ "lodsb\n\t"
--n; "stosb\n\t"
} "testb %%al,%%al\n\t"
"jne 1b\n"
if ( n == 0 ) "2:\txorl %2,%2\n\t"
{ "stosb"
*s1 = '\0'; : "=&S"(d0), "=&D"(d1), "=&a"(d2), "=&c"(d3)
} : "0"(src), "1"(dst), "2"(0), "3"(0xffffffff), "g"(n)
: "memory");
return rc; return dst;
} }

View File

@ -1,26 +1,24 @@
/* strncmp( const char *, const char *, size_t ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
int strncmp( const char * s1, const char * s2, size_t n ) int strncmp(const char* s1, const char* s2, size_t n)
{ {
while ( n && *s1 && ( *s1 == *s2 ) ) register int __res;
{ int d0, d1, d2;
++s1; __asm__ __volatile__(
++s2; "1:\tdecl %3\n\t"
--n; "js 2f\n\t"
} "lodsb\n\t"
"scasb\n\t"
if ( n == 0 ) "jne 3f\n\t"
{ "testb %%al,%%al\n\t"
return 0; "jne 1b\n"
} "2:\txorl %%eax,%%eax\n\t"
else "jmp 4f\n"
{ "3:\tsbbl %%eax,%%eax\n\t"
return ( *( unsigned char * )s1 - * ( unsigned char * )s2 ); "orb $1,%%al\n"
} "4:"
: "=a"(__res), "=&S"(d0), "=&D"(d1), "=&c"(d2)
: "1"(s1), "2"(s2), "3"(n));
return __res;
} }

View File

@ -1,29 +1,21 @@
/* strncpy( char *, const char *, size_t ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strncpy( char * s1, const char * s2, size_t n ) char* strncpy(char* dst, const char* src, size_t n)
{ {
char * rc = s1; int d0, d1, d2, d3;
__asm__ __volatile__(
while ( n && ( *s1++ = *s2++ ) ) "1:\tdecl %2\n\t"
{ "js 2f\n\t"
/* Cannot do "n--" in the conditional as size_t is unsigned and we have "lodsb\n\t"
to check it again for >0 in the next loop below, so we must not risk "stosb\n\t"
underflow. "testb %%al,%%al\n\t"
*/ "jne 1b\n\t"
--n; "rep\n\t"
} "stosb\n"
"2:"
/* Checking against 1 as we missed the last --n in the loop above. */ : "=&S"(d0), "=&D"(d1), "=&c"(d2), "=&a"(d3)
while ( n-- > 1 ) : "0"(src), "1"(dst), "2"(n)
{ : "memory");
*s1++ = '\0'; return dst;
}
return rc;
} }

View File

@ -1,30 +1,16 @@
/* strpbrk( const char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "unconst.h"
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strpbrk( const char * s1, const char * s2 ) char* strpbrk(const char* s1, const char* s2)
{ {
const char * p1 = s1; const char* scanp;
const char * p2; int c, sc;
while ( *p1 ) while ((c = *s1++) != 0) {
{ for (scanp = s2; (sc = *scanp++) != 0;)
p2 = s2; if (sc == c)
return unconst(s1 - 1, char*);
while ( *p2 )
{
if ( *p1 == *p2++ )
{
return ( char * ) p1;
}
}
++p1;
} }
return 0;
return NULL;
} }

View File

@ -1,27 +1,18 @@
/* strrchr( const char *, int ) /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib). #include "unconst.h"
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strrchr( const char * s, int c ) char* strrchr(const char* s, int c)
{ {
size_t i = 0; char cc = c;
const char* sp = (char*)0;
while ( s[i++] ) while (*s) {
{ if (*s == cc)
/* EMPTY */ sp = s;
s++;
} }
if (cc == 0)
do sp = s;
{ return unconst(sp, char*);
if ( s[--i] == ( char ) c )
{
return ( char * ) s + i;
}
} while ( i );
return NULL;
} }

View File

@ -1,37 +1,15 @@
/* strspn( const char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
size_t strspn( const char * s1, const char * s2 ) size_t strspn(const char* s1, const char* s2)
{ {
size_t len = 0; const char *p = s1, *spanp;
const char * p; char c, sc;
while ( s1[ len ] ) cont:
{ c = *p++;
p = s2; for (spanp = s2; (sc = *spanp++) != 0;)
if (sc == c)
while ( *p ) goto cont;
{ return (p - 1 - s1);
if ( s1[len] == *p )
{
break;
}
++p;
}
if ( ! *p )
{
return len;
}
++len;
}
return len;
} }

View File

@ -1,34 +1,21 @@
/* strstr( const char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "unconst.h"
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char * strstr( const char * s1, const char * s2 ) char* strstr(const char* s, const char* find)
{ {
const char * p1 = s1; char c, sc;
const char * p2; size_t len;
while ( *s1 ) if ((c = *find++) != 0) {
{ len = strlen(find);
p2 = s2; do {
do {
while ( *p2 && ( *p1 == *p2 ) ) if ((sc = *s++) == 0)
{ return 0;
++p1; } while (sc != c);
++p2; } while (strncmp(s, find, len) != 0);
} s--;
if ( ! *p2 )
{
return ( char * ) s1;
}
++s1;
p1 = s1;
} }
return unconst(s, char*);
return NULL;
} }

View File

@ -1,30 +1,49 @@
/* strtok( char *, const char * ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
char* strtok(char* s, const char* delim) char* strtok(char* s, const char* delim)
{ {
static char* savep; const char* spanp;
char* res; int c, sc;
char* tok;
static char* last;
if(s) if (s == NULL && (s = last) == NULL)
savep = NULL; return (NULL);
else
s = savep;
if (*s == '\0') /*
return NULL; * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
s += strspn(s, delim); */
if (*s == '\0') cont:
return NULL; c = *s++;
res = s; for (spanp = delim; (sc = *spanp++) != 0;) {
s += strcspn(s, delim); if (c == sc)
savep = s + 1; goto cont;
*s = '\0'; }
return res;
if (c == 0) { /* no non-delimiter characters */
last = NULL;
return (NULL);
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
last = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
} }

View File

@ -1,26 +1,22 @@
/* strxfrm( char *, const char *, size_t ) /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h> #include <string.h>
size_t strxfrm( char * s1, const char * s2, size_t n ) size_t strxfrm(char* dst, const char* src, size_t n)
{ {
size_t len = strlen( s2 ); size_t r = 0;
int c;
if ( len < n ) if (n != 0) {
{ while ((c = *src++) != 0) {
/* Cannot use strncpy() here as the filling of s1 with '\0' is not part r++;
of the spec. if (--n == 0) {
*/ while (*src++ != 0)
/* FIXME: This should access _PDCLIB_lc_collate. */ r++;
while ( n-- && ( *s1++ = ( unsigned char )*s2++ ) ) break;
{ }
/* EMPTY */ *dst++ = c;
} }
*dst = 0;
} }
return r;
return len;
} }

View File

@ -0,0 +1,8 @@
#ifndef _UNCONST_H_
#define _UNCONST_H_
#ifndef unconst
#define unconst(__v, __t) __extension__ ({union { const __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;})
#endif
#endif // _UNCONST_H_

View File

@ -6,7 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define CHECK_DIR_ERR() if(_ksys_work_files(&inf)){ \ #define CHECK_DIR_ERR() if(_ksys70(&inf).status){ \
free((void*)inf.p16); \ free((void*)inf.p16); \
errno = ENOTDIR; \ errno = ENOTDIR; \
return NULL; \ return NULL; \

View File

@ -1,34 +1,34 @@
#include "stddef.h" #include "stddef.h"
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <stdio.h>
const char *wday_str[7]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; const char* wday_str[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
const char *mon_str[12]={"Jan", "Feb", "Mar", "Ap", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; const char* mon_str[12] = { "Jan", "Feb", "Mar", "Ap", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize("O0") #pragma GCC optimize("O0")
#define TIME_STR_MAX 27 #define TIME_STR_MAX 27
char *asctime(const struct tm *tm){ char* asctime(const struct tm* tm)
if(!tm){ {
errno = EINVAL; if (!tm) {
__errno = EINVAL;
return NULL; return NULL;
} }
if(tm->tm_wday>6 || tm->tm_wday<0 || tm->tm_mon<0 || tm->tm_mon>11){ if (tm->tm_wday > 6 || tm->tm_wday < 0 || tm->tm_mon < 0 || tm->tm_mon > 11) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
static char time_str[TIME_STR_MAX]; static char time_str[TIME_STR_MAX];
snprintf(time_str, TIME_STR_MAX-1, "%.3s %.3s%3d %02d:%02d:%02d %d\n", snprintf(time_str, TIME_STR_MAX - 1, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
wday_str[tm->tm_wday], wday_str[tm->tm_wday],
mon_str[tm->tm_mon], mon_str[tm->tm_mon],
tm->tm_mday, tm->tm_hour, tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec, tm->tm_min, tm->tm_sec,
1900 + tm->tm_year 1900 + tm->tm_year);
);
return time_str; return time_str;
} }
#pragma GCC pop_options #pragma GCC pop_options

View File

@ -1,6 +1,6 @@
#include <time.h> #include <time.h>
double difftime (time_t end, time_t beginning) double difftime(time_t end, time_t beginning)
{ {
return end - beginning; return end - beginning;
} }

View File

@ -1,108 +1,112 @@
#include <time.h>
#include <sys/ksys.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <sys/ksys.h>
#include <time.h>
#define LEAPOCH (946684800LL + 86400*(31+29)) #define LEAPOCH (946684800LL + 86400 * (31 + 29))
#define DAYS_PER_400Y (365*400 + 97) #define DAYS_PER_400Y (365 * 400 + 97)
#define DAYS_PER_100Y (365*100 + 24) #define DAYS_PER_100Y (365 * 100 + 24)
#define DAYS_PER_4Y (365*4 + 1) #define DAYS_PER_4Y (365 * 4 + 1)
static int __secs_to_tm(long long t, struct tm *tm) static int __secs_to_tm(long long t, struct tm* tm)
{ {
long long days, secs, years; long long days, secs, years;
int remdays, remsecs, remyears; int remdays, remsecs, remyears;
int qc_cycles, c_cycles, q_cycles; int qc_cycles, c_cycles, q_cycles;
int months; int months;
int wday, yday, leap; int wday, yday, leap;
static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29}; static const char days_in_month[] = { 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29 };
// Reject time_t values whose year would overflow int // Reject time_t values whose year would overflow int
if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL) if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
return -1; return -1;
secs = t - LEAPOCH; secs = t - LEAPOCH;
days = secs / 86400; days = secs / 86400;
remsecs = secs % 86400; remsecs = secs % 86400;
if (remsecs < 0) { if (remsecs < 0) {
remsecs += 86400; remsecs += 86400;
days--; days--;
} }
wday = (3+days)%7; wday = (3 + days) % 7;
if (wday < 0) wday += 7; if (wday < 0)
wday += 7;
qc_cycles = days / DAYS_PER_400Y; qc_cycles = days / DAYS_PER_400Y;
remdays = days % DAYS_PER_400Y; remdays = days % DAYS_PER_400Y;
if (remdays < 0) { if (remdays < 0) {
remdays += DAYS_PER_400Y; remdays += DAYS_PER_400Y;
qc_cycles--; qc_cycles--;
} }
c_cycles = remdays / DAYS_PER_100Y; c_cycles = remdays / DAYS_PER_100Y;
if (c_cycles == 4) c_cycles--; if (c_cycles == 4)
remdays -= c_cycles * DAYS_PER_100Y; c_cycles--;
remdays -= c_cycles * DAYS_PER_100Y;
q_cycles = remdays / DAYS_PER_4Y; q_cycles = remdays / DAYS_PER_4Y;
if (q_cycles == 25) q_cycles--; if (q_cycles == 25)
remdays -= q_cycles * DAYS_PER_4Y; q_cycles--;
remdays -= q_cycles * DAYS_PER_4Y;
remyears = remdays / 365; remyears = remdays / 365;
if (remyears == 4) remyears--; if (remyears == 4)
remdays -= remyears * 365; remyears--;
remdays -= remyears * 365;
leap = !remyears && (q_cycles || !c_cycles); leap = !remyears && (q_cycles || !c_cycles);
yday = remdays + 31 + 28 + leap; yday = remdays + 31 + 28 + leap;
if (yday >= 365+leap) yday -= 365+leap; if (yday >= 365 + leap)
yday -= 365 + leap;
years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles; years = remyears + 4 * q_cycles + 100 * c_cycles + 400LL * qc_cycles;
for (months=0; days_in_month[months] <= remdays; months++) for (months = 0; days_in_month[months] <= remdays; months++)
remdays -= days_in_month[months]; remdays -= days_in_month[months];
if (months >= 10) { if (months >= 10) {
months -= 12; months -= 12;
years++; years++;
} }
if (years+100 > INT_MAX || years+100 < INT_MIN) if (years + 100 > INT_MAX || years + 100 < INT_MIN)
return -1; return -1;
tm->tm_year = years + 100; tm->tm_year = years + 100;
tm->tm_mon = months + 2; tm->tm_mon = months + 2;
tm->tm_mday = remdays + 1; tm->tm_mday = remdays + 1;
tm->tm_wday = wday; tm->tm_wday = wday;
tm->tm_yday = yday; tm->tm_yday = yday;
tm->tm_hour = remsecs / 3600; tm->tm_hour = remsecs / 3600;
tm->tm_min = remsecs / 60 % 60; tm->tm_min = remsecs / 60 % 60;
tm->tm_sec = remsecs % 60; tm->tm_sec = remsecs % 60;
return 0; return 0;
} }
struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict tm) struct tm* __localtime_r(const time_t* restrict t, struct tm* restrict tm)
{ {
// Reject time_t values whose year would overflow int because // Reject time_t values whose year would overflow int because
// __secs_to_zone cannot safely handle them. // __secs_to_zone cannot safely handle them.
if (*t < INT_MIN * 31622400LL || *t > INT_MAX * 31622400LL) { if (*t < INT_MIN * 31622400LL || *t > INT_MAX * 31622400LL) {
errno = EOVERFLOW; errno = EOVERFLOW;
return NULL; return NULL;
} }
//__secs_to_zone(*t, 0, &tm->tm_isdst, &tm->__tm_gmtoff, 0, &tm->__tm_zone); //__secs_to_zone(*t, 0, &tm->tm_isdst, &tm->__tm_gmtoff, 0, &tm->__tm_zone);
if (__secs_to_tm((long long)*t,tm) < 0) { if (__secs_to_tm((long long)*t, tm) < 0) {
errno = EOVERFLOW; errno = EOVERFLOW;
return NULL; return NULL;
} }
return tm; return tm;
} }
struct tm * localtime (const time_t * timer) struct tm* localtime(const time_t* timer)
{ {
static struct tm tm; static struct tm tm;
return __localtime_r(timer, &tm); return __localtime_r(timer, &tm);
} }

View File

@ -1,23 +1,23 @@
#include <time.h> #include <time.h>
time_t mktime (struct tm * timeptr) time_t mktime(struct tm* timeptr)
{ {
// int utcdiff = -3; // int utcdiff = -3;
const int mon_days [] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int mon_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned long int tyears, tdays, leaps, utc_hrs; unsigned long int tyears, tdays, leaps, utc_hrs;
int i; int i;
tyears = timeptr->tm_year - 70 ;// tm->tm_year is from 1900. tyears = timeptr->tm_year - 70; // tm->tm_year is from 1900.
leaps = (tyears + 2) / 4; // no of next two lines until year 2100. leaps = (tyears + 2) / 4; // no of next two lines until year 2100.
i = (timeptr->tm_year - 100) / 100; i = (timeptr->tm_year - 100) / 100;
leaps -= ( (i/4)*3 + i%4 ); leaps -= ((i / 4) * 3 + i % 4);
tdays = 0; tdays = 0;
for (i=0; i < timeptr->tm_mon; i++) tdays += mon_days[i]; for (i = 0; i < timeptr->tm_mon; i++)
tdays += mon_days[i];
tdays += timeptr->tm_mday-1; // days of month passed. tdays += timeptr->tm_mday - 1; // days of month passed.
tdays = tdays + (tyears * 365) + leaps; tdays = tdays + (tyears * 365) + leaps;
// utc_hrs = timeptr->tm_hour + utcdiff; // for your time zone. // utc_hrs = timeptr->tm_hour + utcdiff; // for your time zone.
return (tdays * 86400) + (timeptr->tm_hour * 3600) + (timeptr->tm_min * 60) + timeptr->tm_sec; return (tdays * 86400) + (timeptr->tm_hour * 3600) + (timeptr->tm_min * 60) + timeptr->tm_sec;
} }

View File

@ -1,7 +1,8 @@
#include <time.h>
#include <sys/ksys.h> #include <sys/ksys.h>
#include <time.h>
time_t time(time_t *timer){ time_t time(time_t* timer)
{
static struct tm __buffertime; static struct tm __buffertime;
int kos_date, kos_time; int kos_date, kos_time;
kos_date = _ksys_get_date().val; kos_date = _ksys_get_date().val;
@ -10,9 +11,9 @@ time_t time(time_t *timer){
int bcd_day = (kos_date >> 16); int bcd_day = (kos_date >> 16);
int bcd_mon = ((kos_date & 0xFF00) >> 8); int bcd_mon = ((kos_date & 0xFF00) >> 8);
int bcd_year = (kos_date & 0xFF); int bcd_year = (kos_date & 0xFF);
__buffertime.tm_mday = ((bcd_day & 0xF0)>>4)*10 + (bcd_day & 0x0F); __buffertime.tm_mday = ((bcd_day & 0xF0) >> 4) * 10 + (bcd_day & 0x0F);
__buffertime.tm_mon = ((bcd_mon & 0xF0)>>4)*10 + (bcd_mon & 0x0F) - 1; __buffertime.tm_mon = ((bcd_mon & 0xF0) >> 4) * 10 + (bcd_mon & 0x0F) - 1;
__buffertime.tm_year = ((bcd_year & 0xF0)>>4)*10 + (bcd_year & 0x0F) + 100; __buffertime.tm_year = ((bcd_year & 0xF0) >> 4) * 10 + (bcd_year & 0x0F) + 100;
__buffertime.tm_wday = __buffertime.tm_yday = __buffertime.tm_isdst = -1; /* temporary */ __buffertime.tm_wday = __buffertime.tm_yday = __buffertime.tm_isdst = -1; /* temporary */
@ -20,13 +21,13 @@ time_t time(time_t *timer){
int bcd_min = ((kos_time & 0xFF00) >> 8); int bcd_min = ((kos_time & 0xFF00) >> 8);
int bcd_hour = (kos_time & 0xFF); int bcd_hour = (kos_time & 0xFF);
__buffertime.tm_sec = ((bcd_sec & 0xF0)>>4)*10 + (bcd_sec & 0x0F); __buffertime.tm_sec = ((bcd_sec & 0xF0) >> 4) * 10 + (bcd_sec & 0x0F);
__buffertime.tm_min = ((bcd_min & 0xF0)>>4)*10 + (bcd_min & 0x0F); __buffertime.tm_min = ((bcd_min & 0xF0) >> 4) * 10 + (bcd_min & 0x0F);
__buffertime.tm_hour = ((bcd_hour & 0xF0)>>4)*10 + (bcd_hour & 0x0F); __buffertime.tm_hour = ((bcd_hour & 0xF0) >> 4) * 10 + (bcd_hour & 0x0F);
time_t ret = mktime(&__buffertime); time_t ret = mktime(&__buffertime);
if(timer){ if (timer) {
*timer=ret; *timer = ret;
} }
return ret; return ret;
} }