diff --git a/programs/develop/libraries/kolibri-libc/.gitignore b/programs/develop/libraries/kolibri-libc/.gitignore new file mode 100644 index 0000000000..72d3598050 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/.gitignore @@ -0,0 +1,8 @@ +*.swp +lib/libc.obj +lib/libc.obj.a +lib/crt0.o +*.o +tests/argtest +source/make.bat +/samples/*.kex diff --git a/programs/develop/libraries/kolibri-libc/compile_flags.txt b/programs/develop/libraries/kolibri-libc/compile_flags.txt new file mode 100644 index 0000000000..9b0813db28 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/compile_flags.txt @@ -0,0 +1,5 @@ +-D +_KOLIBRI_LIBC_OBJ +-I +include + diff --git a/programs/develop/libraries/kolibri-libc/include/clayer/network.h b/programs/develop/libraries/kolibri-libc/include/clayer/network.h new file mode 100644 index 0000000000..3ac45bdebf --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/clayer/network.h @@ -0,0 +1,57 @@ +#ifndef __NETWORK_H +#define __NETWORK_H + +#include +#include + +#define stdcall __attribute__ ((stdcall)) + +#define EAI_ADDRFAMILY 1 +#define EAI_AGAIN 2 +#define EAI_BADFLAGS 3 +#define EAI_FAIL 4 +#define EAI_FAMILY 5 +#define EAI_MEMORY 6 +#define EAI_NONAME 8 +#define EAI_SERVICE 9 +#define EAI_SOCKTYPE 10 +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_OVERFLOW 14 + +// Flags for addrinfo +#define AI_PASSIVE 1 +#define AI_CANONNAME 2 +#define AI_NUMERICHOST 4 +#define AI_NUMERICSERV 8 +#define AI_ADDRCONFIG 0x400 + +#pragma pack(push, 1) +struct ARP_entry{ +unsigned int IP; +unsigned char MAC[6]; +unsigned short status; +unsigned short TTL; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + int ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#pragma pack(pop) + +extern int networklib_init (); +extern int stdcall (*inet_addr)(const char* hostname); +extern char* stdcall (*inet_ntoa)(int ip_addr); +extern int stdcall (*getaddrinfo)(const char* hostname, const char* servname, const struct addrinfo* hints, struct addrinfo** res); +extern void stdcall (*freeaddrinfo)(struct addrinfo* ai); + +#endif diff --git a/programs/develop/libraries/kolibri-libc/include/ctype.h b/programs/develop/libraries/kolibri-libc/include/ctype.h new file mode 100644 index 0000000000..5f87ebe292 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/ctype.h @@ -0,0 +1,45 @@ +#ifndef _CTYPE_H_ +#define _CTYPE_H_ +/* +** All character classification functions except isascii(). +** Integer argument (c) must be in ASCII range (0-127) for +** dependable answers. +*/ + +#define __ALNUM 1 +#define __ALPHA 2 +#define __CNTRL 4 +#define __DIGIT 8 +#define __GRAPH 16 +#define __LOWER 32 +#define __PRINT 64 +#define __PUNCT 128 +#define __BLANK 256 +#define __UPPER 512 +#define __XDIGIT 1024 + +#ifdef _KOLIBRI_LIBC_OBJ +extern unsigned short __is[129]; +#else +extern unsigned short *__is; +#endif + +#define isalnum(c)(__is[c+1] & __ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */ +#define isalpha(c)(__is[c+1] & __ALPHA ) /* 'a'-'z', 'A'-'Z' */ +#define iscntrl(c)(__is[c+1] & __CNTRL ) /* 0-31, 127 */ +#define isdigit(c)(__is[c+1] & __DIGIT ) /* '0'-'9' */ +#define isgraph(c)(__is[c+1] & __GRAPH ) /* '!'-'~' */ +#define islower(c)(__is[c+1] & __LOWER ) /* 'a'-'z' */ +#define isprint(c)(__is[c+1] & __PRINT ) /* ' '-'~' */ +#define ispunct(c)(__is[c+1] & __PUNCT ) /* !alnum && !cntrl && !space */ +#define isspace(c)(__is[c+1] & __BLANK ) /* HT, LF, VT, FF, CR, ' ' */ +#define isupper(c)(__is[c+1] & __UPPER ) /* 'A'-'Z' */ +#define isxdigit(c)(__is[c+1] & __XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */ + +#define isascii(c) (!((c)&(~0x7f))) +#define toascii(c) ((c)&0x7f) + +extern unsigned char tolower(unsigned char c); +extern unsigned char toupper(unsigned char c); + +#endif \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/errno.h b/programs/develop/libraries/kolibri-libc/include/errno.h new file mode 100644 index 0000000000..4735f0edb7 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/errno.h @@ -0,0 +1,144 @@ +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int errno; + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ +/* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device / Resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ + +/* math software */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ + +/* non-blocking and interrupt i/o */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ + +/* ipc/network software -- argument errors */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define ENOTSUP 45 /* Operation not supported */ +#define EOPNOTSUPP ENOTSUP /* Operation not supported on socket */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ + +/* ipc/network software -- operational errors */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#define ETIMEDOUT 60 /* Operation timed out */ +#define ECONNREFUSED 61 /* Connection refused */ +#define ELOOP 62 /* Too many levels of symbolic links */ +#define ENAMETOOLONG 63 /* File name too long */ + +/* should be rearranged */ +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ + +/* quotas & mush */ +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Disc quota exceeded */ + +/* Network File System */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ +#define EFTYPE 79 /* Inappropriate file type or format */ +#define EAUTH 80 /* Authentication error */ +#define ENEEDAUTH 81 /* Need authenticator */ + +/* Intelligent device errors */ +#define EPWROFF 82 /* Device power is off */ +#define EDEVERR 83 /* Device error, e.g. paper out */ +#define EOVERFLOW 84 /* Value too large to be stored in data type */ + +/* Program loading errors */ +#define EBADEXEC 85 /* Bad executable */ +#define EBADARCH 86 /* Bad CPU type in executable */ +#define ESHLIBVERS 87 /* Shared library version mismatch */ +#define EBADMACHO 88 /* Malformed Macho file */ +#define ECANCELED 89 /* Operation canceled */ +#define EIDRM 90 /* Identifier removed */ +#define ENOMSG 91 /* No message of desired type */ +#define EILSEQ 92 /* Illegal byte sequence */ +#define ENOATTR 93 /* Attribute not found */ +#define EBADMSG 94 /* Bad message */ +#define EMULTIHOP 95 /* Reserved */ +#define ENODATA 96 /* No message available on STREAM */ +#define ENOLINK 97 /* Reserved */ +#define ENOSR 98 /* No STREAM resources */ +#define ENOSTR 99 /* Not a STREAM */ +#define EPROTO 100 /* Protocol error */ +#define ETIME 101 /* STREAM ioctl timeout */ +#define ENOPOLICY 103 /* No such policy registered */ +#define ENOTRECOVERABLE 104 /* State not recoverable */ +#define EOWNERDEAD 105 /* Previous owner died */ +#define EQFULL 106 /* Interface output queue is full */ +#define ELAST 106 /* Must be equal largest errno */ + +#ifdef __cplusplus +} +#endif + +#endif // _ERRNO_H_ \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/float.h b/programs/develop/libraries/kolibri-libc/include/float.h new file mode 100644 index 0000000000..a2b4ed26a0 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/float.h @@ -0,0 +1,65 @@ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ + +#define FLT_RADIX 2 + +/* IEEE float */ +#define FLT_MANT_DIG 24 +#define FLT_DIG 6 +#define FLT_ROUNDS 1 +#define FLT_EPSILON 1.19209290e-07F +#define FLT_MIN_EXP (-125) +#define FLT_MIN 1.17549435e-38F +#define FLT_MIN_10_EXP (-37) +#define FLT_MAX_EXP 128 +#define FLT_MAX 3.40282347e+38F +#define FLT_MAX_10_EXP 38 + +/* IEEE double */ +#define DBL_MANT_DIG 53 +#define DBL_DIG 15 +#define DBL_EPSILON 2.2204460492503131e-16 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014e-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157e+308 +#define DBL_MAX_10_EXP 308 + +/* horrible intel long double */ +#if defined __i386__ || defined __x86_64__ + +#define LDBL_MANT_DIG 64 +#define LDBL_DIG 18 +#define LDBL_EPSILON 1.08420217248550443401e-19L +#define LDBL_MIN_EXP (-16381) +#define LDBL_MIN 3.36210314311209350626e-4932L +#define LDBL_MIN_10_EXP (-4931) +#define LDBL_MAX_EXP 16384 +#define LDBL_MAX 1.18973149535723176502e+4932L +#define LDBL_MAX_10_EXP 4932 + +#else + +/* same as IEEE double */ +#define LDBL_MANT_DIG 53 +#define LDBL_DIG 15 +#define LDBL_EPSILON 2.2204460492503131e-16 +#define LDBL_MIN_EXP (-1021) +#define LDBL_MIN 2.2250738585072014e-308 +#define LDBL_MIN_10_EXP (-307) +#define LDBL_MAX_EXP 1024 +#define LDBL_MAX 1.7976931348623157e+308 +#define LDBL_MAX_10_EXP 308 + +#endif + +#ifndef NAN +# define NAN (__nan__) +#endif + +#ifndef INFINITY +# define INFINITY (__inf__) +#endif + +#endif /* _FLOAT_H_ */ diff --git a/programs/develop/libraries/kolibri-libc/include/limits.h b/programs/develop/libraries/kolibri-libc/include/limits.h new file mode 100644 index 0000000000..9bdcba4695 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/limits.h @@ -0,0 +1,21 @@ +#ifndef _LIMITS_H_ +#define _LIMITS_H_ + + +#define INT_MAX 2147483647 +#define UINT_MAX (INT_MAX * 2U + 1) + + +#ifndef ARG_MAX +#define ARG_MAX 4096 +#endif + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifndef STDIO_MAX_MEM +#define STDIO_MAX_MEM 4096 +#endif + +#endif /* _LIMITS_H_ */ \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/math.h b/programs/develop/libraries/kolibri-libc/include/math.h new file mode 100644 index 0000000000..b1749dc50b --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/math.h @@ -0,0 +1,171 @@ +/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef _MATH_H_ +#define _MATH_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern double _FUNC(acos)(double _x); +extern double _FUNC(asin)(double _x); +extern double _FUNC(atan)(double _x); +extern double _FUNC(atan2)(double _y, double _x); +extern double _FUNC(ceil)(double _x); +extern double _FUNC(cos)(double _x); +extern double _FUNC(cosh)(double _x); +extern double _FUNC(exp)(double _x); +extern double _FUNC(fabs)(double _x); +extern double _FUNC(floor)(double _x); +extern double _FUNC(fmod)(double _x, double _y); +extern double _FUNC(frexp)(double _x, int *_pexp); +extern double _FUNC(ldexp)(double _x, int _exp); +extern double _FUNC(log)(double _y); +extern double _FUNC(log10)(double _x); +extern double _FUNC(modf)(double _x, double *_pint); +extern double _FUNC(pow)(double _x, double _y); +extern double _FUNC(sin)(double _x); +extern double _FUNC(sinh)(double _x); +extern double _FUNC(sqrt)(double _x); +extern double _FUNC(tan)(double _x); +extern double _FUNC(tanh)(double _x); + +#define M_E 2.7182818284590452354 +#define M_LOG2E 1.4426950408889634074 +#define M_LOG10E 0.43429448190325182765 +#define M_LN2 0.69314718055994530942 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 +#define PI M_PI +#define PI2 M_PI_2 + +extern double _FUNC(acosh)(double); +extern double _FUNC(asinh)(double); +extern double _FUNC(atanh)(double); +extern double _FUNC(cbrt)(double); +extern double _FUNC(exp10)(double _x); +extern double _FUNC(exp2)(double _x); +extern double _FUNC(expm1)(double); +extern double _FUNC(hypot)(double, double); +extern double _FUNC(log1p)(double); +extern double _FUNC(log2)(double _x); +extern long double _FUNC(modfl)(long double _x, long double *_pint); +extern double _FUNC(pow10)(double _x); +extern double _FUNC(pow2)(double _x); +extern double _FUNC(powi)(double, int); +extern void _FUNC(sincos)(double, double *, double *); + +/* These are in libm.a (Cygnus). You must link -lm to get these */ +/* See libm/math.h for comments */ + +#ifndef __cplusplus +struct exception { + int type; + const char *name; + double arg1; + double arg2; + double retval; + int err; +}; +#endif + +extern double _FUNC(erf)(double); +extern double _FUNC(erfc)(double); +extern double _FUNC(gamma)(double); +extern int _FUNC(isinf)(double); +extern int _FUNC(isnan)(double); +extern int _FUNC(finite)(double); +extern double _FUNC(j0)(double); +extern double _FUNC(j1)(double); +extern double _FUNC(jn)(int, double); +extern double _FUNC(lgamma)(double); +extern double _FUNC(nan)(const char*); +extern double _FUNC(y0)(double); +extern double _FUNC(y1)(double); +extern double _FUNC(yn)(int, double); +extern double _FUNC(logb)(double); +extern double _FUNC(nextafter)(double, double); +extern double _FUNC(remainder)(double, double); +extern double _FUNC(scalb)(double, double); +#ifndef __cplusplus +extern int _FUNC(matherr)(struct exception *); +#endif +extern double _FUNC(significand)(double); +extern double _FUNC(copysign)(double, double); +extern int _FUNC(ilogb)(double); +extern double _FUNC(rint)(double); +extern double _FUNC(scalbn)(double, int); +extern double _FUNC(drem)(double, double); +extern double _FUNC(gamma_r)(double, int *); +extern double _FUNC(lgamma_r)(double, int *); +extern float _FUNC(acosf)(float); +extern float _FUNC(asinf)(float); +extern float _FUNC(atanf)(float); +extern float _FUNC(atan2f)(float, float); +extern float _FUNC(cosf)(float); +extern float _FUNC(sinf)(float); +extern float _FUNC(tanf)(float); +extern float _FUNC(coshf)(float); +extern float _FUNC(sinhf)(float); +extern float _FUNC(tanhf)(float); +extern float _FUNC(expf)(float); +extern float _FUNC(frexpf)(float, int *); +extern float _FUNC(ldexpf)(float, int); +extern float _FUNC(logf)(float); +extern float _FUNC(log10f)(float); +extern float _FUNC(modff)(float, float *); +extern float _FUNC(powf)(float, float); +extern float _FUNC(sqrtf)(float); +extern float _FUNC(ceilf)(float); +extern float _FUNC(fabsf)(float); +extern float _FUNC(floorf)(float); +extern float _FUNC(fmodf)(float, float); +extern float _FUNC(erff)(float); +extern float _FUNC(erfcf)(float); +extern float _FUNC(gammaf)(float); +extern float _FUNC(hypotf)(float, float); +extern int _FUNC(isinff)(float); +extern int _FUNC(isnanf)(float); +extern int _FUNC(finitef)(float); +extern float _FUNC(j0f)(float); +extern float _FUNC(j1f)(float); +extern float _FUNC(jnf)(int, float); +extern float _FUNC(lgammaf)(float); +extern float _FUNC(nanf)(const char*); +extern float _FUNC(y0f)(float); +extern float _FUNC(y1f)(float); +extern float _FUNC(ynf)(int, float); +extern float _FUNC(acoshf)(float); +extern float _FUNC(asinhf)(float); +extern float _FUNC(atanhf)(float); +extern float _FUNC(cbrtf)(float); +extern float _FUNC(logbf)(float); +extern float _FUNC(nextafterf)(float, float); +extern float _FUNC(remainderf)(float, float); +extern float _FUNC(scalbf)(float, float); +extern float _FUNC(significandf)(float); +extern float _FUNC(copysignf)(float, float); +extern int _FUNC(ilogbf)(float); +extern float _FUNC(rintf)(float); +extern float _FUNC(scalbnf)(float, int); +extern float _FUNC(dremf)(float, float); +extern float _FUNC(expm1f)(float); +extern float _FUNC(log1pf)(float); +extern float _FUNC(gammaf_r)(float, int *); +extern float _FUNC(lgammaf_r)(float, int *); + +#ifdef __cplusplus +} +#endif + +#endif /* _MATH_H_ */ \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/setjmp.h b/programs/develop/libraries/kolibri-libc/include/setjmp.h new file mode 100644 index 0000000000..aa1993680e --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/setjmp.h @@ -0,0 +1,17 @@ +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +#include + +typedef unsigned long __jmp_buf[6]; + +typedef struct __jmp_buf_tag { + __jmp_buf __jb; + unsigned long __fl; + unsigned long __ss[128/sizeof(long)]; +} jmp_buf[1]; + +extern int _FUNC(setjmp)(jmp_buf env); +extern void _FUNC(longjmp)(jmp_buf env, int val); + +#endif // _SETJMP_H_ diff --git a/programs/develop/libraries/kolibri-libc/include/stdarg.h b/programs/develop/libraries/kolibri-libc/include/stdarg.h new file mode 100644 index 0000000000..bd0928d891 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/stdarg.h @@ -0,0 +1,77 @@ +#ifndef _STDARG_H_ +#define _STDARG_H_ + +#include + +#ifdef __x86_64__ +#ifndef _WIN64 + +//This should be in sync with the declaration on our lib/libtcc1.c +/* GCC compatible definition of va_list. */ +typedef struct { + unsigned int gp_offset; + unsigned int fp_offset; + union { + unsigned int overflow_offset; + char *overflow_arg_area; + }; + char *reg_save_area; +} __va_list_struct; + +typedef __va_list_struct va_list[1]; + +extern void _FUNC(__va_start)(__va_list_struct *ap, void *fp); +extern void* _FUNC(__va_arg)(__va_list_struct *ap, int arg_type, int size, int align); + +#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0)) +#define va_arg(ap, type) \ + (*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type)))) +#define va_copy(dest, src) (*(dest) = *(src)) +#define va_end(ap) + +#else /* _WIN64 */ +typedef char *va_list; +#define va_start(ap,last) __builtin_va_start(ap,last) +#define va_arg(ap,type) (ap += 8, sizeof(type)<=8 ? *(type*)ap : **(type**)ap) +#define va_copy(dest, src) ((dest) = (src)) +#define va_end(ap) +#endif + +#elif __arm__ +typedef char *va_list; +#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x) +#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \ + & ~(_tcc_alignof(type) - 1)) +#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3) +#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \ + &~3), *(type *)(ap - ((sizeof(type)+3)&~3))) +#define va_copy(dest, src) (dest) = (src) +#define va_end(ap) + +#elif defined(__aarch64__) +typedef struct { + void *__stack; + void *__gr_top; + void *__vr_top; + int __gr_offs; + int __vr_offs; +} va_list; +#define va_start(ap, last) __va_start(ap, last) +#define va_arg(ap, type) __va_arg(ap, type) +#define va_end(ap) +#define va_copy(dest, src) ((dest) = (src)) + +#else /* __i386__ */ +typedef char *va_list; +/* only correct for i386 */ +#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3) +#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3))) +#define va_copy(dest, src) (dest) = (src) +#define va_end(ap) +#endif + +/* fix a buggy dependency on GCC in libio.h */ +typedef va_list __gnuc_va_list; +#define _VA_LIST_DEFINED + +#endif /* _STDARG_H */ diff --git a/programs/develop/libraries/kolibri-libc/include/stdbool.h b/programs/develop/libraries/kolibri-libc/include/stdbool.h new file mode 100644 index 0000000000..0af22124ae --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/stdbool.h @@ -0,0 +1,11 @@ +#ifndef _STDBOOL_H_ +#define _STDBOOL_H_ + +/* ISOC99 boolean */ + +#define bool _Bool +#define true 1 +#define false 0 +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H */ diff --git a/programs/develop/libraries/kolibri-libc/include/stddef.h b/programs/develop/libraries/kolibri-libc/include/stddef.h new file mode 100644 index 0000000000..bea97027f1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/stddef.h @@ -0,0 +1,37 @@ +#ifndef _STDDEF_H_ +#define _STDDEF_H_ + +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ssize_t; +typedef __WCHAR_TYPE__ wchar_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __PTRDIFF_TYPE__ intptr_t; +typedef __SIZE_TYPE__ uintptr_t; + +#ifndef __int8_t_defined +#define __int8_t_defined +typedef signed char int8_t; +typedef signed short int int16_t; +typedef signed int int32_t; +typedef signed long long int int64_t; +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#endif + +#ifndef NULL + #define NULL ((void*)0) +#endif + +#ifdef _KOLIBRI_LIBC_OBJ + #define _FUNC(func) func +#else + #define _FUNC(func) (*func) +#endif + +#define offsetof(type, field) ((size_t)&((type *)0)->field) + +#endif /* _STDDEF_H_ */ \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/stdint.h b/programs/develop/libraries/kolibri-libc/include/stdint.h new file mode 100644 index 0000000000..916e999f6f --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/stdint.h @@ -0,0 +1,28 @@ +#ifndef _STDINT_H_ +#define _STDINT_H_ + +#include + +#define INT8_MIN (-128) +#define INT8_MAX (127) +#define UINT8_MAX (255) + +#define INT16_MIN (-32768) +#define INT16_MAX (32767) +#define UINT16_MAX (65535) + +#define INT32_MIN (-2147483647L-1) +#define INT32_MAX (2147483647L) +#define UINT32_MAX (4294967295UL) + +#if __have_long64 +#define INT64_MIN (-9223372036854775807L-1L) +#define INT64_MAX (9223372036854775807L) +#define UINT64_MAX (18446744073709551615U) +#elif __have_longlong64 +#define INT64_MIN (-9223372036854775807LL-1LL) +#define INT64_MAX (9223372036854775807LL) +#define UINT64_MAX (18446744073709551615ULL) +#endif + +#endif /* _STDINT_H_*/ diff --git a/programs/develop/libraries/kolibri-libc/include/stdio.h b/programs/develop/libraries/kolibri-libc/include/stdio.h new file mode 100644 index 0000000000..fb97057b33 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/stdio.h @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include +#include +#include + +extern int _FUNC(puts)(const char *str); +extern int _FUNC(printf)(const char* format, ...); +extern int _FUNC(sprintf)(char* buffer, const char* format, ...); +extern int _FUNC(snprintf)(char* buffer, size_t count, const char* format, ...); +extern int _FUNC(vsnprintf)(char* buffer, size_t count, const char* format, va_list va); +extern int _FUNC(vprintf)(const char* format, va_list va); + +extern void _FUNC(debug_printf)(const char* format, ...); + +typedef size_t fpos_t; + +#define _STDIO_F_R 1 << 0 // Read +#define _STDIO_F_W 1 << 1 // Write +#define _STDIO_F_A 1 << 2 // Append +#define _STDIO_F_X 1 << 3 // eXclusive +#define _STDIO_F_B 1 << 4 // Binary + +typedef struct FILE_s { + char *name; + fpos_t position; + int error; + int eof; + int kind; // 0 - undiefned, 1 - text, 2 - binary + int orientation; // 0 - undiefned, 1 - byte, 2 - wide + int mode; // flags _STDIO_F_* + int append_offset; // do not seek before this point ("a" mode) + int __ungetc_emu_buff; // Uses __ungetc_emu (temporary solution!) + int start_size; +} FILE; + +#define _IOFBF 0 +#define _IOLBF 1 +#define _IONBF 2 + +#define BUFSIZ 1024 + +#define EOF -1 + +#define FOPEN_MAX 0xffffffff + +#define FILENAME_MAX 255 + +#define L_tmpnam FILENAME_MAX + +#define SEEK_CUR 0 +#define SEEK_END 1 +#define SEEK_SET 2 + +#define TMP_MAX FOPEN_MAX + +#define stderr (FILE*)3 +#define stdin (FILE*)1 +#define stdout (FILE*)2 + +extern int _FUNC(fgetc)(FILE *); +extern char* _FUNC(fgets)(char *restrict, int, FILE *restrict); +extern int _FUNC(fprintf)(FILE *restrict, const char *restrict, ...); +extern int _FUNC(fputc)(int, FILE *); +extern int _FUNC(fputs)(const char *restrict, FILE *restrict); +extern size_t _FUNC(fread)(void *restrict, size_t size, size_t count, FILE *restrict); +extern int _FUNC(fscanf)(FILE *restrict, const char *restrict, ...); +extern size_t _FUNC(fwrite)(const void *restrict, size_t size, size_t count, FILE *restrict); +extern int _FUNC(getc)(FILE *); +#define getc _FUNC(fgetc) +extern int _FUNC(getchar)(void); +extern int _FUNC(printf)(const char *restrict, ...); +extern int _FUNC(putc)(int, FILE *); +extern int _FUNC(putchar)(int); +extern int _FUNC(puts)(const char *); +extern int _FUNC(scanf)(const char *restrict, ...); +extern char* _FUNC(gets)(char *str); +//extern int _FUNC(ungetc)(int, FILE *); +extern int _FUNC(vfprintf)(FILE *restrict, const char *restrict, va_list); +extern int _FUNC(vfscanf)(FILE *restrict, const char *restrict, va_list); +extern int _FUNC(vprintf)(const char *restrict, va_list); +extern int _FUNC(vscanf)(const char *restrict, va_list); +extern int _FUNC(vsscanf)(const char *, const char*, va_list); + +extern int _FUNC(remove)(const char *); +extern int _FUNC(rename)(const char *, const char *); +extern FILE* _FUNC(tmpfile)(void); +extern char* _FUNC(tmpnam)(char *); + +extern int _FUNC(fclose)(FILE *); +extern int _FUNC(fflush)(FILE *); +extern FILE* _FUNC(fopen)(const char *restrict, const char *restrict); +extern FILE* _FUNC(freopen)(const char *restrict, const char *restrict, FILE *restrict); +extern void _FUNC(setbuf)(FILE *restrict, char *restrict); +extern int _FUNC(setvbuf)(FILE *restrict, char *restrict, int, size_t); + +extern int _FUNC(fgetpos)(FILE *restrict, fpos_t *restrict); +extern int _FUNC(fseek)(FILE *, long, int); +extern int _FUNC(fsetpos)(FILE *, const fpos_t *); +extern long _FUNC(ftell)(FILE *); +extern void _FUNC(rewind)(FILE *); + +extern void _FUNC(clearerr)(FILE *); +extern int _FUNC(feof)(FILE *); +extern int _FUNC(ferror)(FILE *); +extern void _FUNC(perror)(const char *); + +extern size_t _FUNC(fread)(void *restrict, size_t, size_t, FILE *restrict); + +extern int _FUNC(getchar)(void); + +extern void _FUNC(con_set_title)(const char*); + +#endif // _STDIO_H_ diff --git a/programs/develop/libraries/kolibri-libc/include/stdlib.h b/programs/develop/libraries/kolibri-libc/include/stdlib.h new file mode 100644 index 0000000000..8ea389bfe7 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/stdlib.h @@ -0,0 +1,40 @@ +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include + +#define RAND_MAX 65535 +#ifndef NULL +# define NULL ((void*)0) +#endif + +#define min(a, b) ((a)<(b) ? (a) : (b)) +#define max(a, b) ((a)>(b) ? (a) : (b)) + +extern int _FUNC(atoi)(const char *s); +extern long _FUNC(atol)(const char *); +extern long long _FUNC(atoll)(const char *); +extern void _FUNC(itoa)(int n, char* s); + +extern int _FUNC(abs)(int); +extern long _FUNC(labs)(long); +extern long long _FUNC(llabs)(long long); + +typedef struct { int quot, rem; } div_t; +typedef struct { long quot, rem; } ldiv_t; +typedef struct { long long quot, rem; } lldiv_t; + +extern div_t _FUNC(div)(int, int); +extern ldiv_t _FUNC(ldiv)(long, long); +extern lldiv_t _FUNC(lldiv)(long long, long long); + +extern void* _FUNC(malloc)(size_t size); +extern void* _FUNC(calloc)(size_t num, size_t size); +extern void* _FUNC(realloc)(void *ptr, size_t newsize); +extern void _FUNC(free)(void *ptr); + +extern long int _FUNC(strtol)(const char* str, char** endptr, int base); + +extern void _FUNC(exit)(int status); + +#endif \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/string.h b/programs/develop/libraries/kolibri-libc/include/string.h new file mode 100644 index 0000000000..33bcf99133 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/string.h @@ -0,0 +1,186 @@ +/* String handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* String function conventions */ + +/* + In any of the following functions taking a size_t n to specify the length of + an array or size of a memory region, n may be 0, but the pointer arguments to + the call shall still be valid unless otherwise stated. +*/ + +/* Copying functions */ + +extern void* _FUNC(memccpy)(void *restrict dest, const void *restrict src, int c, size_t n); + +/* Copy a number of n characters from the memory area pointed to by s2 to the + area pointed to by s1. If the two areas overlap, behaviour is undefined. + Returns the value of s1. +*/ +extern void* _FUNC(memcpy)(void* s1, const void* s2, size_t n); + +/* Copy a number of n characters from the memory area pointed to by s2 to the + area pointed to by s1. The two areas may overlap. + Returns the value of s1. +*/ +extern void* memmove(void* s1, const void* s2, size_t n); + +/* Copy the character array s2 (including terminating '\0' byte) into the + character array s1. + Returns the value of s1. +*/ +extern char* _FUNC(strcpy)(char* s1, const char* s2); + +/* Copy a maximum of n characters from the character array s2 into the character + array s1. If s2 is shorter than n characters, '\0' bytes will be appended to + the copy in s1 until n characters have been written. If s2 is longer than n + characters, NO terminating '\0' will be written to s1. If the arrays overlap, + behaviour is undefined. + Returns the value of s1. +*/ +extern char* _FUNC(strncpy)(char* s1, const char* s2, size_t n); + +/* Concatenation functions */ + +/* Append the contents of the character array s2 (including terminating '\0') to + the character array s1 (first character of s2 overwriting the '\0' of s1). If + the arrays overlap, behaviour is undefined. + Returns the value of s1. +*/ +extern char* _FUNC(strcat)(char* s1, const char* s2); + +/* Append a maximum of n characters from the character array s2 to the character + array s1 (first character of s2 overwriting the '\0' of s1). A terminating + '\0' is ALWAYS appended, even if the full n characters have already been + written. If the arrays overlap, behaviour is undefined. + Returns the value of s1. +*/ +extern char* _FUNC(strncat)(char* s1, const char* s2, size_t n); + +/* Comparison functions */ + +/* Compare the first n characters of the memory areas pointed to by s1 and s2. + Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if + s1 > s2. +*/ +extern int _FUNC(memcmp)(const void * s1, const void* s2, size_t n); + +/* Compare the character arrays s1 and s2. + Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if + s1 > s2. +*/ +extern int _FUNC(strcmp)(const char * s1, const char* s2); + +/* Compare the character arrays s1 and s2, interpreted as specified by the + LC_COLLATE category of the current locale. + Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if + s1 > s2. + TODO: Currently a dummy wrapper for strcmp() as PDCLib does not yet support + locales. +*/ +extern int _FUNC(strcoll)(const char* s1, const char* s2); + +/* Compare no more than the first n characters of the character arrays s1 and + s2. + Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if + s1 > s2. +*/ +extern int _FUNC(strncmp)(const char* s1, const char* s2, size_t n); + +/* Transform the character array s2 as appropriate for the LC_COLLATE setting of + the current locale. If length of resulting string is less than n, store it in + the character array pointed to by s1. Return the length of the resulting + string. +*/ +extern size_t _FUNC(strxfrm)(char* s1, const char* s2, size_t n); + +/* Search functions */ + +/* Search the first n characters in the memory area pointed to by s for the + character c (interpreted as unsigned char). + Returns a pointer to the first instance found, or NULL. +*/ +extern void* _FUNC(memchr)(const void* s, int c, size_t n); + +/* Search the character array s (including terminating '\0') for the character c + (interpreted as char). + Returns a pointer to the first instance found, or NULL. +*/ +extern char* _FUNC(strchr)(const char* s, int c); + +/* Determine the length of the initial substring of character array s1 which + consists only of characters not from the character array s2. + Returns the length of that substring. +*/ +extern size_t _FUNC(strcspn)(const char* s1, const char* s2); + +/* Search the character array s1 for any character from the character array s2. + Returns a pointer to the first occurrence, or NULL. +*/ +extern char* _FUNC(strpbrk)(const char* s1, const char* s2); + +/* Search the character array s (including terminating '\0') for the character c + (interpreted as char). + Returns a pointer to the last instance found, or NULL. +*/ +extern char* _FUNC(strrchr)(const char * s, int c ); + +/* Determine the length of the initial substring of character array s1 which + consists only of characters from the character array s2. + Returns the length of that substring. +*/ +extern size_t _FUNC(strspn)(const char * s1, const char * s2); + +/* Search the character array s1 for the substring in character array s2. + Returns a pointer to that sbstring, or NULL. If s2 is of length zero, + returns s1. +*/ +extern char* _FUNC(strstr)(const char * s1, const char * s2); + +/* In a series of subsequent calls, parse a C string into tokens. + On the first call to strtok(), the first argument is a pointer to the to-be- + parsed C string. On subsequent calls, the first argument is NULL unless you + want to start parsing a new string. s2 holds an array of separator characters + which can differ from call to call. Leading separators are skipped, the first + trailing separator overwritten with '\0'. + Returns a pointer to the next token. + WARNING: This function uses static storage, and as such is not reentrant. +*/ +extern char* _FUNC(strtok)(char* s1, const char* s2); + +/* Miscellaneous functions */ + +/* Write the character c (interpreted as unsigned char) to the first n + characters of the memory area pointed to by s. + Returns s. +*/ +extern void* _FUNC(memset)(void* s, int c, size_t n); + +/* Map an error number to a (locale-specific) error message string. Error + numbers are typically errno values, but any number is mapped to a message. + TODO: PDCLib does not yet support locales. +*/ +extern char* _FUNC(strerror)(int errnum); + +/* Returns the length of the string s (excluding terminating '\0').*/ +extern size_t _FUNC(strlen)(const char * s); + +/* The function reverses the sequence of characters in the string pointed to by str. */ +extern char* _FUNC(strrev)(char *str); + +/* The strdup function executes the function pointed to by the str argument. */ +extern char* _FUNC(strdup)(const char *str); + +#endif diff --git a/programs/develop/libraries/kolibri-libc/include/sys/dirent.h b/programs/develop/libraries/kolibri-libc/include/sys/dirent.h new file mode 100644 index 0000000000..584adbea1c --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/sys/dirent.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#ifndef _DIRENT_H_ +#define _DIRENT_H_ + +#include +#include + +#define IS_FOLDER 16 +#define IS_FILE 0 + +typedef unsigned ino_t; + +struct dirent{ + ino_t d_ino; //File serial number. + char d_name[PATH_MAX]; // Name of entry. + unsigned d_type; +}; + +typedef struct{ + struct dirent* objs; + ino_t pos; + ino_t num_objs; +}DIR; + + +int _FUNC(closedir)(DIR *dir); +DIR* _FUNC(opendir)(const char *path); +struct dirent* _FUNC(readdir)(DIR *); +void _FUNC(rewinddir)(DIR *dir); +void _FUNC(seekdir)(DIR *dir, unsigned pos); +unsigned _FUNC(telldir)(DIR *dir); + +#endif // _DIRENT_H_ \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/include/sys/ksys.h b/programs/develop/libraries/kolibri-libc/include/sys/ksys.h new file mode 100644 index 0000000000..88f23db9a3 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/sys/ksys.h @@ -0,0 +1,1006 @@ +#ifndef _KSYS_H_ +#define _KSYS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define asm_inline __asm__ __volatile__ + +#define KSYS_FS_ERR_SUCCESS 0 // Success +#define KSYS_FS_ERR_1 1 // Base and/or partition of a hard disk is not defined (fn21.7 & fn21.8) +#define KSYS_FS_ERR_2 2 // Function is not supported for the given file system +#define KSYS_FS_ERR_3 3 // Unknown file system +#define KSYS_FS_ERR_4 4 // Reserved, is never returned in the current implementation +#define KSYS_FS_ERR_5 5 // File not found +#define KSYS_FS_ERR_EOF 6 // End of file, EOF +#define KSYS_FS_ERR_7 7 // Pointer lies outside of application memory +#define KSYS_FS_ERR_8 8 // Disk is full +#define KSYS_FS_ERR_9 9 // FAT table is destroyed +#define KSYS_FS_ERR_10 10 // Access denied +#define KSYS_FS_ERR_11 11 // Device error + +typedef void ksys_panic(char *func_name); + +typedef struct { + unsigned char blue; + unsigned char green; + unsigned char red; +}rgb_t; + +#pragma pack(push,1) +typedef union{ + unsigned val; + struct{ + short x; + short y; + }; +}ksys_pos_t; + +typedef union ksys_oskey_t{ + unsigned val; + struct{ + unsigned char state; + unsigned char code; + unsigned char ctrl_key; + }; +}ksys_oskey_t; + +typedef struct{ + unsigned handle; + unsigned io_code; + unsigned *input; + int inp_size; + void *output; + int out_size; +}ksys_ioctl_t; + +typedef struct{ + void *data; + size_t size; +}ksys_ufile_t; + + +typedef struct{ + unsigned p00; + union{ + uint64_t p04; + struct { + unsigned p04dw; + unsigned p08dw; + }; + }; + unsigned p12; + union { + unsigned p16; + const char *new_name; + void *bdfe; + void *buf16; + const void *cbuf16; + }; + char p20; + const char *p21; +}ksys70_t; + + +typedef struct { + unsigned attributes; + unsigned name_cp; + char creation_time[4]; + char creation_date[4]; + char last_access_time[4]; + char last_access_date[4]; + char last_modification_time[4]; + char last_modification_date[4]; + unsigned long long size; + char name[0]; +}ksys_bdfe_t; + +typedef struct { + int cpu_usage; //+0 + int window_pos_info; //+4 + short int reserved1; //+8 + char name[12]; //+10 + int memstart; //+22 + int memused; //+26 + int pid; //+30 + int winx_start; //+34 + int winy_start; //+38 + int winx_size; //+42 + int winy_size; //+46 + short int slot_info; //+50 + short int reserved2; //+52 + int clientx; //+54 + int clienty; //+58 + int clientwidth; //+62 + int clientheight; //+66 + unsigned char window_state;//+70 + char reserved3[1024-71]; //+71 +}ksys_proc_table_t; + +typedef unsigned int ksys_color_t; + +typedef struct{ + ksys_color_t frame_area; + ksys_color_t grab_bar; + ksys_color_t grab_bar_button; + ksys_color_t grab_button_text; + ksys_color_t grab_text; + ksys_color_t work_area; + ksys_color_t work_button; + ksys_color_t work_button_text; + ksys_color_t work_text; + ksys_color_t work_graph; +}ksys_colors_table_t; + +typedef struct{ + unsigned pid; // PID of sending thread + unsigned datalen; // data bytes + char *data; // data begin +}ksys_ipc_msg; + +typedef struct{ + unsigned lock; // nonzero is locked + unsigned used; // used bytes in buffer + ksys_ipc_msg *data; // data begin +}ksys_ipc_buffer; + +typedef struct { + char* func_name; + void* func_ptr; +}ksys_coff_etable_t; + +#pragma pack(pop) + +enum KSYS_EVENTS { + KSYS_EVENT_NONE = 0, /* Event queue is empty */ + KSYS_EVENT_REDRAW = 1, /* Window and window elements should be redrawn */ + KSYS_EVENT_KEY = 2, /* A key on the keyboard was pressed */ + KSYS_EVENT_BUTTON = 3, /* A button was clicked with the mouse */ + KSYS_EVENT_DESKTOP = 5, /* Desktop redraw finished */ + KSYS_EVENT_MOUSE = 6, /* Mouse activity (movement, button press) was detected */ + KSYS_EVENT_IPC = 7, /* Interprocess communication notify */ + KSYS_EVENT_NETWORK = 8, /* Network event */ + KSYS_EVENT_DEBUG = 9, /* Debug subsystem event */ + KSYS_EVENT_IRQBEGIN = 16 /* 16..31 IRQ0..IRQ15 interrupt =IRQBEGIN+IRQn */ +}; + +enum KSYS_FILE_ENCODING{ + KSYS_FILE_CP866 =1, + KSYS_FILE_UTF16LE = 2, + KSYS_FILE_UTF8 = 3 +}; + +enum KSYS_CLIP_ENCODING{ + KSYS_CLIP_UTF8 = 0, + KSYS_CLIP_CP866 = 1, + KSYS_CLIP_CP1251 = 2 +}; + +enum KSYS_CLIP_TYPES{ + KSYS_CLIP_TEXT = 0, + KSYS_CLIP_IMAGE = 1, + KSYS_CLIP_RAW = 2 +}; + +enum KSYS_MOUSE_POS{ + KSYS_MOUSE_SCREEN_POS = 0, + KSYS_MOUSE_WINDOW_POS = 1 +}; + +enum KSYS_SHM_MODE{ + KSYS_SHM_OPEN = 0x00, + KSYS_SHM_OPEN_ALWAYS = 0x04, + KSYS_SHM_CREATE = 0x08, + KSYS_SHM_READ = 0x00, + KSYS_SHM_WRITE = 0x01, +}; + +static inline +int _ksys_strcmp(const char * s1, const char * s2 ) +{ + while ((*s1) && (*s1 == *s2)){ ++s1; ++s2; } + return(*(unsigned char*)s1 - *(unsigned char *)s2); +} + +// Functions for working with the graphical interface + +static inline +void _ksys_start_draw() +{ + asm_inline("int $0x40"::"a"(12),"b"(1)); +} + +static inline +void _ksys_end_draw() +{ + asm_inline("int $0x40" ::"a"(12),"b"(2)); +} + +static inline +void _ksys_create_window(int x, int y, int w, int h, const char *name, ksys_color_t workcolor, unsigned style) +{ + asm_inline( + "int $0x40" + ::"a"(0), + "b"((x << 16) | ((w-1) & 0xFFFF)), + "c"((y << 16) | ((h-1) & 0xFFFF)), + "d"((style << 24) | (workcolor & 0xFFFFFF)), + "D"(name), + "S"(0) + :"memory" + ); +}; + +static inline +void _ksys_change_window(int new_x, int new_y, int new_w, int new_h) +{ + asm_inline( + "int $0x40" + ::"a"(67), "b"(new_x), "c"(new_y), "d"(new_w),"S"(new_h) + ); +} + +static inline +void _ksys_define_button(unsigned x, unsigned y, unsigned w, unsigned h, unsigned id, ksys_color_t color) +{ + asm_inline( + "int $0x40" + ::"a"(8), + "b"((x<<16)+w), + "c"((y<<16)+h), + "d"(id), + "S"(color) + ); +}; + +static inline +void _ksys_draw_line(int xs, int ys, int xe, int ye, ksys_color_t color) +{ + asm_inline( + "int $0x40" + ::"a"(38), "d"(color), + "b"((xs << 16) | xe), + "c"((ys << 16) | ye) + ); +} + +static inline +void _ksys_draw_bar(int x, int y, int w, int h, ksys_color_t color) +{ + asm_inline( + "int $0x40" + ::"a"(13), "d"(color), + "b"((x << 16) | w), + "c"((y << 16) | h) + ); +} + +static inline +void _ksys_draw_bitmap(void *bitmap, int x, int y, int w, int h) +{ + asm_inline( + "int $0x40" + ::"a"(7), "b"(bitmap), + "c"((w << 16) | h), + "d"((x << 16) | y) + :"memory" + ); +} + +static inline +void _ksys_draw_text(const char *text, int x, int y, int len, ksys_color_t color) +{ + asm_inline( + "int $0x40" + ::"a"(4),"d"(text), + "b"((x << 16) | y), + "S"(len),"c"(color) + :"memory" + ); +} + +static inline +void _ksys_draw_text_bg(const char *text, int x, int y, int len, ksys_color_t color, ksys_color_t bg) +{ + asm_inline( + "int $0x40" + ::"a"(4),"d"(text), + "b"((x << 16) | y), + "S"(len),"c"(color), "D"(bg) + :"memory" + ); +} + +static inline +void _ksys_draw_number(int number, int x, int y, int len, ksys_color_t color){ + unsigned fmt; + fmt = len << 16 | 0x80000000; // no leading zeros + width + asm_inline( + "int $0x40" + ::"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color) + ); +} + +static inline +void _ksys_draw_number_bg(unsigned number, int x, int y, int len, ksys_color_t color, ksys_color_t bg){ + unsigned fmt; + fmt = len << 16 | 0x80000000; // no leading zeros + width + asm_inline( + "int $0x40" + ::"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color), "D"(bg) + ); +} + +static inline +unsigned _ksys_get_skin_height() +{ + unsigned height; + asm_inline( + "int $0x40 \n\t" + :"=a"(height) + :"a"(48),"b"(4) + ); + return height; +} + +static inline +void _ksys_get_colors(ksys_colors_table_t *color_table) +{ + asm_inline( + "int $0x40" + ::"a"(48),"b"(3),"c"(color_table),"d"(40) + ); +} + +/* Functions for working with a screen. */ + +static inline +ksys_pos_t _ksys_screen_size() +{ + ksys_pos_t size; + ksys_pos_t size_tmp; + asm_inline( + "int $0x40" + :"=a"(size_tmp) + :"a"(14) + ); + size.x = size_tmp.y; + size.y = size_tmp.x; + return size; +} + + +/* Functions for working with a mouse and cursors. */ + +static inline +ksys_pos_t _ksys_get_mouse_pos(int origin) +{ + ksys_pos_t pos; + asm_inline( + "int $0x40 \n\t" + "rol $16, %%eax" + :"=a"(pos) + :"a"(37),"b"(origin) + ); + return pos; +} + +static inline +unsigned _ksys_get_mouse_buttons() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(37),"b"(2) + ); + return val; +} + +static inline +unsigned _ksys_get_mouse_wheels() +{ + unsigned val; + asm_inline( + "int $0x40 \n\t" + :"=a"(val) + :"a"(37),"b"(7) + ); + return val; +} + +static inline +unsigned _ksys_load_cursor(void *path, unsigned flags) +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(37), "b"(4), "c"(path), "d"(flags) + :"memory" + ); + return val; +} + +static inline +unsigned _ksys_set_cursor(unsigned cursor) +{ + unsigned old; + asm_inline( + "int $0x40" + :"=a"(old) + :"a"(37), "b"(5), "c"(cursor) + ); + return old; +} + +static inline +int _ksys_destroy_cursor(unsigned cursor) +{ + int ret; + asm_inline( + "int $0x40" + :"=a"(ret) + :"a"(37), "b"(6), "c"(cursor) + :"memory" + ); + return ret; +} + +static inline +unsigned _ksys_get_mouse_eventstate() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(37),"b"(3) + ); + return val; +} + + +/* Functions for working with events and buttons. */ + +static inline +unsigned _ksys_set_event_mask(unsigned mask) +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(40), "b"(mask) + ); + return val; +} + +static inline +unsigned _ksys_wait_event(unsigned time) +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(23), "b"(time) + ); + return val; +} + +static inline +unsigned _ksys_check_event() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(11) + ); + return val; +} + +static inline +unsigned _ksys_get_event() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(10) + ); + return val; +} + +static inline +unsigned _ksys_get_button() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(17) + ); + return val>>8; +} + +static inline +ksys_oskey_t _ksys_get_key(void) +{ + ksys_oskey_t val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(2) + ); + return val; +} + +/* Functions for working with the clipboard */ + +static inline +int _ksys_clip_num() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(54), "b"(0) + ); + return val; +} + +static inline +char* _ksys_clip_get(int n) // returned buffer must be freed by _ksys_free() +{ + char* val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(54), "b"(1), "c"(n) + ); + return val; +} + +static inline +int _ksys_clip_set(int n, char *buffer) +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(54), "b"(2), "c"(n), "d"(buffer) + :"memory" + ); + return val; +} + +static inline +int _ksys_clip_pop() +{ + unsigned val; + asm_inline ( + "int $0x40" + :"=a"(val) + :"a"(54), "b"(3) + ); + return val; +} + +static inline +int _ksys_clip_unlock() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(54), "b"(4) + ); + return val; +} + + +/* Working with time */ + +static inline +unsigned _ksys_get_tick_count() +{ + unsigned val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(26),"b"(9) + ); + return val; +} + +static inline +uint64_t _ksys_get_ns_count() +{ + uint64_t val; + asm_inline( + "int $0x40" + :"=A"(val) + :"a"(26), "b"(10) + ); + return val; +} + +static inline +void _ksys_delay(unsigned time) +{ + asm_inline( + "int $0x40" + ::"a"(5), "b"(time) + :"memory" + ); +} + +static inline +unsigned _ksys_get_date() +{ + unsigned val; + asm_inline("int $0x40":"=a"(val):"a"(29)); + return val; +} + +static inline +unsigned _ksys_get_clock() +{ + unsigned val; + asm_inline("int $0x40":"=a"(val):"a"(3)); + return val; +} + + +/* Working with memory allocation */ + +static inline +void* _ksys_alloc(size_t size){ + void *val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(12),"c"(size) + ); + return val; +} + +static inline +int _ksys_free(void *mem) +{ + int val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(13),"c"(mem) + ); + return val; +} + +static inline +void* _ksys_realloc(void *mem, size_t size) +{ + void *val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(20),"c"(size),"d"(mem) + :"memory" + ); + return val; +} + +static inline +int* _ksys_unmap(void *base, size_t offset, size_t size) +{ + int *val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size) + ); + return val; +} + + +/* Loading the dynamic coff library */ + +static inline +ksys_coff_etable_t* _ksys_load_coff(const char* path) +{ + ksys_coff_etable_t *table; + asm_inline( + "int $0x40" + :"=a"(table) + :"a"(68),"b"(19), "c"(path) + :"memory" + ); + return table; +} + +static inline +void* _ksys_get_coff_func(ksys_coff_etable_t *table, const char* fun_name, ksys_panic* panic) +{ + unsigned i=0; + while (1){ + if (NULL == (table+i)->func_name){ + break; + }else{ + if (!_ksys_strcmp(fun_name, (table+i)->func_name)){ + return (table+i)->func_ptr; + } + } + i++; + } + panic((char*)fun_name); + return NULL; +} + + +/* Debug board functions */ + +static inline +void _ksys_debug_putc(char c) +{ + asm_inline("int $0x40"::"a"(63), "b"(1), "c"(c)); +} + +static inline +void _ksys_debug_puts(char *s) +{ + unsigned i=0; + while (*(s+i)){ + asm_inline ("int $0x40"::"a"(63), "b"(1), "c"(*(s+i))); + i++; + } +} + + +/* Working with threads and process */ + +static inline +int _ksys_start_thread(void* proc, char* stack_top) +{ + int val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(51), "b"(1), "c"(proc), "d"(stack_top) + ); + return val; +} + +static inline +void _ksys_focus_window(int slot){ + asm_inline( + "int $0x40" + ::"a"(18), "b"(3), "c"(slot) + ); +} + +static inline +int _ksys_get_thread_slot(int tid){ + int val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(18), "b"(21), "c"(tid) + ); + return val; +} + +static inline +int _ksys_process_info(ksys_proc_table_t* table, int pid) +{ + int val; + asm_inline( + "int $0x40" + :"=a"(val) + :"a"(9), "b"(table), "c"(pid) + :"memory" + ); + return val; +} + +static inline +void _ksys_exit() +{ + asm_inline("int $0x40"::"a"(-1)); +} + + +/* Working with files and directories */ + +static inline +void _ksys_setcwd(char* dir){ + asm_inline( + "int $0x40" + ::"a"(30), "b"(1), "c"(dir) + ); +} + +static inline +int _ksys_getcwd(char* buf, int bufsize){ + register int val; + asm_inline( + "int $0x40" + :"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize) + ); + return val; +} + +static inline +ksys_ufile_t _ksys_load_file(const char *path) +{ + ksys_ufile_t uf; + asm_inline( + "int $0x40" + :"=a"(uf.data), "=d"(uf.size) + :"a"(68), "b"(27),"c"(path) + :"memory" + ); + return uf; +} + +static inline +ksys_ufile_t _ksys_load_file_enc(const char *path, unsigned file_encoding) +{ + ksys_ufile_t uf; + asm_inline( + "int $0x40" + :"=a"(uf.data), "=d"(uf.size) + :"a"(68), "b"(28),"c"(path), "d"(file_encoding) + :"memory" + ); + return uf; +} + +static inline +int _ksys_work_files(const ksys70_t *k) +{ + int status; + asm_inline( + "int $0x40" + :"=a"(status) + :"a"(70), "b"(k) + :"memory" + ); + return status; +} + +static inline +int _ksys_file_read_file(const char *name, unsigned long long offset, unsigned size, void *buf, unsigned *bytes_read) +{ + ksys70_t k; + k.p00 = 0; + k.p04 = offset; + k.p12 = size; + k.buf16 = buf; + k.p20 = 0; + k.p21 = name; + int status; + unsigned bytes_read_v; + _ksys_work_files(&k); + if (!status) { + *bytes_read = bytes_read_v; + } + return status; +} + +static inline +int _ksys_file_write_file(const char *name, unsigned long long offset, unsigned size, const void *buf, unsigned *bytes_written) +{ + ksys70_t k; + k.p00 = 3; + k.p04 = offset; + k.p12 = size; + k.cbuf16 = buf; + k.p20 = 0; + k.p21 = name; + int status; + unsigned bytes_written_v; + asm_inline( + "int $0x40" + :"=a"(status), "=b"(bytes_written_v) + :"a"(70), "b"(&k) + :"memory" + ); + if (!status) { + *bytes_written = bytes_written_v; + } + return status; +} + +static inline +int _ksys_file_create(const char* name){ + ksys70_t k; + k.p00 = 2; + k.p12 = 0; + k.p21 = name; + return _ksys_work_files(&k); +} + +static inline +int _ksys_file_get_info(const char *name, ksys_bdfe_t *bdfe) +{ + ksys70_t k; + k.p00 = 5; + k.bdfe = bdfe; + k.p20 = 0; + k.p21 = name; + return _ksys_work_files(&k); +} + +static inline +int _ksys_file_delete(const char *name) +{ + ksys70_t k; + k.p00 = 8; + k.p20 = 0; + k.p21 = name; + return _ksys_work_files(&k); +} + +static inline +int _ksys_file_rename(const char *name, const char *new_name) +{ + ksys70_t k; + k.p00 = 10; + k.new_name = new_name; + k.p20 = 0; + k.p21 = name; + return _ksys_work_files(&k); +} + + +static inline +int _ksys_exec(char *app_name, char *args) +{ + ksys70_t file_opt; + file_opt.p00 = 7; + file_opt.p04dw = 0; + file_opt.p08dw = (unsigned)args; + file_opt.p21 = app_name; + return _ksys_work_files(&file_opt); +} + +static inline +int _ksys_mkdir(const char *path) +{ + ksys70_t dir_opt; + dir_opt.p00 = 9; + dir_opt.p21 = path; + return _ksys_work_files(&dir_opt); +} + +/* Working with a named shared memory area. */ + +static inline +int _ksys_shm_open(char *name, int mode, int size, char **new_shm) +{ + int error; + asm_inline( + "int $0x40" + :"=a"(*new_shm), "=d"(error) + :"a"(68), "b"(22), "c"(name), "d"(size), "S"(mode) + ); + return error; +} + + +static inline +void _ksys_shm_close(char *shm_name) +{ + asm_inline( + "int $0x40": + :"a"(68), "b"(23), "c"(shm_name) + ); +} + +#ifdef __cplusplus +} +#endif + +#endif // _KSYS_H_ diff --git a/programs/develop/libraries/kolibri-libc/include/sys/socket.h b/programs/develop/libraries/kolibri-libc/include/sys/socket.h new file mode 100644 index 0000000000..ad25469785 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/sys/socket.h @@ -0,0 +1,244 @@ +/* Copyright (C) 2019-2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#ifndef _SOCKET_H_ +#define _SOCKET_H_ + +#include +#include +#include + +// Socket Types +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +// IP protocols +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_RAW 255 + +// IP options +#define IP_TTL 2 + +// Address families +#define AF_UNSPEC 0 +#define AF_LOCAL 1 +#define AF_INET 2 // Default INET=IPv4 +#define AF_INET4 2 // IPv4 +#define AF_INET6 10 // IPv6 + +#define PF_UNSPEC AF_UNSPEC +#define PF_LOCAL AF_LOCAL +#define PF_INET4 AF_INET4 +#define PF_INET6 AF_INET6 + +// internal definition +#define AI_SUPPORTED 0x40F + +// for system function 76 +#define API_ETH (0<<16) +#define API_IPv4 (1<<16) +#define API_ICMP (2<<16) +#define API_UDP (3<<16) +#define API_TCP (4<<16) +#define API_ARP (5<<16) +#define API_PPPOE (6<<16) + +// Socket flags for user calls +#define MSG_NOFLAG 0 +#define MSG_PEEK 0x02 +#define MSG_DONTWAIT 0x40 + +// Socket levels +#define SOL_SOCKET 0xffff + +//Socket options +#define SO_BINDTODEVICE (1<<9) +#define SO_NONBLOCK (1<<31) + +#define PORT(X) (X<<8) + +#pragma pack(push,1) +struct sockaddr{ + unsigned short sin_family; + unsigned short sin_port; + unsigned int sin_addr; + unsigned long long sin_zero; +}; + +typedef struct{ + unsigned int level; + unsigned int optionname; + unsigned int optlenght; + unsigned char options; +}optstruct; +#pragma pack(pop) + +static inline +void _conv_socket_err(){ + switch(errno){ + case 1: errno = ENOBUFS; break; + case 2: errno = EINPROGRESS; break; + case 4: errno = EOPNOTSUPP; break; + case 6: errno = EWOULDBLOCK; break; + case 9: errno = ENOTCONN; break; + case 10: errno = EALREADY; break; + case 11: errno = EINVAL; break; + case 12: errno = EMSGSIZE; break; + case 18: errno = ENOMEM; break; + case 20: errno = EADDRINUSE; break; + case 61: errno = ECONNREFUSED; break; + case 52: errno = ECONNRESET; break; + case 56: errno = EISCONN; break; + case 60: errno = ETIMEDOUT; break; + case 54: errno = ECONNABORTED; break; + default: errno = 0; break; + } +} + +static inline +int socket(int domain, int type, int protocol) +{ + int socket; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(socket) + :"a"(75), "b"(0), "c"(domain), "d"(type), "S"(protocol) + ); + _conv_socket_err(); + return socket; +} + +static inline +int close(int socket) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(1), "c"(socket) + ); + _conv_socket_err(); + return status; +} + +static inline +int bind(int socket, const struct sockaddr *addres, int addres_len) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(2), "c"(socket), "d"(addres), "S"(addres_len) + ); + _conv_socket_err(); + return status; +} + +static inline +int listen(int socket, int backlog) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(3), "c"(socket), "d"(backlog) + ); + _conv_socket_err(); + return status; +} + +static inline +int connect(int socket, const struct sockaddr* address, int socket_len) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(4), "c"(socket), "d"(address), "S"(socket_len) + ); + _conv_socket_err(); + return status; +} + +static inline int +accept(int socket, const struct sockaddr *address, int address_len) +{ + int new_socket; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(new_socket) + :"a"(75), "b"(5), "c"(socket), "d"(address), "S"(address_len) + ); + _conv_socket_err(); + return new_socket; +} + +static inline +int send(int socket, const void *message, size_t msg_len, int flag) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(6), "c"(socket), "d"(message), "S"(msg_len), "D"(flag) + ); + _conv_socket_err(); + return status; +} + +static inline +int recv(int socket, void *buffer, size_t buff_len, int flag) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(7), "c"(socket), "d"(buffer), "S"(buff_len), "D"(flag) + ); + _conv_socket_err(); + return status; +} + +static inline +int setsockopt(int socket,const optstruct* opt) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(8), "c"(socket),"d"(opt) + ); + _conv_socket_err(); + return status; +} + +static inline +int getsockopt(int socket, optstruct* opt) +{ + int status; + asm_inline( + "int $0x40" + :"=b"(errno), "=a"(status) + :"a"(75), "b"(9), "c"(socket),"d"(opt) + ); + _conv_socket_err(); + return status; +} + +static inline +int socketpair(int *socket1, int *socket2) +{ + asm_inline( + "int $0x40" + :"=b"(*socket2), "=a"(*socket1) + :"a"(75), "b"(10) + ); + errno=*socket2; + _conv_socket_err(); + return *socket1; +} + +#endif //_SOCKET_H_ diff --git a/programs/develop/libraries/kolibri-libc/include/time.h b/programs/develop/libraries/kolibri-libc/include/time.h new file mode 100644 index 0000000000..dbf15294fc --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/include/time.h @@ -0,0 +1,30 @@ +#ifndef _TIME_H_ +#define _TIME_H_ + +#include + +typedef unsigned long int clock_t; +typedef unsigned long int time_t; +#define clock() _ksys_get_clock() +#define CLOCKS_PER_SEC 100 + +struct tm { + int tm_sec; /* seconds after the minute 0-61*/ + int tm_min; /* minutes after the hour 0-59 */ + int tm_hour; /* hours since midnight 0-23 */ + int tm_mday; /* day of the month 1-31 */ + int tm_mon; /* months since January 0-11 */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday 0-6 */ + int tm_yday; /* days since January 1 0-365 */ + int tm_isdst; /* Daylight Saving Time flag */ +}; + +extern time_t _FUNC(mktime)(struct tm * timeptr); +extern time_t _FUNC(time)(time_t* timer); +extern struct tm * _FUNC(localtime)(const time_t * timer); /* non-standard! ignore parameter and return just time now, not generate tm_isdst, tm_yday, tm_wday == -1 */ +extern double _FUNC(difftime)(time_t end, time_t beginning); + +extern struct tm buffertime; + +#endif \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/lib/libc.obj b/programs/develop/libraries/kolibri-libc/lib/libc.obj new file mode 100644 index 0000000000..75375eb7b7 Binary files /dev/null and b/programs/develop/libraries/kolibri-libc/lib/libc.obj differ diff --git a/programs/develop/libraries/kolibri-libc/linuxtools/ExportGen b/programs/develop/libraries/kolibri-libc/linuxtools/ExportGen new file mode 100755 index 0000000000..f74ed05c83 Binary files /dev/null and b/programs/develop/libraries/kolibri-libc/linuxtools/ExportGen differ diff --git a/programs/develop/libraries/kolibri-libc/linuxtools/LoaderBuild b/programs/develop/libraries/kolibri-libc/linuxtools/LoaderBuild new file mode 100755 index 0000000000..6db7102e5c --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/linuxtools/LoaderBuild @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + +AR=ar +FASM=fasm + +set -e + +cd $1 + +echo "Compile ASM files..." + +rm -f *.o +cp __lib__.asm.bak __lib__.asm + +for asm_file in $(find *.asm) +do + $FASM $asm_file >> /dev/null +done + +echo "Create libc.obj.a library..." +ar -rsc ../lib/libc.obj.a *.o +rm -f *.asm *.o +echo "Done!" diff --git a/programs/develop/libraries/kolibri-libc/linuxtools/LoaderGen b/programs/develop/libraries/kolibri-libc/linuxtools/LoaderGen new file mode 100755 index 0000000000..aa77ea19e3 Binary files /dev/null and b/programs/develop/libraries/kolibri-libc/linuxtools/LoaderGen differ diff --git a/programs/develop/libraries/kolibri-libc/linuxtools/src/ExportGen.c b/programs/develop/libraries/kolibri-libc/linuxtools/src/ExportGen.c new file mode 100755 index 0000000000..97078eb9a1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/linuxtools/src/ExportGen.c @@ -0,0 +1,57 @@ +// export_table_gen +// Copyright (C) maxcodehack and turbocat2001, 2021 + +#include +#include + +int main(int argc, char** argv) { + if (argc != 3) { + printf("Usage: %s \n", argv[0]); + return 0; + } + FILE *input, *output; + if ((input = fopen(argv[1], "r")) == NULL) + { + printf("error: file \"%s\" not found\n", argv[1]); + return 1; + } + char buf[10000]; + // Head + strcpy(buf, \ + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n\n" \ + "#include \n\n" \ + "#include \n\n" \ + "ksys_coff_etable_t EXPORTS[] = {\n"); + + // Generate + char symbol[256]; + while(fscanf(input, "%s", symbol) != EOF) { + if(symbol[0]!='!'){ + char temp[256]; + sprintf(temp, "{\"%s\", &%s},\n", symbol, symbol); + strcat(buf, temp); + } + } + strcat(buf, "NULL,\n};"); + fclose(input); + + // Output generated + output = fopen(argv[2], "w"); + if (output == NULL) + { + printf("Unable to write to file: '%s'!\n", argv[2]); + return 1; + } + + fputs(buf, output); + fclose(output); + + printf("Done, check %s!\n", argv[2]); + + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/linuxtools/src/LoaderGen.c b/programs/develop/libraries/kolibri-libc/linuxtools/src/LoaderGen.c new file mode 100644 index 0000000000..3d12b2d611 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/linuxtools/src/LoaderGen.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) { + if(argc!=3){ + printf("Usage: LoadGen \n"); + return 0; + } + argv[2][strlen(argv[1])-2]='\0'; + FILE* symbols_txt = fopen(argv[1], "r"); + if(!symbols_txt){ + fprintf(stderr, "File '%s' not found!\n", argv[1]); + return -1; + } + char line[256]; + while(fgets(line, 256, symbols_txt)) { + if(line[0]!='!'){ + if(line[strlen(line)-1]=='\n'){ + line[strlen(line)-1]='\0'; + } + char asm_name[PATH_MAX]; + sprintf(asm_name, "%s/%s.asm", argv[2], line); + FILE *out = fopen(asm_name, "wb"); + if(!out){ + fprintf(stderr, "Error! File '%s' not created!\n", asm_name); + return -1; + }else{ + printf("File '%s' created successfully!\n", asm_name); + } + + fprintf(out, "format ELF\n"); + fprintf(out, "include \"__lib__.inc\"\n"); + fprintf(out, "fun equ __func@%s\n", line); + fprintf(out, "fun_str equ '%s'\n", line); + fprintf(out, "section '.text'\n"); + fprintf(out, "fun_name db fun_str, 0\n"); + fprintf(out, "section '.data'\n"); + fprintf(out, "extrn lib_name\n"); + fprintf(out, "public fun as fun_str\n"); + fprintf(out, "fun dd fun_name\n"); + fprintf(out, "lib dd lib_name\n"); + + fclose(out); + } + } +} diff --git a/programs/develop/libraries/kolibri-libc/linuxtools/src/Makefile b/programs/develop/libraries/kolibri-libc/linuxtools/src/Makefile new file mode 100644 index 0000000000..6218788b14 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/linuxtools/src/Makefile @@ -0,0 +1,3 @@ +all: + $(CC) ExportGen.c -o ../ExportGen + $(CC) LoaderGen.c -o ../LoaderGen diff --git a/programs/develop/libraries/kolibri-libc/loader/__lib__.asm.bak b/programs/develop/libraries/kolibri-libc/loader/__lib__.asm.bak new file mode 100644 index 0000000000..eac1985673 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/loader/__lib__.asm.bak @@ -0,0 +1,9 @@ +format ELF + +include '__lib__.inc' + +section '.text' + +public lib_name + +lib_name db 0x55, 0xAA, lib_name_str, 0 diff --git a/programs/develop/libraries/kolibri-libc/loader/__lib__.inc b/programs/develop/libraries/kolibri-libc/loader/__lib__.inc new file mode 100644 index 0000000000..15d14f801d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/loader/__lib__.inc @@ -0,0 +1,2 @@ +lib_name equ @libc.obj +lib_name_str equ '/sys/lib/libc.obj' diff --git a/programs/develop/libraries/kolibri-libc/samples/Makefile b/programs/develop/libraries/kolibri-libc/samples/Makefile new file mode 100644 index 0000000000..29243a4b1c --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/Makefile @@ -0,0 +1,23 @@ + +KTCC=../linuxtools/kos32-tcc +KPACK = kpack +CFLAGS = -I../include +LDFLAGS = -nostdlib -L../lib ../lib/crt0.o + +BIN= stdio_test.kex \ +basic_gui.kex \ +http_tcp_demo.kex \ +math_test.kex \ +string_test.kex \ +whois.kex \ +file_io.kex \ + + +all: $(BIN) + +%.kex : %.c + $(KTCC) $(CFLAGS) $(LDFLAGS) $< -o $@ -lnetwork -lc.obj + $(KPACK) --nologo $@ + +clean: + rm *.kex diff --git a/programs/develop/libraries/kolibri-libc/samples/basic_gui.c b/programs/develop/libraries/kolibri-libc/samples/basic_gui.c new file mode 100644 index 0000000000..83ea646d05 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/basic_gui.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include + +ksys_colors_table_t sys_color_table; + +char statusbar[255]; +ksys_proc_table_t proc_info; +char text_line[255]; + +enum BUTTONS +{ + BTN_QUIT = 1, + BTN_POP = 10, + BTN_UNLOCK = 11 +}; + +#define FONT_W 8 +#define FONT_H 14 +#define LINES 10 + +void draw_window() +{ + int win_hight, win_width, i, pos_y = _ksys_get_skin_height() + 36; // 60 == 24+36 + + // start redraw + _ksys_start_draw(); + // define&draw window + _ksys_create_window(10, 40, 600, 400, "My window", sys_color_table.work_area, 0x13); + _ksys_process_info(&proc_info, -1); + + win_width = proc_info.winx_size; + win_hight = proc_info.winy_size; + + _ksys_define_button(10, 30, 70, 20, BTN_POP, sys_color_table.work_button); + _ksys_draw_text("BUTTON1", 15, 34, 0, 0x90000000 | sys_color_table.work_button_text); //0x80000000 asciiz + _ksys_define_button(100, 30, 80, 20, BTN_UNLOCK, sys_color_table.work_button); + _ksys_draw_text("BUTTTON2", 110, 34, 0, 0x90000000 | sys_color_table.work_button_text); + + // display statusbar + _ksys_draw_bar(6, win_hight - 17, win_width - 11, 12, 0x80000000 | sys_color_table.work_area); //0x80000000 gradient + _ksys_draw_text(statusbar, 10, win_hight - 15, 0, 0x80000000 | sys_color_table.work_text); + + // display strings + for (i = LINES; i > 0; i--){ + snprintf (text_line, sizeof text_line, "Line[%d]<>", i); + + text_line[(win_width - 10 - 5) / FONT_W + 1] = '\0'; // clip text size, seems to big lines crashing OS, and form len by window size + _ksys_draw_text(text_line, 5, pos_y, 0, 0x90000000 | sys_color_table.work_text); + pos_y += FONT_H; + + if(pos_y + 29 > win_hight) break; // 12 font + 12 statusbar + 5 border + } + // end redraw + _ksys_end_draw(); +} + +int main() +{ + int gui_event; + uint32_t pressed_button = 0, mouse_button; + ksys_pos_t mouse_pos; + strcpy(statusbar, "Program running...Double click on TEXT for details"); + + _ksys_get_colors(&sys_color_table); + _ksys_set_event_mask(0xC0000027); // mouse events only when focused window and mouse inside + + do{ + gui_event = _ksys_get_event(); + switch(gui_event) + { + case KSYS_EVENT_NONE: + break; + case KSYS_EVENT_REDRAW: + draw_window(); + break; + case KSYS_EVENT_KEY: + break; + case KSYS_EVENT_BUTTON: + pressed_button = _ksys_get_button(); + switch (pressed_button) + { + case BTN_POP: + strcpy(statusbar, "POP pressed...."); + draw_window(); + break; + case BTN_UNLOCK: + strcpy(statusbar, "UNLOCK pressed...."); + draw_window(); + break; + case BTN_QUIT: + return 0; + break; + } + break; + case KSYS_EVENT_MOUSE: + mouse_pos = _ksys_get_mouse_pos(KSYS_MOUSE_WINDOW_POS); // window relative + mouse_button = _ksys_get_mouse_eventstate(); + debug_printf("mouse ev (%d,%d)%x\n", mouse_pos.x, mouse_pos.y, mouse_button); + if (mouse_button & (1<<24)) // double click + { + int n = (mouse_pos.y - 60) / FONT_H; + if (n < 0 || n >= LINES) break; + debug_printf("click on str(%d), clip slot(%d)\n", n, LINES - n - 1); + sprintf(statusbar, "click on str(%d), clip slot(%d)\n", n, LINES - n - 1); + draw_window(); + } + break; + } + } while(1) ; /* End of main activity loop */ + + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/samples/file_io.c b/programs/develop/libraries/kolibri-libc/samples/file_io.c new file mode 100644 index 0000000000..09597041f1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/file_io.c @@ -0,0 +1,43 @@ +#include +#include + +int main(int argc, char **argv) +{ + + int i; + char c; + FILE *f; + FILE *fin; + FILE *fout; + + //write to file + f=fopen("testfile.txt","w"); + + for(i=0;i<50;i++) + { + fputc('1',f); + } + fclose(f); + + //append to file + f=fopen("testfile.txt","a"); + + for(i=0;i<50;i++) + { + fputc('2',f); + } + fclose(f); + + //copy from testfile.txt to copyfile.txt + + fin=fopen("testfile.txt","r"); + fout=fopen("copyfile.txt","w"); +/* + while((c=fgetc(fin))!=EOF) + { + fputc(c,fout); + }*/ + fclose(fin); + fclose(fout); + +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/samples/http_tcp_demo.c b/programs/develop/libraries/kolibri-libc/samples/http_tcp_demo.c new file mode 100644 index 0000000000..0b79b38006 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/http_tcp_demo.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +int errno; + +int main() { + networklib_init(); + + char *host = "kolibrios.org"; + int port = 80; + printf("Connecting to %s on port %d\n", host, port); + struct addrinfo *addr_info; + char port_str[16]; sprintf(port_str, "%d", port); + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 doesnt matter + hints.ai_socktype = SOCK_STREAM; // TCP stream sockets + if (getaddrinfo(host, port_str, 0, &addr_info) != 0) { + printf("Host %s not found!\n", host); + freeaddrinfo(addr_info); + exit(-1); + } + printf("IP address of %s is %s\n", host, inet_ntoa(addr_info->ai_addr->sin_addr)); + //printf("Host port = %d\n", addr_info->ai_addr->sin_port >> 8); + + char request[256]; + sprintf(request, "GET /en/ HTTP/1.1\r\nHost: %s\r\n\r\n", host); + printf("request = %s\n", request); + + int sock = socket(AF_INET4, SOCK_STREAM, IPPROTO_TCP); + + puts("Connecting...\n"); + if (connect(sock, addr_info->ai_addr, addr_info->ai_addrlen) != 0) { + printf("Connection failed, errno = %d\n", errno); + exit(errno); + } + puts("Connected successfully\n"); + + puts("Sending request...\n"); + if (send(sock, request, strlen(request), MSG_NOFLAG) == -1) { + printf("Sending failed, errno = %d\n", errno); + exit(errno); + } + puts("Request sended successfully, waiting for response...\n"); + + char buf[512 + 1]; + if (recv(sock, buf, 512, MSG_NOFLAG) == -1) { + printf("Receive failed, errno = %d\n", errno); + exit(errno); + } + + printf("Response = %s\n", buf); + + freeaddrinfo(addr_info); + + close(sock); + puts("\n goodbye)\n"); + exit(0); +} diff --git a/programs/develop/libraries/kolibri-libc/samples/math_test.c b/programs/develop/libraries/kolibri-libc/samples/math_test.c new file mode 100644 index 0000000000..29bf738270 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/math_test.c @@ -0,0 +1,43 @@ +#include +#include + +int main() +{ + int i; + for (i = 0; i < 20; i++) + { + printf("------------------------------------------------------\n"); +// printf ( "remainder of 5.3 / 2 is %f\n", remainder (5.3,2) ); + // printf ( "remainder of 18.5 / 4.2 is %f\n", remainder (18.5,4.2) ); +//remainder of 5.3 / 2 is -0.700000 +//remainder of 18.5 / 4.2 is 1.700000 + + printf ( "fmod of 5.3 / 2 is %f\n", fmod (5.3,2) ); + printf ( "fmod of 18.5 / 4.2 is %f\n", fmod (18.5,4.2) ); +// fmod of 5.3 / 2 is 1.300000 +// fmod of 18.5 / 4.2 is 1.700000 + + double param, fractpart, intpart, result; + int n; + + param = 3.14159265; + fractpart = modf (param , &intpart); + printf ("%f = %f + %f \n", param, intpart, fractpart); +//3.141593 = 3.000000 + 0.141593 + + param = 0.95; + n = 4; + result = ldexp (param , n); + printf ("%f * 2^%d = %f\n", param, n, result); +//0.950000 * 2^4 = 15.200000 + + param = 8.0; + result = frexp (param , &n); + printf ("%f = %f * 2^%d\n", param, result, n); +//8.000000 = 0.500000 * 2^4 + param = 50; + result = frexp (param , &n); + printf ("%f = %f * 2^%d\n", param, result, n); + + } +} diff --git a/programs/develop/libraries/kolibri-libc/samples/stdio_test.c b/programs/develop/libraries/kolibri-libc/samples/stdio_test.c new file mode 100644 index 0000000000..8ec65a12cc --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/stdio_test.c @@ -0,0 +1,16 @@ +#include +#include +#include + +char* test_string1 = "Hello world!"; + +int main(int argc, char** argv){ + printf("Hello world! = %s\n", test_string1); + printf("345.358980 = %f\n", 345.35898); + printf("345 = %d\n", (int)345.35898); + printf("ff = %x\n", 255); + printf("-1 = %d\n", UINT_MAX); + printf("5A-4B-N$ = %s%c-%u%c-N%c\n", "5", 'A', 4, 'B', '$'); + puts("Done!"); + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/samples/string_test.c b/programs/develop/libraries/kolibri-libc/samples/string_test.c new file mode 100644 index 0000000000..5bf99c36f2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/string_test.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include + +int main(int argc, char** argv){ + char hello1[]="Hello, KolibriOS!"; + char hello2[20]; + memcpy(hello1, hello2, strlen(hello1)); + if(!_ksys_strcmp(hello1, hello2)){ + printf("memcpy: Successfully!\n"); + return 0; + } else{ + printf("memcpy: Failure\n"); + return -1; + } +} diff --git a/programs/develop/libraries/kolibri-libc/samples/whois.c b/programs/develop/libraries/kolibri-libc/samples/whois.c new file mode 100644 index 0000000000..440c328840 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/samples/whois.c @@ -0,0 +1,299 @@ +/* +WHOIS port for KolibriOS (Adapted by turbocat2001). +The main code is taken from the site: +https://www.binarytides.com/whois-client-code-in-c-with-linux-sockets/ +*/ + +#include +int errno; + +#include "sys/ksys.h" +#include +#include +#include +#include +#include + +FILE *out=stdout; + +#ifdef DEBUG +FILE *out=stderr; +#endif + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +#define fprintf fprintf + +void show_help() +{ + puts("Usage: whois [-f ]\n"); + puts(" host Connect to server host"); + puts(" -f file Redirecting output to file\n"); + puts("Example: whois google.com -f my.txt"); +} + +int get_whois_data(char * , char **); +int hostname_to_ip(char * , char *); +int whois_query(char * , char * , char **); +char *str_replace(char *search , char *replace , char *subject ); +char* str_copy(char*); + + +int main(int argc , char *argv[]) +{ + networklib_init(); + char *domain , *data = NULL; + int f_flag=0; + + if(argc==2){ + domain=strdup(argv[1]); + } + + else if(!strcmp(argv[2], "-f") && argc==4){ + domain=strdup(argv[1]); + if((out=fopen(argv[3],"w"))==NULL){ + printf("Error writing to file: '%s' !\n", argv[3]); + exit(0); + } + }else{ + show_help(); + exit(0); + } + if(out==stdout){ + con_set_title("Whois"); + } + get_whois_data(domain , &data); + exit(0); +} + +/* + Get the whois data of a domain +*/ + +int get_whois_data(char *domain , char **data) +{ + char ext[1024] , *pch , *response = NULL , *response_2 = NULL , *wch , *dt; + + //remove "http://" and "www." + domain = str_replace("http://" , "" , domain); + domain = str_replace("www." , "" , domain); + + //get the extension , com , org , edu + dt = strdup(domain); + + if(dt == NULL){ + fprintf(out, "strdup failed"); + } + pch = (char*)strtok(dt , "."); + while(pch != NULL){ + strcpy(ext , pch); + pch = strtok(NULL , "."); + } + // This will tell the whois server for the particular TLD like com , org + if( whois_query("whois.iana.org" , ext , &response) == EXIT_FAILURE){ + fprintf(out, "Whois query failed"); + return 1; + } + fprintf(out, "\n\nResponse is:\n\n"); + fprintf(out, "%s", response); + + // Now analysze the response + pch = strtok(response , "\n"); + while(pch != NULL){ + // Check if whois line + wch = strstr(pch , "whois."); + if(wch != NULL){ + break; + } + + // Next line please + pch = strtok(NULL , "\n"); + } + // Now we have the TLD whois server in wch , query again + //This will provide minimal whois information along with the parent whois server of the specific domain :) + wch = strdup(wch); + free(response); + //This should not be necessary , but segmentation fault without this , why ? + response = NULL; + if(wch != NULL){ + fprintf(out,"\nTLD Whois server is : %s" , wch); + if( whois_query(wch , domain , &response) == EXIT_FAILURE){ + fprintf(out, "Whois query failed\n"); + return EXIT_FAILURE; + } + }else{ + fprintf(out, "\nTLD whois server for %s not found\n" , ext); + return EXIT_SUCCESS; + } + + response_2 = strdup(response); + + // Again search for a whois server in this response. :) + pch = strtok(response , "\n"); + while(pch != NULL){ + // Check if whois line + wch = strstr(pch , "whois."); + if(wch != NULL){ + break; + } + //Next line please + pch = strtok(NULL , "\n"); + } + + /* + If a registrar whois server is found then query it + */ + if(wch){ + // Now we have the registrar whois server , this has the direct full information of the particular domain + // so lets query again + + fprintf(out, "\nRegistrar Whois server is : %s" , wch); + + if( whois_query(wch , domain , &response) == EXIT_FAILURE ){ + fprintf(out, "Whois query failed"); + }else{ + fprintf(out, "\n%s" , response); + } + } + /* + otherwise echo the output from the previous whois result + */ + else{ + fprintf(out, "%s" , response_2); + } + return 0; +} + +/* + Perform a whois query to a server and record the response +*/ +int whois_query(char *server , char *query , char **response) +{ + char ip[32] , message[100] , buffer[1500]; + int sock , read_size , total_size = 0; + int WHOIS_PORT = 43; + struct sockaddr dest; + + sock = socket(AF_INET4 , SOCK_STREAM , IPPROTO_TCP); + + //Prepare connection structures :) + memset(&dest , 0 , sizeof(dest) ); + dest.sin_family = AF_INET; + server = str_copy(server); + + server[strcspn(server, "\r\n")] = '\0'; + fprintf(out, "\nResolving: %s ...\n" , server); + if(hostname_to_ip(server , ip) == EXIT_FAILURE ){ + fprintf(out, "Failed\n"); + return EXIT_FAILURE; + } + + fprintf(out, "Found ip: %s \n" , ip); + dest.sin_addr = inet_addr(ip); + dest.sin_port = PORT(WHOIS_PORT); + +; //Now connect to remote server + if(connect(sock , (const struct sockaddr*) &dest , sizeof(dest)) < 0){ + perror("connect failed"); + perror(strerror(errno)); + return EXIT_FAILURE; + } + + //Now send some data or message + fprintf(out, "\nQuerying for: %s ...\n" , query); + sprintf(message , "%s\r\n" , query); + if( send(sock , message , strlen(message) , 0) < 0){ + perror("send failed"); + return EXIT_FAILURE; + } + + //Now receive the response + while((read_size = recv(sock, buffer, sizeof(buffer), 0))){ + *response = realloc(*response , read_size + total_size); + if(*response == NULL){ + fprintf(out, "realloc failed"); + return EXIT_FAILURE; + } + memcpy(*response + total_size , buffer , read_size); + total_size += read_size; + } + + fprintf(out, "Done\n"); + + *response = realloc(*response , total_size + 1); + *(*response + total_size) = '\0'; + close(sock); + return EXIT_SUCCESS; +} +/* + Get the ip address of a given hostname +*/ +int hostname_to_ip(char *hostname , char *ip) +{ + struct addrinfo *addr_info; + char port_str[16]; sprintf(port_str, "%d", 80); + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 doesnt matter + hints.ai_socktype = SOCK_STREAM; // TCP stream sockets + if (getaddrinfo(hostname, port_str, 0, &addr_info) != 0) { + freeaddrinfo(addr_info); + return EXIT_FAILURE; + }else{ + strcpy(ip, inet_ntoa(addr_info->ai_addr->sin_addr)); + return EXIT_SUCCESS; + } +} +/* + Search and replace a string with another string , in a string +*/ +char *str_replace(char *search , char *replace , char *subject) +{ + char *p = NULL , *old = NULL , *new_subject = NULL ; + int c = 0 , search_size; + + search_size = strlen(search); + + //Count how many occurences + for(p = strstr(subject , search) ; p != NULL ; p = strstr(p + search_size , search)){ + c++; + } + //Final size + c = ( strlen(replace) - search_size )*c + strlen(subject); + + //New subject with new size + new_subject = malloc( c ); + + //Set it to blank + strcpy(new_subject , ""); + + //The start position + old = subject; + + for(p = strstr(subject , search) ; p != NULL ; p = strstr(p + search_size , search)){ + //move ahead and copy some text from original subject , from a certain position + strncpy(new_subject + strlen(new_subject) , old , p - old); + + //move ahead and copy the replacement text + strcpy(new_subject + strlen(new_subject) , replace); + + //The new start position after this search match + old = p + search_size; + } + + //Copy the part after the last search match + strcpy(new_subject + strlen(new_subject) , old); + + return new_subject; +} + +char* str_copy(char *source) +{ + char *copy = malloc(strlen(source) + 1); + + if(copy){ + strcpy(copy, source); + } + return copy; +} diff --git a/programs/develop/libraries/kolibri-libc/source/Makefile b/programs/develop/libraries/kolibri-libc/source/Makefile new file mode 100644 index 0000000000..d6a3fde598 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/Makefile @@ -0,0 +1,23 @@ + +CC=kos32-gcc + +KPACK=kpack +FASM=fasm + +CFLAGS = -c -nostdinc -I../include -DGNUC -D_KOLIBRI_LIBC_OBJ -Os -fno-common -fno-builtin -fno-leading-underscore -fno-pie + +SRC=libc.c +LIB=libc.obj + +all: + $(MAKE) -C ../linuxtools/src + mkdir -p exports ../lib + ../linuxtools/ExportGen symbols.txt exports/exports.c + $(FASM) crt/crt0.asm ../lib/crt0.o + $(CC) $(CFLAGS) $(SRC) -o $(LIB) + $(KPACK) $(LIB) +install: + cp -f ../lib/libc.obj ~/.kex/root/RD/1/LIB + +clean: + rm ../lib/libc.obj diff --git a/programs/develop/libraries/kolibri-libc/source/Tupfile.lua b/programs/develop/libraries/kolibri-libc/source/Tupfile.lua new file mode 100755 index 0000000000..5e8f2e3740 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/Tupfile.lua @@ -0,0 +1,16 @@ +if tup.getconfig("NO_GCC") ~= "" then return end +HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../../../" or tup.getconfig("HELPERDIR") +tup.include(HELPERDIR .. "/use_gcc.lua") + +CFLAGS = " -c -w -nostdinc -DGNUC -D_KOLIBRI_LIBC_OBJ -Os -fno-common -fno-builtin -fno-leading-underscore -fno-pie" +INCLUDES = " -I../include" + +tup.rule("../linuxtools/src/ExportGen.c", "gcc %f -o %o" , "../linuxtools/ExportGen") +tup.rule("../linuxtools/src/LoaderGen.c", "gcc %f -o %o" , "../linuxtools/LoaderGen") + +tup.rule({"symbols.txt",extra_inputs = {"../linuxtools/ExportGen"}}, "../linuxtools/ExportGen %f %o" , "exports/exports.c") + +tup.rule({"libc.c",extra_inputs = {"exports/exports.c"}} , "kos32-gcc" .. CFLAGS .. INCLUDES .. " -o %o %f " .. tup.getconfig("KPACK_CMD"), "../lib/libc.obj") + + + diff --git a/programs/develop/libraries/kolibri-libc/source/crt/config.inc b/programs/develop/libraries/kolibri-libc/source/crt/config.inc new file mode 100644 index 0000000000..dc70bf9760 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/config.inc @@ -0,0 +1 @@ +__CPU_type fix p5 diff --git a/programs/develop/libraries/kolibri-libc/source/crt/crt0.asm b/programs/develop/libraries/kolibri-libc/source/crt/crt0.asm new file mode 100644 index 0000000000..f8004becb7 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/crt0.asm @@ -0,0 +1,253 @@ +format ELF +section '.text' executable +public start +public start as '_start' +;extrn mf_init +extrn main +;include 'debug2.inc' +include 'proc32.inc' +include 'macros.inc' +include 'dll.inc' +__DEBUG__=0 + +;start_: +virtual at 0 + db 'MENUET01' ; 1. Magic number (8 bytes) + dd 0x01 ; 2. Version of executable file + dd start ; 3. Start address +imgsz dd 0x0 ; 4. Size of image + dd 0x100000 ; 5. Size of needed memory + dd 0x100000 ; 6. Pointer to stack +hparams dd 0x0 ; 7. Pointer to program arguments +hpath dd 0x0 ; 8. Pointer to program path +end virtual + +start: +;DEBUGF 'Start programm\n' + ;init heap of memory + mov eax,68 + mov ebx,11 + int 0x40 + + mov [argc], 0 + mov eax, [hparams] + test eax, eax + jz .without_path + mov eax, path + cmp word ptr eax, 32fh ; '/#3' UTF8 + jne .without_path + mov word ptr eax, 12fh ; '/#1' fix to CP866 +.without_path: + mov esi, eax + call push_param +; retrieving parameters + mov esi, params + xor edx, edx ; dl - èä¸ò ïàðàìåòð(1) èëè ðàçäåëèòåëè(0) + ; dh - ñèìâîë ñ êîòîðîãî íà÷àëñÿ ïàðàìåòð (1 êàâû÷êè, 0 îñòàëüíîå) + mov ecx, 1 ; cl = 1 + ; ch = 0 ïðîñòî íîëü +.parse: + lodsb + test al, al + jz .run + test dl, dl + jnz .findendparam + ;{åñëè áûë ðàçäåëèòåëü + cmp al, ' ' + jz .parse ;çàãðóæåí ïðîáåë, ãðóçèì ñëåäóþùèé ñèìâîë + mov dl, cl ;íà÷èíàåòñÿ ïàðàìåòð + cmp al, '"' + jz @f ;çàãðóæåíû êàâû÷êè + mov dh, ch ;ïàðàìåòð áåç êàâû÷åê + dec esi + call push_param + inc esi + jmp .parse + + @@: + mov dh, cl ;ïàðàìåòð â êàâû÷åêàõ + call push_param ;åñëè íå ïðîáåë çíà÷èò íà÷èíàåòñÿ êàêîé òî ïàðàìåòð + jmp .parse ;åñëè áûë ðàçäåëèòåëü} + +.findendparam: + test dh, dh + jz @f ; áåç êàâû÷åê + cmp al, '"' + jz .clear + jmp .parse + @@: + cmp al, ' ' + jnz .parse + +.clear: + lea ebx, [esi - 1] + mov [ebx], ch + mov dl, ch + jmp .parse + +.run: + call load_imports + push argv + push [argc] + call main +.exit: + xor eax,eax + dec eax + int 0x40 + dd -1 +.crash: + jmp .exit +;============================ +push_param: +;============================ +;parameters +; esi - pointer +;description +; procedure increase argc +; and add pointer to array argv +; procedure changes ebx + mov ebx, [argc] + cmp ebx, max_parameters + jae .dont_add + mov [argv+4*ebx], esi + inc [argc] +.dont_add: + ret +;============================== + +;============================== +load_imports: +;============================== +;parameters +; none +;description +; imports must be located at end of image (but before BSS sections) +; the address of end of imports (next byte after imports) is located in imgsz +; look at each import from that address up to illegal import +; legal import is such that: +; first pointer points to procedure name +; and is smaller than imgsz +; second pointer points lo library name, starting with 0x55, 0xAA +; and is smaller than imgsz +; each library should be initialized as appropriate, once +; so as library is initialized, its name will be replaced 0x00 + mov ebx, [imgsz] ; byte after imports +.handle_next_import: + sub ebx, 4 ; ebx = pointer to pointer to library name + mov esi, dword[ebx] ; esi = pointer to library name + push ebx + push esi + call load_library ; eax = pointer to library exports + pop esi + pop ebx + test eax, eax + jz .done + sub ebx, 4 ; ebx = pointer to pointer to symbol name + push ebx + stdcall dll.GetProcAddress, eax, dword[ebx] + pop ebx + test eax, eax + jz .fail + mov dword[ebx], eax + jmp .handle_next_import +.done: + ret +.fail: + ret +;============================== + +;============================== +load_library: +;============================== +;parameters +; ebx: library name address +;description +; each library should be initialized as appropriate, once +; so as library is initialized, its name will be replaced 0x00 +; and 4 next bytes will be set to address of library + ; first two bytes of library name must be 0x55, 0xAA (is like a magic) + cld ; move esi further, not back + cmp esi, [imgsz] + ja .fail + lodsb ; al = first byte of library name + cmp al, 0x55 + jne .fail + lodsb ; al = second byte of library name + cmp al, 0xAA + jne .fail + lodsb ; al = third byte of library name (0x00 if the library is already loaded) + test al, al + jnz .load + lodsd ; if we here, then third byte is 0x00 => address of library is in next 4 bytes + ; now eax contains address of library + ret +.load: + dec esi ; we checked on 0 before, let's go back + mov eax, 68 + mov ebx, 19 + mov ecx, esi + int 0x40 ; eax = address of exports + mov byte[esi], 0 ; library is loaded, let's place 0 in first byte of name + mov [esi + 1], eax ; now next 4 bytes of library name are replaced by address of library + ; call lib_init + stdcall dll.GetProcAddress, eax, lib_init_str ; eax = address of lib_init + test eax, eax + jz .ret + stdcall dll.Init, eax +.ret: + mov eax, [esi + 1] ; put address of library into eax + ret +.fail: + mov eax, 0 + ret + +; ==== memmove for tcc ====== + +proc memmove c, to:dword,from:dword,count:dword + + push esi + push edi + mov ecx,[count] + test ecx,ecx + jz no_copy_block_ + mov esi,[from] + mov edi,[to] + cmp esi, edi + je no_copy_block_ + jg copy_ + add esi, ecx + add edi, ecx + dec esi + dec edi + std +copy_: + rep movsb + cld +no_copy_block_: + + pop edi + pop esi + mov eax,[to] + ret +endp + + +;============================== + +lib_init_str db 'lib_init', 0 + +public argc as '__argc' +public params as '__argv' +public path as '__path' +public memmove + +section '.bss' +buf_len = 0x400 +max_parameters=0x20 +argc rd 1 +argv rd max_parameters +path rb buf_len +params rb buf_len + +;section '.data' +;include_debug_strings ; ALWAYS present in data section diff --git a/programs/develop/libraries/kolibri-libc/source/crt/crt0_tiny.asm b/programs/develop/libraries/kolibri-libc/source/crt/crt0_tiny.asm new file mode 100644 index 0000000000..053216ba06 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/crt0_tiny.asm @@ -0,0 +1,193 @@ +format ELF +section '.text' executable +public start +public start as '_start' +;extrn mf_init +extrn main +include '../../../../programs/proc32.inc' +;include 'debug2.inc' +__DEBUG__=0 + +;start_: +virtual at 0 + db 'MENUET01' ; 1. Magic number (8 bytes) + dd 0x01 ; 2. Version of executable file + dd start ; 3. Start address + dd 0x0 ; 4. Size of image + dd 0x100000 ; 5. Size of needed memory + dd 0x100000 ; 6. Pointer to stack +hparams dd 0x0 ; 7. Pointer to program arguments +hpath dd 0x0 ; 8. Pointer to program path +end virtual + +start: +;DEBUGF 'Start programm\n' + ;init heap of memory + mov eax,68 + mov ebx,11 + int 0x40 + +;DEBUGF ' path "%s"\n params "%s"\n', .path, .params +; check for overflow +;; that not work +; mov al, [path+buf_len-1] +; or al, [params+buf_len-1] +; jnz .crash +; check if path written by OS + mov [argc], 0 + mov eax, [hparams] + test eax, eax + jz .without_path + mov eax, path + cmp word ptr eax, 32fh ; '/#3' UTF8 + jne .without_path + mov word ptr eax, 12fh ; '/#1' fix to CP866 +.without_path: + mov esi, eax + call push_param +; retrieving parameters + mov esi, params + xor edx, edx ; dl - èä¸ò ïàðàìåòð(1) èëè ðàçäåëèòåëè(0) + ; dh - ñèìâîë ñ êîòîðîãî íà÷àëñÿ ïàðàìåòð (1 êàâû÷êè, 0 îñòàëüíîå) + mov ecx, 1 ; cl = 1 + ; ch = 0 ïðîñòî íîëü +.parse: + lodsb + test al, al + jz .run + test dl, dl + jnz .findendparam + ;{åñëè áûë ðàçäåëèòåëü + cmp al, ' ' + jz .parse ;çàãðóæåí ïðîáåë, ãðóçèì ñëåäóþùèé ñèìâîë + mov dl, cl ;íà÷èíàåòñÿ ïàðàìåòð + cmp al, '"' + jz @f ;çàãðóæåíû êàâû÷êè + mov dh, ch ;ïàðàìåòð áåç êàâû÷åê + dec esi + call push_param + inc esi + jmp .parse + + @@: + mov dh, cl ;ïàðàìåòð â êàâû÷åêàõ + call push_param ;åñëè íå ïðîáåë çíà÷èò íà÷èíàåòñÿ êàêîé òî ïàðàìåòð + jmp .parse ;åñëè áûë ðàçäåëèòåëü} + +.findendparam: + test dh, dh + jz @f ; áåç êàâû÷åê + cmp al, '"' + jz .clear + jmp .parse + @@: + cmp al, ' ' + jnz .parse + +.clear: + lea ebx, [esi - 1] + mov [ebx], ch + mov dl, ch + jmp .parse + +.run: +;DEBUGF 'call main(%x, %x) with params:\n', [argc], argv +if __DEBUG__ = 1 + mov ecx, [argc] + @@: + lea esi, [ecx * 4 + argv-4] + DEBUGF '0x%x) "%s"\n', cx, [esi] + loop @b +end if + push argv + push [argc] + call main +.exit: +;DEBUGF 'Exit from prog\n'; + xor eax,eax + dec eax + int 0x40 + dd -1 +.crash: +;DEBUGF 'E:buffer overflowed\n' + jmp .exit +;============================ +push_param: +;============================ +;parameters +; esi - pointer +;description +; procedure increase argc +; and add pointer to array argv +; procedure changes ebx + mov ebx, [argc] + cmp ebx, max_parameters + jae .dont_add + mov [argv+4*ebx], esi + inc [argc] +.dont_add: + ret + +proc memcpy c, to:dword,from:dword,count:dword + push esi + push edi + mov ecx,[count] + test ecx,ecx + jz no_copy_block + mov esi,[from] + mov edi,[to] + cld + rep movsb +no_copy_block: + + pop edi + pop esi + mov eax, [to] + ret +endp + +proc memmove c, to:dword,from:dword,count:dword + + push esi + push edi + mov ecx,[count] + test ecx,ecx + jz no_copy_block_ + mov esi,[from] + mov edi,[to] + cmp esi, edi + je no_copy_block_ + jg copy_ + add esi, ecx + add edi, ecx + dec esi + dec edi + std +copy_: + rep movsb + cld +no_copy_block_: + + pop edi + pop esi + mov eax,[to] + ret +endp + +;============================== +public argc as '__argc' +public params as '__argv' +public path as '__path' +public memcpy +public memmove + +section '.bss' +buf_len = 0x400 +max_parameters=0x20 +argc rd 1 +argv rd max_parameters +path rb buf_len +params rb buf_len + +;section '.data' +;include_debug_strings ; ALWAYS present in data section diff --git a/programs/develop/libraries/kolibri-libc/source/crt/dll.inc b/programs/develop/libraries/kolibri-libc/source/crt/dll.inc new file mode 100644 index 0000000000..151c374e7b --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/dll.inc @@ -0,0 +1,158 @@ +;----------------------------------------------------------------------------- +; load one or more DLL file in COFF format and try to import functions by our list +; if first function in import list begins with 'lib_', call it as DLL initialization +; return eax = 1 as fail, if anyone of .obj file not found in /sys/lib +; return 0 if all fine, but 0 not garantees in succesfull import - see dll.Link comment +; dirties all registers! eax, ebx, ecx, edx, esi, edi +proc dll.Load, import_table:dword + mov esi, [import_table] + .next_lib: + mov edx, [esi] + or edx, edx + jz .exit + push esi + mov esi, [esi + 4] + mov edi, s_libdir.fname + @@: + lodsb + stosb + or al, al + jnz @b + mcall 68, 19, s_libdir + or eax, eax + jz .fail + stdcall dll.Link, eax, edx + push eax + mov eax, [eax] + cmp dword[eax], 'lib_' + pop eax + jnz @f + stdcall dll.Init, [eax + 4] + @@: + pop esi + add esi, 8 + jmp .next_lib + .exit: + xor eax, eax + ret + .fail: + add esp, 4 + xor eax, eax + inc eax + ret +endp +;----------------------------------------------------------------------------- +; scans dll export table for a functions we want to import +; break scan on first unresolved import +; no return value +proc dll.Link, exp:dword, imp:dword + push eax + mov esi, [imp] + test esi, esi + jz .done + .next: + lodsd + test eax, eax + jz .done + stdcall dll.GetProcAddress, [exp], eax + or eax, eax + jz @f + mov [esi - 4], eax + jmp .next + @@: + mov dword[esp], 0 + .done: + pop eax + ret +endp +;----------------------------------------------------------------------------- +; calls lib_init with predefined parameters +; no return value +proc dll.Init, dllentry:dword + pushad + mov eax, mem.Alloc + mov ebx, mem.Free + mov ecx, mem.ReAlloc + mov edx, dll.Load + stdcall [dllentry] + popad + ret +endp +;----------------------------------------------------------------------------- +; scans export table for a sz_name function +; returns in eax function address or 0 if not found +proc dll.GetProcAddress, exp:dword, sz_name:dword + mov edx, [exp] + xor eax, eax + .next: + or edx, edx + jz .end + cmp dword[edx], 0 + jz .end + stdcall strcmp, [edx], [sz_name] + test eax, eax + jz .ok + add edx, 8 + jmp .next + .ok: + mov eax, [edx + 4] + .end: + cmp eax, -1 + jnz @f + xor eax, eax + @@: + ret +endp +;----------------------------------------------------------------------------- +; compares strings +; returns eax = 0 if equal, -1 otherwise +proc strcmp, str1:dword, str2:dword + push esi edi + mov esi, [str1] + mov edi, [str2] + xor eax, eax + @@: + lodsb + scasb + jne .fail + or al, al + jnz @b + jmp .ok + .fail: + or eax, -1 + .ok: + pop edi esi + ret +endp +;----------------------------------------------------------------------------- +if defined dll.Load +s_libdir: + db '/sys/lib/' + .fname rb 32 +end if +;----------------------------------------------------------------------------- +proc mem.Alloc, size + push ebx ecx + mov ecx, [size] + mcall 68, 12 + pop ecx ebx + ret +endp +;----------------------------------------------------------------------------- +proc mem.ReAlloc, mptr, size + push ebx ecx edx + mov ecx, [size] + mov edx, [mptr] + mcall 68, 20 + pop edx ecx ebx + ret +endp +;----------------------------------------------------------------------------- +proc mem.Free, mptr + push ebx ecx + mov ecx,[mptr] + mcall 68, 13 + pop ecx ebx + ret +endp +;----------------------------------------------------------------------------- diff --git a/programs/develop/libraries/kolibri-libc/source/crt/macros.inc b/programs/develop/libraries/kolibri-libc/source/crt/macros.inc new file mode 100644 index 0000000000..feb72aebe7 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/macros.inc @@ -0,0 +1,597 @@ +@^ fix macro comment { +^@ fix } + +; -------------------------- +macro library [lname,fname] +{ + forward + dd __#lname#_library_table__,__#lname#_library_name__ + common + dd 0 + forward + align 4 + __#lname#_library_name__ db fname,0 +} + +macro import lname,[name,sname] +{ + common + align 4 + __#lname#_library_table__: + forward + if used name + name dd __#name#_import_name__ + end if + common + dd 0 + forward + if used name + align 4 + __#name#_import_name__ db sname,0 + end if +} + +macro export [name,sname] +{ + forward + dd __#name#_export_name__,name + common + dd 0 + forward + align 4 + __#name#_export_name__ db sname,0 +} +; ------------------------- + +macro m2m dest,src { + push src + pop dest +} + + +macro iglobal { + IGlobals equ IGlobals, + macro __IGlobalBlock { } + +macro uglobal { + UGlobals equ UGlobals, + macro __UGlobalBlock { } + +endg fix } ; Use endg for ending iglobal and uglobal blocks. + + +macro IncludeIGlobals{ + macro IGlobals dummy,[n] \{ __IGlobalBlock + purge __IGlobalBlock \} + match I, IGlobals \{ I \} } + +macro IncludeUGlobals{ + macro UGlobals dummy,[n] \{ + \common + \local begin, size + begin = $ + virtual at $ + \forward + __UGlobalBlock + purge __UGlobalBlock + \common + size = $ - begin + end virtual + rb size + \} + match U, UGlobals \{ U \} } + +uglobal +endg + +iglobal +endg + + +; new application structure +macro meos_app_start + { + use32 + org 0x0 + + db 'MENUET01' + dd 0x01 + dd __start + dd __end + dd __memory + dd __stack + + if used __params & ~defined __params + dd __params + else + dd 0x0 + end if + + dd 0x0 + } +MEOS_APP_START fix meos_app_start +KOS_APP_START fix meos_app_start + +macro code + { + __start: + } +CODE fix code + +macro data + { + __data: + IncludeIGlobals + } +DATA fix data + +macro udata + { + if used __params & ~defined __params + __params: + db 0 + __end: + rb 255 + else + __end: + end if + __udata: + IncludeUGlobals + } +UDATA fix udata + +macro meos_app_end + { + align 32 + rb 2048 + __stack: + __memory: + } +MEOS_APP_END fix meos_app_end +KOS_APP_END fix meos_app_end + + +; macro for defining multiline text data +struc mstr [sstring] + { + forward + local ssize + virtual at 0 + db sstring + ssize = $ + end virtual + dd ssize + db sstring + common + dd -1 + } + +; macro for defining multiline text data +struc mls [sstring] + { + forward + local ssize + virtual at 0 + db sstring ; mod + ssize = $ + end virtual + db ssize + db sstring + common + db -1 ; mod + } + + + +; strings +macro sz name,[data] { ; [mike.dld] + common + if used name + name db data + .size = $-name + end if +} + +macro szZ name,[data] { ; same as sz, but for zero terminated string [dunkaist] + common + if used name + name db data,0 + .size = $-name-1 + end if +} +sz0 fix szZ + +macro lsz name,[lng,data] { ; [mike.dld] + common + if used name + label name + forward + if lang eq lng + db data + end if + common + .size = $-name + end if +} + +macro szc name,elsz,[data] { ; [mike.dld] + common + local s,m + m = 0 + if used name + label name + forward + virtual at 0 + db data + s = $ + end virtual + d#elsz s + if m < s + m = s + end if + db data + common + .size = $-name + .maxl = m + end if +} + +macro lszc name,elsz,[lng,data] { ; [mike.dld] + common + local s,m,c + m = 0 + c = 0 + if used name + label name + forward + if lang eq lng + virtual at 0 + db data + s = $ + end virtual + d#elsz s + if m < s + m = s + end if + db data + c = c+1 + end if + common + .size = $-name + .maxl = m + .count = c + end if +} + + +; easy system call macro +macro mpack dest, hsrc, lsrc +{ + if (hsrc eqtype 0) & (lsrc eqtype 0) + mov dest, (hsrc) shl 16 + lsrc + else + if (hsrc eqtype 0) & (~lsrc eqtype 0) + mov dest, (hsrc) shl 16 + add dest, lsrc + else + mov dest, hsrc + shl dest, 16 + add dest, lsrc + end if + end if +} + +macro __mov reg,a,b { ; mike.dld + if (~a eq)&(~b eq) + mpack reg,a,b + else if (~a eq)&(b eq) + mov reg,a + end if +} + + +include 'config.inc' +;__CPU_type equ p5 +SYSENTER_VAR equ 0 + +macro mcall a,b,c,d,e,f,g { ; [mike.dld], [Ghost] + local ..ret_point + __mov eax,a + __mov ebx,b + __mov ecx,c + __mov edx,d + __mov esi,e + __mov edi,f + __mov ebp,g + + if __CPU_type eq p5 + int 0x40 + else + if __CPU_type eq p6 + push ebp + mov ebp, esp + push ..ret_point ; it may be 2 or 5 byte + sysenter + ..ret_point: + pop edx + pop ecx + + else + if __CPU_type eq k6 + push ecx + syscall + pop ecx + else + display 'ERROR : unknown CPU type (set to p5)', 10, 13 + __CPU_type equ p5 + int 0x40 + end if + end if + end if +} + + +; ------------------------- +macro __header a,[b] { + common + use32 + org 0 + db 'MENUET',a + forward + if b eq + dd 0 + else + dd b + end if +} + +macro __section name { + align 16 + label name +} + +macro __func name { + if ~used name + display 'FUNC NOT USED: ',`name,13,10 + else + align 4 + name: + ;diff16 `name,0,name +} + +macro endf { end if } + +macro diff16 title,l1,l2 + { + local s,d + s = l2-l1 + display title,': 0x' + repeat 8 + d = '0' + s shr ((8-%) shl 2) and $0F + if d > '9' + d = d + 'A'-'9'-1 + end if + display d + end repeat + display 13,10 + } + +macro diff10 title,l1,l2 + { + local s,d,z,m + s = l2-l1 + z = 0 + m = 1000000000 + display title,': ' + repeat 10 + d = '0' + s / m + s = s - (s/m)*m + m = m / 10 + if d <> '0' + z = 1 + end if + if z <> 0 + display d + end if + end repeat + display 13,10 + } + + +macro movi arg1,arg2 +{ +if (arg1 in ) & ((arg2 eqtype 0) | (arg2 eqtype '0')) + if (arg2) = 0 + xor arg1,arg1 + else if (arg2) = 1 + xor arg1,arg1 + inc arg1 + else if (arg2) = -1 + or arg1,-1 + else if (arg2) >= -128 & (arg2) <= 127 + push arg2 + pop arg1 + else + mov arg1,arg2 + end if +else + mov arg1,arg2 +end if +} + + +macro RGB [a] { + common + match (r=,g=,b),a \{ + \dd ((r) shl 16) or ((g) shl 8) or (b) + \} +} + + +struc POINT _t,_dx,_dy { + .x _t _dx + .y _t _dy +} + +; structure definition helper +include 'struct.inc' + +struct RECT + left dd ? + top dd ? + right dd ? + bottom dd ? +ends + +struct BOX + left dd ? + top dd ? + width dd ? + height dd ? +ends + +; structures used in KolibriOS +struct process_information + cpu_usage dd ? ; +0 + window_stack_position dw ? ; +4 + window_stack_value dw ? ; +6 + dw ? ; +8 + process_name rb 12 ; +10 + memory_start dd ? ; +22 + used_memory dd ? ; +26 + PID dd ? ; +30 + box BOX ; +34 + slot_state dw ? ; +50 + dw ? ; +52 + client_box BOX ; +54 + wnd_state db ? ; +70 + rb (1024-71) +ends + +struct system_colors + frame dd ? ;nonset1 + grab dd ? ;nonset2 + work_dark dd ? + work_light dd ? + grab_text dd ? ;window_title + work dd ? + work_button dd ? + work_button_text dd ? + work_text dd ? + work_graph dd ? +ends + +struct FILEDATE + Second db ? + Minute db ? + Hour db ? + db ? + Day db ? + Month db ? + Year dw ? +ends + +struct FILEINFO + Attributes dd ? + IsUnicode db ? + db 3 dup(?) + DateCreate FILEDATE + DateAccess FILEDATE + DateModify FILEDATE + Size dq ? +ends + +cmove fix cmovz + +macro cmovz reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jnz ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovz reg1, reg2 +end if + +} + +cmovne fix cmovnz + +macro cmovnz reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jz ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovnz reg1, reg2 +end if + +} + +macro cmovg reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jle ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovg reg1, reg2 +end if +} + +macro cmovl reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jge ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovl reg1, reg2 +end if +} + +; replaces /programs/cmp.inc +irp cond, e, ne, g, ng, l, nl, ge, le { + macro cmp#cond a, b, c\{ + cmp a, b + j#cond c + \} +} + +; constants + +; events +EV_IDLE = 0 +EV_TIMER = 0 +EV_REDRAW = 1 +EV_KEY = 2 +EV_BUTTON = 3 +EV_EXIT = 4 +EV_BACKGROUND = 5 +EV_MOUSE = 6 +EV_IPC = 7 +EV_STACK = 8 + +; event mask bits for function 40 +EVM_REDRAW = 1b +EVM_KEY = 10b +EVM_BUTTON = 100b +EVM_EXIT = 1000b +EVM_BACKGROUND = 10000b +EVM_MOUSE = 100000b +EVM_IPC = 1000000b +EVM_STACK = 10000000b +EVM_DEBUG = 100000000b +EVM_STACK2 = 1000000000b + +EVM_MOUSE_FILTER = 0x80000000 +EVM_CURSOR_FILTER = 0x40000000 diff --git a/programs/develop/libraries/kolibri-libc/source/crt/proc32.inc b/programs/develop/libraries/kolibri-libc/source/crt/proc32.inc new file mode 100644 index 0000000000..762826cbbb --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/proc32.inc @@ -0,0 +1,301 @@ + +; Macroinstructions for defining and calling procedures + +macro stdcall proc,[arg] ; directly call STDCALL procedure + { common + if ~ arg eq + reverse + pushd arg + common + end if + call proc } + +macro invoke proc,[arg] ; indirectly call STDCALL procedure + { common + if ~ arg eq + reverse + pushd arg + common + end if + call [proc] } + +macro ccall proc,[arg] ; directly call CDECL procedure + { common + size@ccall = 0 + if ~ arg eq + reverse + pushd arg + size@ccall = size@ccall+4 + common + end if + call proc + if size@ccall + add esp,size@ccall + end if } + +macro cinvoke proc,[arg] ; indirectly call CDECL procedure + { common + size@ccall = 0 + if ~ arg eq + reverse + pushd arg + size@ccall = size@ccall+4 + common + end if + call [proc] + if size@ccall + add esp,size@ccall + end if } + +macro proc [args] ; define procedure + { common + match name params, args> + \{ define@proc name, \{ prologue name,flag,parmbytes,localbytes,reglist \} + virtual at parmbase@proc + match =,args, params \{ defargs@proc args \} + match =args@proc args, args@proc params \{ defargs@proc args \} + parmbytes = $-(parmbase@proc) + end virtual + name # % = parmbytes/4 + all@vars equ + current = 0 + macro locals + \{ virtual at localbase@proc+current + macro label def \\{ match . type,def> \\\{ deflocal@proc .,label, \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} + macro finish@proc + \{ localbytes = current + match close:reglist, close@proc: \\{ close name,flag,parmbytes,localbytes,reglist \\} + end if \} } + +macro defargs@proc [arg] + { common + if ~ arg eq + forward + local ..arg,current@arg + match argname:type, arg + \{ current@arg equ argname + label ..arg type + argname equ ..arg + if qqword eq type + dd ?,?,?,?,?,?,?,? + else if dqword eq type + dd ?,?,?,? + else if tbyte eq type + dd ?,?,? + else if qword eq type | pword eq type + dd ?,? + else + dd ? + end if \} + match =current@arg,current@arg + \{ current@arg equ arg + arg equ ..arg + ..arg dd ? \} + common + args@proc equ current@arg + forward + restore current@arg + common + end if } + +macro deflocal@proc name,def,[val] { name def val } + +macro deflocal@proc name,def,[val] + { common + match vars, all@vars \{ all@vars equ all@vars, \} + all@vars equ all@vars name + forward + local ..var,..tmp + ..var def val + match =?, val \{ ..tmp equ \} + match any =?, val \{ ..tmp equ \} + match any (=?), val \{ ..tmp equ \} + match =label, def \{ ..tmp equ \} + match tmp : value, ..tmp : val + \{ tmp: end virtual + initlocal@proc ..var,def value + virtual at tmp\} + common + match first rest, ..var, \{ name equ first \} } + +struc label type { label . type } + +macro initlocal@proc name,def + { virtual at name + def + size@initlocal = $ - name + end virtual + position@initlocal = 0 + while size@initlocal > position@initlocal + virtual at name + def + if size@initlocal - position@initlocal < 2 + current@initlocal = 1 + load byte@initlocal byte from name+position@initlocal + else if size@initlocal - position@initlocal < 4 + current@initlocal = 2 + load word@initlocal word from name+position@initlocal + else + current@initlocal = 4 + load dword@initlocal dword from name+position@initlocal + end if + end virtual + if current@initlocal = 1 + mov byte [name+position@initlocal],byte@initlocal + else if current@initlocal = 2 + mov word [name+position@initlocal],word@initlocal + else + mov dword [name+position@initlocal],dword@initlocal + end if + position@initlocal = position@initlocal + current@initlocal + end while } + +macro endp + { purge ret,locals,endl + finish@proc + purge finish@proc + restore regs@proc + match all,args@proc \{ restore all \} + restore args@proc + match all,all@vars \{ restore all \} } + +macro local [var] + { common + locals + forward done@local equ + match varname[count]:vartype, var + \{ match =BYTE, vartype \\{ varname rb count + restore done@local \\} + match =WORD, vartype \\{ varname rw count + restore done@local \\} + match =DWORD, vartype \\{ varname rd count + restore done@local \\} + match =PWORD, vartype \\{ varname rp count + restore done@local \\} + match =QWORD, vartype \\{ varname rq count + restore done@local \\} + match =TBYTE, vartype \\{ varname rt count + restore done@local \\} + match =DQWORD, vartype \\{ label varname dqword + rq count*2 + restore done@local \\} + match =QQWORD, vartype \\{ label varname qqword + rq count*4 + restore done@local \\} + match =XWORD, vartype \\{ label varname xword + rq count*2 + restore done@local \\} + match =YWORD, vartype \\{ label varname yword + rq count*4 + restore done@local \\} + match , done@local \\{ virtual + varname vartype + end virtual + rb count*sizeof.\#vartype + restore done@local \\} \} + match :varname:vartype, done@local:var + \{ match =BYTE, vartype \\{ varname db ? + restore done@local \\} + match =WORD, vartype \\{ varname dw ? + restore done@local \\} + match =DWORD, vartype \\{ varname dd ? + restore done@local \\} + match =PWORD, vartype \\{ varname dp ? + restore done@local \\} + match =QWORD, vartype \\{ varname dq ? + restore done@local \\} + match =TBYTE, vartype \\{ varname dt ? + restore done@local \\} + match =DQWORD, vartype \\{ label varname dqword + dq ?,? + restore done@local \\} + match =QQWORD, vartype \\{ label varname qqword + dq ?,?,?,? + restore done@local \\} + match =XWORD, vartype \\{ label varname xword + dq ?,? + restore done@local \\} + match =YWORD, vartype \\{ label varname yword + dq ?,?,?,? + restore done@local \\} + match , done@local \\{ varname vartype + restore done@local \\} \} + match ,done@local + \{ var + restore done@local \} + common + endl } diff --git a/programs/develop/libraries/kolibri-libc/source/crt/struct.inc b/programs/develop/libraries/kolibri-libc/source/crt/struct.inc new file mode 100644 index 0000000000..789dd17976 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/crt/struct.inc @@ -0,0 +1,240 @@ + +; Macroinstructions for defining data structures + +macro struct name + { virtual at 0 + fields@struct equ name + match child parent, name \{ fields@struct equ child,fields@\#parent \} + sub@struct equ + struc db [val] \{ \common define field@struct .,db, + fields@struct equ fields@struct,field@struct \} + struc dw [val] \{ \common define field@struct .,dw, + fields@struct equ fields@struct,field@struct \} + struc du [val] \{ \common define field@struct .,du, + fields@struct equ fields@struct,field@struct \} + struc dd [val] \{ \common define field@struct .,dd, + fields@struct equ fields@struct,field@struct \} + struc dp [val] \{ \common define field@struct .,dp, + fields@struct equ fields@struct,field@struct \} + struc dq [val] \{ \common define field@struct .,dq, + fields@struct equ fields@struct,field@struct \} + struc dt [val] \{ \common define field@struct .,dt, + fields@struct equ fields@struct,field@struct \} + struc rb count \{ define field@struct .,db,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rw count \{ define field@struct .,dw,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rd count \{ define field@struct .,dd,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rp count \{ define field@struct .,dp,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rq count \{ define field@struct .,dq,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rt count \{ define field@struct .,dt,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro db [val] \{ \common \local anonymous + define field@struct anonymous,db, + fields@struct equ fields@struct,field@struct \} + macro dw [val] \{ \common \local anonymous + define field@struct anonymous,dw, + fields@struct equ fields@struct,field@struct \} + macro du [val] \{ \common \local anonymous + define field@struct anonymous,du, + fields@struct equ fields@struct,field@struct \} + macro dd [val] \{ \common \local anonymous + define field@struct anonymous,dd, + fields@struct equ fields@struct,field@struct \} + macro dp [val] \{ \common \local anonymous + define field@struct anonymous,dp, + fields@struct equ fields@struct,field@struct \} + macro dq [val] \{ \common \local anonymous + define field@struct anonymous,dq, + fields@struct equ fields@struct,field@struct \} + macro dt [val] \{ \common \local anonymous + define field@struct anonymous,dt, + fields@struct equ fields@struct,field@struct \} + macro rb count \{ \local anonymous + define field@struct anonymous,db,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rw count \{ \local anonymous + define field@struct anonymous,dw,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rd count \{ \local anonymous + define field@struct anonymous,dd,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rp count \{ \local anonymous + define field@struct anonymous,dp,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rq count \{ \local anonymous + define field@struct anonymous,dq,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rt count \{ \local anonymous + define field@struct anonymous,dt,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro union \{ fields@struct equ fields@struct,,union,< + sub@struct equ union \} + macro struct \{ fields@struct equ fields@struct,,substruct,< + sub@struct equ substruct \} } + +macro ends + { match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt + restruc rb,rw,rd,rp,rq,rt + purge db,dw,du,dd,dp,dq,dt + purge rb,rw,rd,rp,rq,rt + purge union,struct + match name tail,fields@struct, \\{ if $ + display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah + err + end if \\} + match name=,fields,fields@struct \\{ fields@struct equ + make@struct name,fields + define fields@\\#name fields \\} + end virtual \} + match any, sub@struct \{ fields@struct equ fields@struct> \} + restore sub@struct } + +macro make@struct name,[field,type,def] + { common + local define + define equ name + forward + local sub + match , field \{ make@substruct type,name,sub def + define equ define,.,sub, \} + match any, field \{ define equ define,.#field,type, \} + common + match fields, define \{ define@struct fields \} } + +macro define@struct name,[field,type,def] + { common + virtual + db `name + load initial@struct byte from 0 + if initial@struct = '.' + display 'Error: name of structure should not begin with a dot.',0Dh,0Ah + err + end if + end virtual + local list + list equ + forward + if ~ field eq . + name#field type def + sizeof.#name#field = $ - name#field + else + label name#.#type + rb sizeof.#type + end if + local value + match any, list \{ list equ list, \} + list equ list + common + sizeof.#name = $ + restruc name + match values, list \{ + struc name value \\{ \\local \\..base + match any, fields@struct \\\{ fields@struct equ fields@struct,.,name, \\\} + match , fields@struct \\\{ label \\..base + forward + match , value \\\\{ field type def \\\\} + match any, value \\\\{ field type value + if ~ field eq . + rb sizeof.#name#field - ($-field) + end if \\\\} + common label . at \\..base \\\} + \\} + macro name value \\{ + match any, fields@struct \\\{ \\\local anonymous + fields@struct equ fields@struct,anonymous,name, \\\} + match , fields@struct \\\{ + forward + match , value \\\\{ type def \\\\} + match any, value \\\\{ \\\\local ..field + ..field = $ + type value + if ~ field eq . + rb sizeof.#name#field - ($-..field) + end if \\\\} + common \\\} \\} \} } + +macro enable@substruct + { macro make@substruct substruct,parent,name,[field,type,def] + \{ \common + \local define + define equ parent,name + \forward + \local sub + match , field \\{ match any, type \\\{ enable@substruct + make@substruct type,parent,sub def + purge make@substruct + define equ define,.,sub, \\\} \\} + match any, field \\{ define equ define,.\#field,type, \\} + \common + match fields, define \\{ define@\#substruct fields \\} \} } + +enable@substruct + +macro define@union parent,name,[field,type,def] + { common + virtual at parent#.#name + forward + if ~ field eq . + virtual at parent#.#name + parent#field type def + sizeof.#parent#field = $ - parent#field + end virtual + if sizeof.#parent#field > $ - parent#.#name + rb sizeof.#parent#field - ($ - parent#.#name) + end if + else + virtual at parent#.#name + label parent#.#type + type def + end virtual + label name#.#type at parent#.#name + if sizeof.#type > $ - parent#.#name + rb sizeof.#type - ($ - parent#.#name) + end if + end if + common + sizeof.#name = $ - parent#.#name + end virtual + struc name [value] \{ \common + label .\#name + last@union equ + forward + match any, last@union \\{ virtual at .\#name + field type def + end virtual \\} + match , last@union \\{ match , value \\\{ field type def \\\} + match any, value \\\{ field type value \\\} \\} + last@union equ field + common rb sizeof.#name - ($ - .\#name) \} + macro name [value] \{ \common \local ..anonymous + ..anonymous name value \} } + +macro define@substruct parent,name,[field,type,def] + { common + virtual at parent#.#name + forward + if ~ field eq . + parent#field type def + sizeof.#parent#field = $ - parent#field + else + label parent#.#type + rb sizeof.#type + end if + common + sizeof.#name = $ - parent#.#name + end virtual + struc name value \{ + label .\#name + forward + match , value \\{ field type def \\} + match any, value \\{ field type value + if ~ field eq . + rb sizeof.#parent#field - ($-field) + end if \\} + common \} + macro name value \{ \local ..anonymous + ..anonymous name \} } diff --git a/programs/develop/libraries/kolibri-libc/source/ctype/is.c b/programs/develop/libraries/kolibri-libc/source/ctype/is.c new file mode 100644 index 0000000000..fc160bec22 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/ctype/is.c @@ -0,0 +1,21 @@ +#include + +unsigned short __is[129] = { + 0, /* EOF */ + 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 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, + 0x140, 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, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, + 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, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, + 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, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x004 + }; diff --git a/programs/develop/libraries/kolibri-libc/source/exports/exports.c b/programs/develop/libraries/kolibri-libc/source/exports/exports.c new file mode 100644 index 0000000000..7f179087a2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/exports/exports.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +ksys_coff_etable_t EXPORTS[] = { +{"clearerr", &clearerr}, +{"debug_printf", &debug_printf}, +{"fclose", &fclose}, +{"feof", &feof}, +{"ferror", &ferror}, +{"fflush", &fflush}, +{"fgetc", &fgetc}, +{"fgetpos", &fgetpos}, +{"fgets", &fgets}, +{"fopen", &fopen}, +{"fprintf", &fprintf}, +{"fputc", &fputc}, +{"fputs", &fputs}, +{"fread", &fread}, +{"freopen", &freopen}, +{"fscanf", &fscanf}, +{"fseek", &fseek}, +{"fsetpos", &fsetpos}, +{"ftell", &ftell}, +{"fwrite", &fwrite}, +{"getchar", &getchar}, +{"gets", &gets}, +{"perror", &perror}, +{"printf", &printf}, +{"puts", &puts}, +{"remove", &remove}, +{"rename", &rename}, +{"rewind", &rewind}, +{"scanf", &scanf}, +{"setbuf", &setbuf}, +{"setvbuf", &setvbuf}, +{"snprintf", &snprintf}, +{"sprintf", &sprintf}, +{"sscanf", &sscanf}, +{"tmpfile", &tmpfile}, +{"tmpnam", &tmpnam}, +{"vfscanf", &vfscanf}, +{"vprintf", &vprintf}, +{"vfscanf", &vfscanf}, +{"vsnprintf", &vsnprintf}, +{"vsscanf", &vsscanf}, +{"abs", &abs}, +{"atoi", &atoi}, +{"atol", &atol}, +{"atoll", &atoll}, +{"calloc", &calloc}, +{"difftime", &difftime}, +{"div", &div}, +{"exit", &exit}, +{"free", &free}, +{"itoa", &itoa}, +{"labs", &labs}, +{"ldiv", &ldiv}, +{"llabs", &llabs}, +{"lldiv", &lldiv}, +{"localtime", &localtime}, +{"malloc", &malloc}, +{"mktime", &mktime}, +{"realloc", &realloc}, +{"strtol", &strtol}, +{"time", &time}, +{"memcpy", &memcpy}, +{"memchr", &memchr}, +{"memcmp", &memcmp}, +{"memmove", &memmove}, +{"memset", &memset}, +{"strncat", &strncat}, +{"strchr", &strchr}, +{"strcmp", &strcmp}, +{"strcoll", &strcoll}, +{"strcpy", &strcpy}, +{"strcspn", &strcspn}, +{"strdup", &strdup}, +{"strerror", &strerror}, +{"strlen", &strlen}, +{"strncat", &strncat}, +{"strncmp", &strncmp}, +{"strncpy", &strncpy}, +{"strrchr", &strrchr}, +{"strrev", &strrev}, +{"strspn", &strspn}, +{"strstr", &strstr}, +{"strtok", &strtok}, +{"strxfrm", &strxfrm}, +{"closedir", &closedir}, +{"opendir", &opendir}, +{"readdir", &readdir}, +{"rewinddir", &rewinddir}, +{"seekdir", &seekdir}, +{"telldir", &telldir}, +{"acosh", &acosh}, +{"asinh", &asinh}, +{"atanh", &atanh}, +{"acosh", &acosh}, +{"frexp", &frexp}, +{"hypot", &hypot}, +{"ldexp", &ldexp}, +{"sinh", &sinh}, +{"tanh", &tanh}, +{"acos", &acos}, +{"asin", &asin}, +{"atan", &atan}, +{"atan2", &atan2}, +{"ceil", &ceil}, +{"cos", &cos}, +{"exp", &exp}, +{"fabs", &fabs}, +{"floor", &floor}, +{"fmod", &fmod}, +{"log", &log}, +{"modf", &modf}, +{"modfl", &modfl}, +{"pow", &pow}, +{"pow2", &pow2}, +{"pow10", &pow10}, +{"longjmp", &longjmp}, +{"setjmp", &setjmp}, +{"__is", &__is}, +{"con_set_title", &con_set_title}, +NULL, +}; \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/libc.c b/programs/develop/libraries/kolibri-libc/source/libc.c new file mode 100644 index 0000000000..672989134d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/libc.c @@ -0,0 +1,141 @@ +#include "ctype/is.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 "stdio/clearerr.c" +#include "stdio/vscanf.c" +#include "stdio/gets.c" +#include "stdio/setbuf.c" +#include "stdio/fgetc.c" +#include "stdio/fopen.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/vsscanf.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/vfscanf.c" +#include "stdio/fflush.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 "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/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/strncmp.c" +#include "string/strncat.c" +#include "string/strtok.c" +#include "string/strcmp.c" +#include "string/memset.c" +#include "string/memcpy.c" +#include "string/memmove.c" + +#include "stdlib/calloc.c" +#include "stdlib/lldiv.c" +#include "stdlib/malloc.c" +#include "stdlib/atoll.c" +#include "stdlib/free.c" +#include "stdlib/llabs.c" +#include "stdlib/exit.c" +#include "stdlib/mktime.c" +#include "stdlib/atoi.c" +#include "stdlib/localtime.c" +#include "stdlib/labs.c" +#include "stdlib/difftime.c" +#include "stdlib/realloc.c" +#include "stdlib/ldiv.c" +#include "stdlib/libtcc1.c" +#include "stdlib/abs.c" +#include "stdlib/div.c" +#include "stdlib/atol.c" +#include "stdlib/itoa.c" +#include "stdlib/time.c" +#include "stdlib/strtol.c" + +#include "math/acosh.c" +#include "math/asinh.c" +#include "math/atanh.c" +#include "math/cosh.c" +#include "math/frexp.c" +#include "math/hypot.c" +#include "math/ldexp.c" +#include "math/sinh.c" +#include "math/tanh.c" + + +__asm__( + ".include \"math/acos.s\"\n\t" + ".include \"math/asin.s\"\n\t" + ".include \"math/atan.s\"\n\t" + ".include \"math/atan2.s\"\n\t" + ".include \"math/ceil.s\"\n\t" + ".include \"math/cos.s\"\n\t" + ".include \"math/exp.s\"\n\t" + ".include \"math/fabs.s\"\n\t" + ".include \"math/floor.s\"\n\t" + ".include \"math/fmod.s\"\n\t" + ".include \"math/log.s\"\n\t" + ".include \"math/modf.s\"\n\t" + ".include \"math/modfl.s\"\n\t" + ".include \"math/pow.s\"\n\t" + ".include \"math/pow2.s\"\n\t" + ".include \"math/pow10.s\"\n\t" +); + +__asm__( + ".include \"setjmp/longjmp.s\"\n\t" + ".include \"setjmp/setjmp.s\"" +); + +#include "stdlib/___chkstk_ms.c" + +#include "exports/exports.c" \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/libc.obj b/programs/develop/libraries/kolibri-libc/source/libc.obj new file mode 100644 index 0000000000..75375eb7b7 Binary files /dev/null and b/programs/develop/libraries/kolibri-libc/source/libc.obj differ diff --git a/programs/develop/libraries/kolibri-libc/source/math/acos.s b/programs/develop/libraries/kolibri-libc/source/math/acos.s new file mode 100644 index 0000000000..3f23b7a017 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/acos.s @@ -0,0 +1,23 @@ +.text + +acos.LC0: + .double 0d1.00000000000000000000e+00 + +.global acos; + +acos: + fldl 4(%esp) + fld1 + fsubp %st(0),%st(1) + fsqrt + + fldl 4(%esp) + fld1 + faddp %st(0),%st(1) + fsqrt + + fpatan + + fld %st(0) + faddp + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/acosh.c b/programs/develop/libraries/kolibri-libc/source/math/acosh.c new file mode 100644 index 0000000000..6e13bbe6ec --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/acosh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +acosh(double x) +{ + return log(x + sqrt(x*x - 1)); +} diff --git a/programs/develop/libraries/kolibri-libc/source/math/asin.s b/programs/develop/libraries/kolibri-libc/source/math/asin.s new file mode 100644 index 0000000000..09eaaa2a17 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/asin.s @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global asin; + +asin: + fldl 4(%esp) + fld %st(0) + fmulp + fld1 + fsubp + fsqrt + fldl 4(%esp) + fxch %st(1) + fpatan + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/asinh.c b/programs/develop/libraries/kolibri-libc/source/math/asinh.c new file mode 100644 index 0000000000..e27e20da7e --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/asinh.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +asinh(double x) +{ + return x>0 ? log(x + sqrt(x*x + 1)) : -log(sqrt(x*x+1)-x); +} + diff --git a/programs/develop/libraries/kolibri-libc/source/math/atan.s b/programs/develop/libraries/kolibri-libc/source/math/atan.s new file mode 100644 index 0000000000..29fd7438e8 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/atan.s @@ -0,0 +1,10 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global atan; + +atan: + fldl 4(%esp) + fld1 + fpatan + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/atan2.s b/programs/develop/libraries/kolibri-libc/source/math/atan2.s new file mode 100644 index 0000000000..090b6941c0 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/atan2.s @@ -0,0 +1,37 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +.data + .align 2 +nan: + .long 0xffffffff + .byte 0xff + .byte 0xff + .byte 0xff + .byte 0x7f + +.text + +.global atan2; + +atan2: + fldl 4(%esp) + fldl 12(%esp) + ftst + fnstsw %ax + sahf + jne doit + fxch %st(1) + ftst + fnstsw %ax + sahf + je isanan + fxch %st(1) +doit: + fpatan + ret +isanan: + movl $1, errno + fstp %st(0) + fstp %st(0) + fldl nan + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/atanh.c b/programs/develop/libraries/kolibri-libc/source/math/atanh.c new file mode 100644 index 0000000000..8335dc78b3 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/atanh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +atanh(double x) +{ + return log((1+x)/(1-x)) / 2.0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/math/ceil.s b/programs/develop/libraries/kolibri-libc/source/math/ceil.s new file mode 100644 index 0000000000..6a33b88cf8 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/ceil.s @@ -0,0 +1,26 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +.global ceil; + +ceil: + pushl %ebp + movl %esp,%ebp + subl $8,%esp + + fstcw -4(%ebp) + fwait + movw -4(%ebp),%ax + andw $0xf3ff,%ax + orw $0x0800,%ax + movw %ax,-2(%ebp) + fldcw -2(%ebp) + + fldl 8(%ebp) + frndint + + fldcw -4(%ebp) + + movl %ebp,%esp + popl %ebp + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/cos.s b/programs/develop/libraries/kolibri-libc/source/math/cos.s new file mode 100644 index 0000000000..12b0eac8e1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/cos.s @@ -0,0 +1,17 @@ +cos.L0: + .quad 0xffffffffffffffff + +.global cos; + +cos: + fldl 4(%esp) + fcos + fstsw + sahf + jnp cos.L1 + fstp %st(0) + fldl cos.L0 + +cos.L1: + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/cosh.c b/programs/develop/libraries/kolibri-libc/source/math/cosh.c new file mode 100644 index 0000000000..c2cca978ac --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/cosh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double cosh(double x) +{ + const double ebig = exp(fabs(x)); + return (ebig + 1.0/ebig) / 2.0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/math/exp.s b/programs/develop/libraries/kolibri-libc/source/math/exp.s new file mode 100644 index 0000000000..9bf570eb4d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/exp.s @@ -0,0 +1,33 @@ + + .data +exp.LCW1: + .word 0 +exp.LCW2: + .word 0 +exp.LC0: + .double 0d1.0e+00 + + .text + +.global exp; + +exp: + fldl 4(%esp) + fldl2e + fmulp + fstcw exp.LCW1 + fstcw exp.LCW2 + fwait + andw $0xf3ff, exp.LCW2 + orw $0x0400, exp.LCW2 + fldcw exp.LCW2 + fldl %st(0) + frndint + fldcw exp.LCW1 + fxch %st(1) + fsub %st(1),%st + f2xm1 + faddl exp.LC0 + fscale + fstp %st(1) + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/fabs.s b/programs/develop/libraries/kolibri-libc/source/math/fabs.s new file mode 100644 index 0000000000..ecc702047a --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/fabs.s @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global fabs; + +fabs: + fldl 4(%esp) + fabs + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/floor.s b/programs/develop/libraries/kolibri-libc/source/math/floor.s new file mode 100644 index 0000000000..00ace37efb --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/floor.s @@ -0,0 +1,26 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +.global floor; + +floor: + pushl %ebp + movl %esp,%ebp + subl $8,%esp + + fstcw -4(%ebp) + fwait + movw -4(%ebp),%ax + andw $0xf3ff,%ax + orw $0x0400,%ax + movw %ax,-2(%ebp) + fldcw -2(%ebp) + + fldl 8(%ebp) + frndint + + fldcw -4(%ebp) + + movl %ebp,%esp + popl %ebp + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/fmod.s b/programs/develop/libraries/kolibri-libc/source/math/fmod.s new file mode 100644 index 0000000000..f77ad49a51 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/fmod.s @@ -0,0 +1,26 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.text + +.global fmod; + +fmod: + fldl 4(%esp) + fldl 12(%esp) + ftst + fnstsw %ax + fxch %st(1) + sahf + jnz next + fstpl %st(0) + jmp out +next: + fprem + fnstsw %ax + sahf + jpe next + fstpl %st(1) +out: + ret + + diff --git a/programs/develop/libraries/kolibri-libc/source/math/frexp.c b/programs/develop/libraries/kolibri-libc/source/math/frexp.c new file mode 100644 index 0000000000..913f16f06b --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/frexp.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +frexp(double x, int *exptr) +{ + union { + double d; + unsigned char c[8]; + } u; + + u.d = x; + /* + * The format of the number is: + * Sign, 12 exponent bits, 51 mantissa bits + * The exponent is 1023 biased and there is an implicit zero. + * We get the exponent from the upper bits and set the exponent + * to 0x3fe (1022). + */ + *exptr = (int)(((u.c[7] & 0x7f) << 4) | (u.c[6] >> 4)) - 1022; + u.c[7] &= 0x80; + u.c[7] |= 0x3f; + u.c[6] &= 0x0f; + u.c[6] |= 0xe0; + return u.d; +} diff --git a/programs/develop/libraries/kolibri-libc/source/math/hypot.c b/programs/develop/libraries/kolibri-libc/source/math/hypot.c new file mode 100644 index 0000000000..00b81691b4 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/hypot.c @@ -0,0 +1,100 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * hypot() function for DJGPP. + * + * hypot() computes sqrt(x^2 + y^2). The problem with the obvious + * naive implementation is that it might fail for very large or + * very small arguments. For instance, for large x or y the result + * might overflow even if the value of the function should not, + * because squaring a large number might trigger an overflow. For + * very small numbers, their square might underflow and will be + * silently replaced by zero; this won't cause an exception, but might + * have an adverse effect on the accuracy of the result. + * + * This implementation tries to avoid the above pitfals, without + * inflicting too much of a performance hit. + * + */ + +/// #include +#include +#include + +/* Approximate square roots of DBL_MAX and DBL_MIN. Numbers + between these two shouldn't neither overflow nor underflow + when squared. */ +#define __SQRT_DBL_MAX 1.3e+154 +#define __SQRT_DBL_MIN 2.3e-162 + +double +hypot(double x, double y) +{ + double abig = fabs(x), asmall = fabs(y); + double ratio; + + /* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */ + if (abig < asmall) + { + double temp = abig; + + abig = asmall; + asmall = temp; + } + + /* Trivial case. */ + if (asmall == 0.) + return abig; + + /* Scale the numbers as much as possible by using its ratio. + For example, if both ABIG and ASMALL are VERY small, then + X^2 + Y^2 might be VERY inaccurate due to loss of + significant digits. Dividing ASMALL by ABIG scales them + to a certain degree, so that accuracy is better. */ + + if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX) + return abig * sqrt(1.0 + ratio*ratio); + else + { + /* Slower but safer algorithm due to Moler and Morrison. Never + produces any intermediate result greater than roughly the + larger of X and Y. Should converge to machine-precision + accuracy in 3 iterations. */ + + double r = ratio*ratio, t, s, p = abig, q = asmall; + + do { + t = 4. + r; + if (t == 4.) + break; + s = r / t; + p += 2. * s * p; + q *= s; + r = (q / p) * (q / p); + } while (1); + + return p; + } +} + +#ifdef TEST + +#include + +int +main(void) +{ + 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^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", + hypot(3.e-320, 4.e-320)); + printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n", + 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(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)); + + return 0; +} + +#endif diff --git a/programs/develop/libraries/kolibri-libc/source/math/ldexp.c b/programs/develop/libraries/kolibri-libc/source/math/ldexp.c new file mode 100644 index 0000000000..818cab7578 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/ldexp.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +double +ldexp(double v, int e) +{ + double two = 2.0; + + if (e < 0) + { + e = -e; /* This just might overflow on two-complement machines. */ + if (e < 0) return 0.0; + while (e > 0) + { + if (e & 1) v /= two; + two *= two; + e >>= 1; + } + } + else if (e > 0) + { + while (e > 0) + { + if (e & 1) v *= two; + two *= two; + e >>= 1; + } + } + return v; +} + diff --git a/programs/develop/libraries/kolibri-libc/source/math/log.s b/programs/develop/libraries/kolibri-libc/source/math/log.s new file mode 100644 index 0000000000..9363fb92cc --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/log.s @@ -0,0 +1,9 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global log; + +log: + fldln2 + fldl 4(%esp) + fyl2x + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/modf.s b/programs/develop/libraries/kolibri-libc/source/math/modf.s new file mode 100644 index 0000000000..9ae5356ca2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/modf.s @@ -0,0 +1,35 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + .text + +.global modf; + +modf: + pushl %ebp + movl %esp,%ebp + subl $16,%esp + pushl %ebx + fnstcw -4(%ebp) + fwait + movw -4(%ebp),%ax + orw $0x0c3f,%ax + movw %ax,-8(%ebp) + fldcw -8(%ebp) + fwait + fldl 8(%ebp) + frndint + fstpl -16(%ebp) + fwait + movl -16(%ebp),%edx + movl -12(%ebp),%ecx + movl 16(%ebp),%ebx + movl %edx,(%ebx) + movl %ecx,4(%ebx) + fldl 8(%ebp) + fsubl -16(%ebp) + leal -20(%ebp),%esp + fclex + fldcw -4(%ebp) + fwait + popl %ebx + leave + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/modfl.s b/programs/develop/libraries/kolibri-libc/source/math/modfl.s new file mode 100644 index 0000000000..c9ec5f8096 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/modfl.s @@ -0,0 +1,23 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global modfl; + +modfl: + pushl %ebp + movl %esp,%ebp + subl $4,%esp + fldt 8(%ebp) + movl 20(%ebp),%eax + fnstcw -2(%ebp) + movw -2(%ebp),%dx + orb $0x0c,%dh + movw %dx,-4(%ebp) + fldcw -4(%ebp) + fld %st(0) + frndint + fldcw -2(%ebp) + fld %st(0) + fstpt (%eax) + fsubrp %st,%st(1) + leave + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/pow.s b/programs/develop/libraries/kolibri-libc/source/math/pow.s new file mode 100644 index 0000000000..3167c37809 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/pow.s @@ -0,0 +1,87 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + .data +yint: + .word 0,0 +pow.LCW1: + .word 0 +pow.LCW2: + .word 0 + + .text +pow.LC0: + .double 0d1.0e+00 + +.global pow; + +frac: + fstcw pow.LCW1 + fstcw pow.LCW2 + fwait + andw $0xf3ff,pow.LCW2 + orw $0x0400,pow.LCW2 + fldcw pow.LCW2 + fldl %st(0) + frndint + fldcw pow.LCW1 + fxch %st(1) + fsub %st(1),%st + ret + +Lpow2: + call frac + f2xm1 + faddl pow.LC0 + fscale + fstp %st(1) + ret + +pow: + fldl 12(%esp) + fldl 4(%esp) + ftst + fnstsw %ax + sahf + jbe xltez + fyl2x + jmp Lpow2 +xltez: + jb xltz + fstp %st(0) + ftst + fnstsw %ax + sahf + ja ygtz + jb error + fstp %st(0) + fld1 + fchs +error: + fsqrt + ret +ygtz: + fstp %st(0) + fldz + ret +xltz: + fabs + fxch %st(1) + call frac + ftst + fnstsw %ax + fstp %st(0) + sahf + je yisint + fstp %st(0) + fchs + jmp error +yisint: + fistl yint + fxch %st(1) + fyl2x + call Lpow2 + andl $1,yint + jz yeven + fchs +yeven: + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/pow10.s b/programs/develop/libraries/kolibri-libc/source/math/pow10.s new file mode 100644 index 0000000000..a676ded690 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/pow10.s @@ -0,0 +1,34 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + + .data +pow10.LCW1: + .word 0 +pow10.LCW2: + .word 0 +pow10.LC0: + .double 0d1.0e+00 + + .text + +.global pow10; + +pow10: + fldl 4(%esp) + fldl2t + fmulp + fstcw pow10.LCW1 + fstcw pow10.LCW2 + fwait + andw $0xf3ff,pow10.LCW2 + orw $0x0400,pow10.LCW2 + fldcw pow10.LCW2 + fldl %st(0) + frndint + fldcw pow10.LCW1 + fxch %st(1) + fsub %st(1),%st + f2xm1 + faddl pow10.LC0 + fscale + fstp %st(1) + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/pow2.s b/programs/develop/libraries/kolibri-libc/source/math/pow2.s new file mode 100644 index 0000000000..d45ed51825 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/pow2.s @@ -0,0 +1,32 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + + .data +pow2.LCW1: + .word 0 +pow2.LCW2: + .word 0 +pow2.LC0: + .double 0d1.0e+00 + + .text + +.global pow2; + +pow2: + fldl 4(%esp) + fstcw pow2.LCW1 + fstcw pow2.LCW2 + fwait + andw $0xf3ff,pow2.LCW2 + orw $0x0400,pow2.LCW2 + fldcw pow2.LCW2 + fldl %st(0) + frndint + fldcw pow2.LCW1 + fxch %st(1) + fsub %st(1),%st + f2xm1 + faddl pow2.LC0 + fscale + fstp %st(1) + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/sin.s b/programs/develop/libraries/kolibri-libc/source/math/sin.s new file mode 100644 index 0000000000..75cc57d05f --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/sin.s @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global sin; + +sin.L0: + .quad 0xffffffffffffffff + +sin: + fldl 4(%esp) + fsin + fstsw + sahf + jnp sin.L1 + fstp %st(0) + fldl L0 +sin.L1: + ret + diff --git a/programs/develop/libraries/kolibri-libc/source/math/sinh.c b/programs/develop/libraries/kolibri-libc/source/math/sinh.c new file mode 100644 index 0000000000..d00e2803e1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/sinh.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double sinh(double x) +{ + if(x >= 0.0) + { + const double epos = exp(x); + return (epos - 1.0/epos) / 2.0; + } + else + { + const double eneg = exp(-x); + return (1.0/eneg - eneg) / 2.0; + } +} diff --git a/programs/develop/libraries/kolibri-libc/source/math/sqrt.s b/programs/develop/libraries/kolibri-libc/source/math/sqrt.s new file mode 100644 index 0000000000..4011a53852 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/sqrt.s @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +.global sqrt; + +sqrt: + fldl 4(%esp) + fsqrt + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/tan.s b/programs/develop/libraries/kolibri-libc/source/math/tan.s new file mode 100644 index 0000000000..5101c4ffbf --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/tan.s @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +tan.L0: + .quad 0xffffffffffffffff + +tan: + fldl 4(%esp) + fptan + fstsw + fstp %st(0) + sahf + jnp tan.L1 +/* fstp %st(0) - if exception, there is nothing on the stack */ + fldl tan.L0 +tan.L1: + ret diff --git a/programs/develop/libraries/kolibri-libc/source/math/tanh.c b/programs/develop/libraries/kolibri-libc/source/math/tanh.c new file mode 100644 index 0000000000..c2eb966319 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/math/tanh.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double tanh(double x) +{ + if (x > 50) + return 1; + else if (x < -50) + return -1; + else + { + const double ebig = exp(x); + const double esmall = 1.0/ebig; + return (ebig - esmall) / (ebig + esmall); + } +} + diff --git a/programs/develop/libraries/kolibri-libc/source/setjmp/longjmp.s b/programs/develop/libraries/kolibri-libc/source/setjmp/longjmp.s new file mode 100644 index 0000000000..93b5ce0628 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/setjmp/longjmp.s @@ -0,0 +1,13 @@ +.global longjmp + +longjmp: + mov 4(%esp),%edx + mov 8(%esp),%eax + cmp $1,%eax + adc $0, %al + mov (%edx),%ebx + mov 4(%edx),%esi + mov 8(%edx),%edi + mov 12(%edx),%ebp + mov 16(%edx),%esp + jmp *20(%edx) diff --git a/programs/develop/libraries/kolibri-libc/source/setjmp/setjmp.s b/programs/develop/libraries/kolibri-libc/source/setjmp/setjmp.s new file mode 100644 index 0000000000..1b073350c8 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/setjmp/setjmp.s @@ -0,0 +1,15 @@ + +.global setjmp + +setjmp: + mov 4(%esp), %eax + mov %ebx, (%eax) + mov %esi, 4(%eax) + mov %edi, 8(%eax) + mov %ebp, 12(%eax) + lea 4(%esp), %ecx + mov %ecx, 16(%eax) + mov (%esp), %ecx + mov %ecx, 20(%eax) + xor %eax, %eax + ret diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/clearerr.c b/programs/develop/libraries/kolibri-libc/source/stdio/clearerr.c new file mode 100644 index 0000000000..b50b929362 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/clearerr.c @@ -0,0 +1,6 @@ +#include + +void clearerr(FILE *stream) { + stream->error = 0; + stream->eof = 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/conio.c b/programs/develop/libraries/kolibri-libc/source/stdio/conio.c new file mode 100644 index 0000000000..43c043a81b --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/conio.c @@ -0,0 +1,68 @@ +#include +#include "conio.h" + +static char* __con_caption = "Console application"; +static char* __con_dllname = "/sys/lib/console.obj"; + +int __con_is_load = 0; + +void stdcall (*__con_init_hidden)(int wnd_width, int wnd_height,int scr_width, int scr_height, const char* title); +void stdcall (*__con_write_asciiz)(const char* str); +void stdcall (*__con_write_string)(const char* str, unsigned length); +int stdcall (*__con_getch)(void); +short stdcall (*__con_getch2)(void); +int stdcall (*__con_kbhit)(void); +char* stdcall (*__con_gets)(char* str, int n); +char* stdcall (*__con_gets2)(__con_gets2_callback callback, char* str, int n); +void stdcall (*__con_exit)(int status); +void stdcall (*__con_set_title)(const char* title); + +static void __con_panic(char* func_name) +{ + _ksys_debug_puts("libc.obj: "); + _ksys_debug_puts(func_name); + _ksys_debug_puts(" = NULL\n"); + _ksys_exit(); +} + +static void __con_lib_link(ksys_coff_etable_t *exp) +{ + __con_init_hidden = _ksys_get_coff_func(exp, "con_init", __con_panic); + __con_write_asciiz = _ksys_get_coff_func(exp, "con_write_asciiz", __con_panic); + __con_write_string = _ksys_get_coff_func(exp, "con_write_string", __con_panic); + __con_getch = _ksys_get_coff_func(exp, "con_getch", __con_panic); + __con_getch2 = _ksys_get_coff_func(exp, "con_getch2", __con_panic); + __con_kbhit = _ksys_get_coff_func(exp, "con_kbhit", __con_panic); + __con_gets = _ksys_get_coff_func(exp, "con_gets", __con_panic); + __con_gets2 = _ksys_get_coff_func(exp, "con_gets2", __con_panic); + __con_exit = _ksys_get_coff_func(exp, "con_exit", __con_panic); + __con_set_title = _ksys_get_coff_func(exp, "con_set_title", __con_panic); +} + + +int __con_init(void) +{ + return __con_init_opt(-1, -1, -1, -1, __con_caption); +} + +void con_set_title(const char* title){ + __con_init(); + __con_set_title(title); +} + +int __con_init_opt(int wnd_width, int wnd_height,int scr_width, int scr_height, const char* title) +{ + if(!__con_is_load){ + ksys_coff_etable_t *__con_lib; + __con_lib = _ksys_load_coff(__con_dllname); + if(__con_lib==NULL){ + _ksys_debug_puts("Error! Can't load console.obj lib\n"); + return 1; + } + __con_lib_link(__con_lib); + __con_init_hidden(wnd_width, wnd_height, scr_width, scr_height, title); + __con_is_load= 1; + return 0; + } + return 1; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/conio.h b/programs/develop/libraries/kolibri-libc/source/stdio/conio.h new file mode 100644 index 0000000000..3b5fa98e7b --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/conio.h @@ -0,0 +1,76 @@ +/* + +This is adapded thunk for console.obj sys library +Only for internal use in stdio.h + +Adapted for tcc by Siemargl, 2016 + +*/ +#ifndef _CONIO_H_ +#define _CONIO_H_ + +#define cdecl __attribute__ ((cdecl)) +#define stdcall __attribute__ ((stdcall)) + + void stdcall (*__con_write_asciiz)(const char* str); +/* Display ASCIIZ-string to the console at the current position, shifting +the current position. */ + + void stdcall (*__con_write_string)(const char* str, unsigned length); +/* Similar to __con_write_asciiz, but length of the string must be given as a +separate parameter */ + + int stdcall (*__con_getch)(void); +/* Get one character from the keyboard. + +For normal characters function returns ASCII-code. For extended +characters (eg, Fx, and arrows), first function call returns 0 +and second call returns the extended code (similar to the DOS-function +input). Starting from version 7, after closing the console window, +this function returns 0. */ + + short stdcall (*__con_getch2)(void); +/* Reads a character from the keyboard. Low byte contains the ASCII-code +(0 for extended characters), high byte - advanced code (like in BIOS +input functions). Starting from version 7, after closing the console +window, this function returns 0. */ + + int stdcall (*__con_kbhit)(void); +/* Returns 1 if a key was pressed, 0 otherwise. To read pressed keys use +__con_getch and __con_getch2. Starting from version 6, after closing +the console window, this function returns 1. */ + + char* stdcall (*__con_gets)(char* str, int n); +/* Reads a string from the keyboard. Reading is interrupted when got +"new line" character, or after reading the (n-1) characters (depending on +what comes first). In the first case the newline is also recorded in the +str. The acquired line is complemented by a null character. +Starting from version 6, the function returns a pointer to the entered +line if reading was successful, and NULL if the console window was closed. */ + +typedef int (stdcall * __con_gets2_callback)(int keycode, char** pstr, int* pn, + int* ppos); + + char* stdcall (*__con_gets2)(__con_gets2_callback callback, char* str, int n); +/* Con_gets completely analogous, except that when the user +press unrecognized key, it calls the specified callback-procedure +(which may, for example, handle up / down for history and tab to enter +autocompletion). You should pass to the procedure: key code and three pointers +- to the string, to the maximum length and to the current position. +function may change the contents of string and may change the string +itself (for example, to reallocate memory for increase the limit), +maximum length, and position of the line - pointers are passed for it. +Return value: 0 = line wasn't changed 1 = line changed, you should +remove old string and display new, 2 = line changed, it is necessary +to display it; 3 = immediately exit the function. +Starting from version 6, the function returns a pointer to the entered +line with the successful reading, and NULL if the console window was closed. */ + + int __con_is_load; + unsigned *__con_dll_ver; + + int __con_init(void); + int __con_init_opt(int wnd_width, int wnd_height, int scr_width, int scr_height, const char* title); + void stdcall (*__con_exit)(int status); + +#endif diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/debug_printf.c b/programs/develop/libraries/kolibri-libc/source/stdio/debug_printf.c new file mode 100644 index 0000000000..9143b1b499 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/debug_printf.c @@ -0,0 +1,15 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include +#include + +void debug_printf(const char *format,...) +{ + va_list ap; + static char log_board[STDIO_MAX_MEM]; + va_start (ap, format); + vsnprintf(log_board, STDIO_MAX_MEM, format, ap); + va_end(ap); + _ksys_debug_puts(log_board); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fclose.c b/programs/develop/libraries/kolibri-libc/source/stdio/fclose.c new file mode 100644 index 0000000000..8f558f4778 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fclose.c @@ -0,0 +1,7 @@ +#include +#include + +int fclose(FILE *stream) { + free(stream); + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/feof.c b/programs/develop/libraries/kolibri-libc/source/stdio/feof.c new file mode 100644 index 0000000000..4b5cb4bde2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/feof.c @@ -0,0 +1,5 @@ +#include + +int feof(FILE *stream) { + return stream->eof; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/ferror.c b/programs/develop/libraries/kolibri-libc/source/stdio/ferror.c new file mode 100644 index 0000000000..c87d1516a2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/ferror.c @@ -0,0 +1,5 @@ +#include + +int ferror(FILE *stream) { + return stream->error; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fflush.c b/programs/develop/libraries/kolibri-libc/source/stdio/fflush.c new file mode 100644 index 0000000000..d6ad8ab510 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fflush.c @@ -0,0 +1,5 @@ +#include + +int fflush(FILE *stream) { + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fgetc.c b/programs/develop/libraries/kolibri-libc/source/stdio/fgetc.c new file mode 100644 index 0000000000..b773d7aaf6 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fgetc.c @@ -0,0 +1,38 @@ +#include +#include +#include + +int fgetc(FILE* stream) +{ + unsigned bytes_read; + char c; + + unsigned status = _ksys_file_read_file(stream->name, stream->position, 1, &c, &bytes_read); + + if (status != KSYS_FS_ERR_SUCCESS) { + switch (status) { + case KSYS_FS_ERR_EOF: + stream->eof = 1; + break; + case KSYS_FS_ERR_1: + case KSYS_FS_ERR_2: + case KSYS_FS_ERR_3: + case KSYS_FS_ERR_4: + case KSYS_FS_ERR_5: + case KSYS_FS_ERR_7: + case KSYS_FS_ERR_8: + case KSYS_FS_ERR_9: + case KSYS_FS_ERR_10: + case KSYS_FS_ERR_11: + default: + // Just some IO error, who knows what exactly happened + errno = EIO; + stream->error = errno; + break; + } + return EOF; + } + + stream->position++; + return c; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fgetpos.c b/programs/develop/libraries/kolibri-libc/source/stdio/fgetpos.c new file mode 100644 index 0000000000..cce4f9a2d9 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fgetpos.c @@ -0,0 +1,6 @@ +#include + +int fgetpos(FILE *restrict stream, fpos_t *restrict pos) { + *pos = stream->position; + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fgets.c b/programs/develop/libraries/kolibri-libc/source/stdio/fgets.c new file mode 100644 index 0000000000..300ae09f7d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fgets.c @@ -0,0 +1,24 @@ +#include +#include "conio.h" +#include + +char *fgets(char *str, int n, FILE *stream) +{ + int i=0, sym_code; + + if(!stream || !str){ + errno = EINVAL; + return NULL; + } + + while (i +#include + +FILE *fopen(const char *restrict _name, const char *restrict _mode) { + FILE *out = malloc(sizeof(FILE)); + return freopen(_name, _mode, out); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/format_print.c b/programs/develop/libraries/kolibri-libc/source/stdio/format_print.c new file mode 100644 index 0000000000..938a9e3138 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/format_print.c @@ -0,0 +1,817 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "format_print.h" +#include + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + + +// internal buffer output +void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } + else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } + else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/format_print.h b/programs/develop/libraries/kolibri-libc/source/stdio/format_print.h new file mode 100644 index 0000000000..c1dd4aecd4 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/format_print.h @@ -0,0 +1,14 @@ +#include +#include + +#pragma pack(push,1) +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; +#pragma pack(pop) + +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen); + void _out_null(char character, void* buffer, size_t idx, size_t maxlen); + int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va); diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/format_scan.c b/programs/develop/libraries/kolibri-libc/source/stdio/format_scan.c new file mode 100644 index 0000000000..4178d21bab --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/format_scan.c @@ -0,0 +1,403 @@ +/* + function for format read from any source + +Siemargl formats as http://www.cplusplus.com/reference/cstdio/scanf/, no wchar though +http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html is used too + +todo: +[characters], [^characters] +-%n nothing scanned, filled only if good result +-%d, i, u, o, x, p read similar - detect base by prefix 0 or 0x +-%a +-can overflow unsigned as signed +-radix point always '.', no LOCALEs +*/ + +#include +#include +#include +#include +#include "format_scan.h" + +static int __try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) +// returns 1 if OK, -1 == EOF, -2 parse broken +{ + int sign = 1, have_digits = 0; + long long div; + + if (ch == '+') + { + ch = vgetc(save, src); + if (ch == EOF) return EOF; + } else + if (ch == '-') + { + sign = -1; + ch = vgetc(save, src); + if (ch == EOF) return EOF; + }; + *real = 0.0; + for (;;) // mantissa before point + { + // test ch is valid + if (isdigit(ch)) + { + *real = *real * 10 + ch - '0'; + have_digits++; + ch = vgetc(save, src); + if (ch == EOF || isspace(ch)) break; // ok, just finish num + } else + if (ch == '.' || ch == 'E' || ch == 'e') + { + break; // ok + } + else + { + vungetc(save, ch, src); + break; + } + } + if (ch != '.' && ch != 'E' && ch != 'e') // ok, just integer part + { + *real *= sign; + if (have_digits) + return 1; + else + return -2; + } + + if(ch == '.') + { + ch = vgetc(save, src); + div = 10; // use as divisor + for (;;) // mantissa after point + { + // test ch is valid + if (isdigit(ch)) + { + *real += (double)(ch - '0') / div; + div *= 10; + have_digits++; + ch = vgetc(save, src); + if (ch == EOF || isspace(ch)) break; // ok, just finish num + } else + if (ch == 'E' || ch == 'e') + { + break; // ok + } + else + { + vungetc(save, ch, src); + break; + } + } + if (ch != 'E' && ch != 'e') // ok, real as XX.YY + { + *real *= sign; + if (have_digits) + return 1; + else + return -2; + } + } + + ch = vgetc(save, src); + *real *= sign; + // exponent + sign = 1; + if (ch == '+') + { + ch = vgetc(save, src); + if (ch == EOF) return EOF; + } else + if (ch == '-') + { + sign = -1; + ch = vgetc(save, src); + if (ch == EOF) return EOF; + }; + div = 0; + for (;;) + { + // test ch is valid + if (isdigit(ch)) + { + div = div * 10 + ch - '0'; + ch = vgetc(save, src); + if (ch == EOF || isspace(ch)) break; // ok, just finish num + } + else + { + vungetc(save, ch, src); + break; + } + } + div *= sign; + *real *= pow(10,div); + + return 1; +} + +static int __try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) +{ + int sign = 1, base = 10, have_digits = 0; + + if (ch == '+') + { + ch = vgetc(save, src); + if (ch == EOF) return EOF; + } else + if (ch == '-') + { + sign = -1; + ch = vgetc(save, src); + if (ch == EOF) return EOF; + }; + + if (ch == '0') // octal or hex, read next + { + base = 8; + ch = vgetc(save, src); + if (ch == EOF || isspace(ch)) + have_digits++; + else + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = vgetc(save, src); + if (ch == EOF) return EOF; + } + } + *digit = 0; + for (;;) + { + // test ch is valid + if ((isdigit(ch) && base == 10) || + (isdigit(ch) && base == 8 && ch < '8') || + (isxdigit(ch) && base == 16)) + { + if (base == 16) + { + if (ch <= '9') ch-= '0'; + else + if (ch <= 'F') ch = 10 + ch - 'A'; + else + ch = 10 + ch - 'a'; + } + else + ch -= '0'; + *digit = *digit * base + ch; + have_digits++; + ch = vgetc(save, src); + if (ch == EOF || isspace(ch)) break; // ok, just finish num + } + else if (ch == EOF || isspace(ch)) + break; + else + { + vungetc(save, ch, src); + break; + } + } + *digit *= sign; + if (have_digits) + return 1; + else + return -2; +} + + + +int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc) +{ + int i; + int length; + int fmt1, fmt2; // width, precision + size_t pos, posc; + const char *fmtc; // first point to %, fmtc points to specifier + int ch; + int format_flag; + int flag_long; // 2 = long double or long long int or wchar + int *point_to_n = NULL, nread = 0; + int flags; // parsed flags + int save = 0; + char *arg_str; + int *arg_int; + long *arg_long; + long long *arg_longlong; + float *arg_float; + double *arg_double; + long double *arg_longdouble; + long long digit; + long double real; + + + pos = 0; + while(*fmt) + { + while (*fmt && isspace(*fmt)) fmt++; // skip paces in format str + + if (*fmt != '%') // usual char + { + ch = vgetc(&save, src); + if (ch != *fmt++) // char not match format + { + vungetc(&save, ch, src); + break; + } + pos++; + continue; + } + + if (*(fmt + 1) == '%') // %% + { + ch = vgetc(&save, src); + if (ch != '%') // char not match format + { + vungetc(&save, ch, src); + break; + } + pos++; + fmt += 2; + continue; + } + //checking to containg format in the string + fmtc = fmt; + posc = pos; + + flags = 0; + format_flag = 0; + flag_long = 0; // 2 = long double or long long int or wchar + + while(*fmtc != '\0' && !format_flag) // searching end of format + { + fmtc++; posc++; + switch( *fmtc ) + { + case 'a': + format_flag = 1; + flags |= flag_unsigned; + break; + case 'c': case 'd': case 'i': case 'e': case 'f': case 'g': case 's': case 'n': + format_flag = 1; + break; + case 'l': + flag_long = flag_long ? 2 : 1; // ll.eq.L + break; + case 'L': + flag_long = 2; + break; + case 'o': case 'u': case 'x': case 'p': + format_flag = 1; + flags |= flag_unsigned; + break; + case '*': case '.': // just skip + break; + default: + if(isdigit(*fmtc)) break; + goto exit_me; // non format char found - user error + } + } + + if (format_flag == 0) + { + goto exit_me; // format char not found - user error + } + + fmt1 = 0; + fmt2 = 0; + if (posc - pos > 1) // try to read width, precision + { + fmt++; + for(i = pos + 1; i < posc; i++) + { + switch(*fmt) + { + case '0': + if(fmt1 == 0 && (flags & flag_point) == 0) flags |= flag_lead_zeros; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if ((flags & flag_point) == 0) + fmt1 = fmt1 * 10 + (*fmt -'0'); + else + fmt2 = fmt2 * 10 + (*fmt -'0'); + break; + case '*': // ignoring + break; + case '.': + flags |= flag_point; + break; + case 'l': case 'L': // valid chars - skip + break; + default: // must be error + goto exit_me; // format char not found - user error + } + fmt++; + } + } + + // do real work - format arguments values + // skip input spaces + do { + ch = vgetc(&save, src); + if (ch == EOF) goto exit_me; + } while (isspace(ch)); + + switch(*fmtc) + { + case 'n': + point_to_n = va_arg(argp, int*); + vungetc(&save, ch, src); + break; + case 'c': // read width chars, ever spaces + arg_str = va_arg(argp, char*); + if (fmt1 == 0) length = 1; + else length = fmt1; + for (i = 0; i < length;) + { + *arg_str++ = ch; i++; + ch = vgetc(&save, src); + if (ch == EOF) break; + } + if (i < length) goto exit_me; // not enough chars + break; + case 's': + arg_str = va_arg(argp, char*); + if (fmt1 == 0) length = STDIO_MAX_MEM; // max string scan 4096 + else length = fmt1; + for (i = 0; i < length; i++) + { + *arg_str++ = ch; + ch = vgetc(&save, src); + if (ch == EOF || isspace(ch)) break; // ok, just finish string + } + *arg_str++ = '\0'; + break; + case 'd': case 'i': case 'u': + case 'o': case 'p': case 'x': + i = __try_parse_int(&digit, ch, src, &save, vgetc, vungetc); + if (i < 0) goto exit_me; + + if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else + if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else + if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; } + break; + case 'a': case 'A': case 'f': case 'F': + case 'e': case 'E': + case 'g': case 'G': + i = __try_parse_real(&real, ch, src, &save, vgetc, vungetc); + if (i < 0) goto exit_me; + + if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else + if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else + if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; } + break; + } + + fmt = fmtc + 1; + nread++; + } +exit_me: + if (point_to_n) *point_to_n = nread; + return nread; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/format_scan.h b/programs/develop/libraries/kolibri-libc/source/stdio/format_scan.h new file mode 100644 index 0000000000..eea22f5641 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/format_scan.h @@ -0,0 +1,20 @@ +#include + +typedef int (*virtual_getc)(void *sp, const void *obj); +typedef void (*virtual_ungetc)(void *sp, int c, const void *obj); + +enum flags_t +{ + flag_unsigned = 0x02, + flag_register = 0x04, + flag_plus = 0x08, + flag_left_just = 0x10, + flag_lead_zeros = 0x20, + flag_space_plus = 0x40, + flag_hash_sign = 0x80, + flag_point = 0x100 +}; + +char *__scanf_buffer; + +extern int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc); \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fprintf.c b/programs/develop/libraries/kolibri-libc/source/stdio/fprintf.c new file mode 100644 index 0000000000..c45c3e41a3 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fprintf.c @@ -0,0 +1,14 @@ + +#include "sys/ksys.h" +#include +#include + +int fprintf(FILE *restrict f, const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vfprintf(f, fmt, ap); + va_end(ap); + return ret; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fputc.c b/programs/develop/libraries/kolibri-libc/source/stdio/fputc.c new file mode 100644 index 0000000000..0fe29f0c88 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fputc.c @@ -0,0 +1,12 @@ +#include +#include +#include + +int fputc(int c, FILE *stream) +{ + if(fwrite(&c, sizeof(int), 1, stream)==1){ + return c; + }else{ + return EOF; + } +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fputs.c b/programs/develop/libraries/kolibri-libc/source/stdio/fputs.c new file mode 100644 index 0000000000..f6488c8bbf --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fputs.c @@ -0,0 +1,6 @@ +#include +#include + +int fputs(const char *str, FILE *stream){ + return fwrite(str, sizeof(char), strlen(str), stream); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fread.c b/programs/develop/libraries/kolibri-libc/source/stdio/fread.c new file mode 100644 index 0000000000..31bb3ab5aa --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fread.c @@ -0,0 +1,20 @@ +#include + +size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream) { + unsigned bytes_read = 0; + unsigned bytes_count = size * nmemb; + + for (size_t i = 0; i < bytes_count; i++) { + char c = fgetc(stream); + + if (c == EOF) { + break; + } + + *(char*)(ptr+i) = c; + + bytes_read++; + } + + return bytes_read / size; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/freopen.c b/programs/develop/libraries/kolibri-libc/source/stdio/freopen.c new file mode 100644 index 0000000000..f5d25e623d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/freopen.c @@ -0,0 +1,42 @@ +#include "sys/ksys.h" +#include +#include +#include +#include + +FILE *freopen(const char *restrict _name, const char *restrict _mode, FILE *restrict out) { + static ksys_bdfe_t info; + info.size=0; + if (!out) { + errno = ENOMEM; + return NULL; + } + + _ksys_file_get_info(_name, &info); + + out->name = strdup(_name); + out->position = 0; + out->error = 0; + out->eof = 0; + out->kind = 0; + out->orientation = 0; + out->mode = 0; + out->start_size = info.size; + + if (strchr(_mode, 'b')) { out->mode |= _STDIO_F_B; } + if (strchr(_mode, 'x')) { out->mode |= _STDIO_F_X; } + if (strchr(_mode, 'a')) { out->mode |= _STDIO_F_A; } + if (strchr(_mode, 'r')) { out->mode |= _STDIO_F_R; } + if (strchr(_mode, 'w')) { out->mode |= _STDIO_F_W; } + if (strchr(_mode, '+')) { out->mode |= _STDIO_F_R | _STDIO_F_W; } + + if (out->mode & _STDIO_F_A) { + out->position = info.size; + out->append_offset = info.size; + } else if(out->mode & _STDIO_F_W){ + if(_ksys_file_create(_name)){ + return NULL; + } + } + return out; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fscanf.c b/programs/develop/libraries/kolibri-libc/source/stdio/fscanf.c new file mode 100644 index 0000000000..2cc5d332dc --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fscanf.c @@ -0,0 +1,13 @@ +#include + +int fscanf(FILE* stream, const char* format, ...) +{ + va_list arg; + int n; + va_start(arg, format); + n = vfscanf(stream, format, arg); + va_end(arg); + return n; +} + + diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fseek.c b/programs/develop/libraries/kolibri-libc/source/stdio/fseek.c new file mode 100644 index 0000000000..dddf2b1f10 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fseek.c @@ -0,0 +1,17 @@ +#include +#include + +int fseek(FILE *stream, long int offset, int whence) { + if (whence == SEEK_SET) { + stream->position = offset; + } else if (whence == SEEK_CUR) { + stream->position += offset; + } else if (whence == SEEK_END) { + ksys_bdfe_t info; + if (_ksys_file_get_info(stream->name, &info)) { + return -1; + } + stream->position = info.size + offset; + } + stream->eof = 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fsetpos.c b/programs/develop/libraries/kolibri-libc/source/stdio/fsetpos.c new file mode 100644 index 0000000000..0247dc8b03 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fsetpos.c @@ -0,0 +1,7 @@ +#include + +int fsetpos(FILE *stream, const fpos_t *pos) { + stream->position = *pos; + stream->eof = 0; + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/ftell.c b/programs/develop/libraries/kolibri-libc/source/stdio/ftell.c new file mode 100644 index 0000000000..ba5c8ce6ab --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/ftell.c @@ -0,0 +1,5 @@ +#include + +long int ftell(FILE *stream) { + return stream->position; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/fwrite.c b/programs/develop/libraries/kolibri-libc/source/stdio/fwrite.c new file mode 100644 index 0000000000..716e455d51 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/fwrite.c @@ -0,0 +1,40 @@ +#include +#include "conio.h" +#include +#include + + +size_t fwrite(const void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream) { + unsigned bytes_written = 0; + unsigned bytes_count = size * nmemb; + + if(!stream){ + errno = EINVAL; + return 0; + } + + if(stream==stdout){ + __con_init(); + __con_write_string((char*)ptr, bytes_count); + return nmemb; + } + else if(stream==stderr){ + for (size_t i = 0; i < bytes_count; i++) { + char c = *(char*)(ptr+i); + _ksys_debug_putc(c); + } + } + else{ + if(stream->mode != _STDIO_F_R){ + unsigned status = _ksys_file_write_file(stream->name, stream->position, bytes_count, ptr, &bytes_written); + if (status != KSYS_FS_ERR_SUCCESS) { + errno = EIO; + stream->error = errno; + return 0; + }else { + stream->position+=bytes_written; + } + } + } + return bytes_written; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/getchar.c b/programs/develop/libraries/kolibri-libc/source/stdio/getchar.c new file mode 100644 index 0000000000..829ee18807 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/getchar.c @@ -0,0 +1,10 @@ +#include +#include "conio.h" + +int getchar(void) { + int c = __con_getch(); + if (c == 0) { + c = EOF; + } + return c; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/gets.c b/programs/develop/libraries/kolibri-libc/source/stdio/gets.c new file mode 100644 index 0000000000..4736242c12 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/gets.c @@ -0,0 +1,16 @@ +#include +#include +#include "conio.h" +#include +#include + +char *gets(char* str) +{ + __con_init(); + if(__con_gets(str, STDIO_MAX_MEM)==NULL){ + errno = EIO; + return NULL; + } + str[strlen(str)-1]='\0'; + return str; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/perror.c b/programs/develop/libraries/kolibri-libc/source/stdio/perror.c new file mode 100644 index 0000000000..672bcba5bc --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/perror.c @@ -0,0 +1,5 @@ +#include + +void perror(const char *s) { + debug_printf("%s: It's some error, maybe...\n", s); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/printf.c b/programs/develop/libraries/kolibri-libc/source/stdio/printf.c new file mode 100644 index 0000000000..eac2794402 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/printf.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include +#include + +//#include "format_print.h" + +int printf(const char *format, ...) +{ + va_list arg; + va_start(arg, format); + return vprintf(format, arg); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/puts.c b/programs/develop/libraries/kolibri-libc/source/stdio/puts.c new file mode 100644 index 0000000000..247ec0e3f8 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/puts.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include +#include "conio.h" +#include "sys/ksys.h" + +int puts(const char *str) +{ + __con_init(); + __con_write_asciiz(str); + __con_write_asciiz("\n"); + return strlen(str); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/remove.c b/programs/develop/libraries/kolibri-libc/source/stdio/remove.c new file mode 100644 index 0000000000..cc07bb9fa3 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/remove.c @@ -0,0 +1,6 @@ +#include +#include + +int remove(const char *name) { + return _ksys_file_delete(name); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/rename.c b/programs/develop/libraries/kolibri-libc/source/stdio/rename.c new file mode 100644 index 0000000000..b1aa0c94c1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/rename.c @@ -0,0 +1,6 @@ +#include +#include + +int rename(const char *name, const char *new_name) { + return _ksys_file_rename(name, new_name); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/rewind.c b/programs/develop/libraries/kolibri-libc/source/stdio/rewind.c new file mode 100644 index 0000000000..5b2a663dd6 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/rewind.c @@ -0,0 +1,5 @@ +#include + +void rewind(FILE *stream) { + stream->position = 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/scanf.c b/programs/develop/libraries/kolibri-libc/source/stdio/scanf.c new file mode 100644 index 0000000000..3d25c75226 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/scanf.c @@ -0,0 +1,21 @@ +//#include "format_scan.h" +#include +#include + +int scanf ( const char * format, ...) +{ + va_list arg; + int n; + va_start(arg, format); + + if(__scanf_buffer == NULL) __scanf_buffer = malloc(STDIO_MAX_MEM); + if(__scanf_buffer == NULL) errno = ENOMEM; return ENOMEM; + + *__scanf_buffer = 0; + n = vscanf(format, arg); + + va_end(arg); + return n; +} + + diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/setbuf.c b/programs/develop/libraries/kolibri-libc/source/stdio/setbuf.c new file mode 100644 index 0000000000..9a027de5b1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/setbuf.c @@ -0,0 +1,5 @@ +#include + +void setbuf(FILE *restrict stream, char *restrict buf) { + return; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/setvbuf.c b/programs/develop/libraries/kolibri-libc/source/stdio/setvbuf.c new file mode 100644 index 0000000000..038826faa6 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/setvbuf.c @@ -0,0 +1,5 @@ +#include + +int setvbuf(FILE *restrict stream, char *restrict buf, int mode, size_t size) { + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/snprintf.c b/programs/develop/libraries/kolibri-libc/source/stdio/snprintf.c new file mode 100644 index 0000000000..6b1fb80312 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/snprintf.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +//#include "format_print.h" +#include + +int snprintf(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/sprintf.c b/programs/develop/libraries/kolibri-libc/source/stdio/sprintf.c new file mode 100644 index 0000000000..949dcfb43f --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/sprintf.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +//#include "format_print.h" +#include + +int sprintf(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/sscanf.c b/programs/develop/libraries/kolibri-libc/source/stdio/sscanf.c new file mode 100644 index 0000000000..2268f978ab --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/sscanf.c @@ -0,0 +1,12 @@ +#include + +int sscanf(const char * s, const char * format, ...) +{ + va_list arg; + int n; + va_start(arg, format); + n = vsscanf(s, format, arg); + va_end(arg); + return n; +} + diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/tmpfile.c b/programs/develop/libraries/kolibri-libc/source/stdio/tmpfile.c new file mode 100644 index 0000000000..9d3e3fd9a1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/tmpfile.c @@ -0,0 +1,11 @@ +#include + +FILE *tmpfile(void) { + char name[FILENAME_MAX + 1]; + + if (!tmpnam(name)) { + return NULL; + } + + return fopen(name, "wb+"); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/tmpnam.c b/programs/develop/libraries/kolibri-libc/source/stdio/tmpnam.c new file mode 100644 index 0000000000..ff13759c4d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/tmpnam.c @@ -0,0 +1,16 @@ +#include +#include +#include + +static char buf[FILENAME_MAX + 1]; +static int static_index = 0; + +char *tmpnam(char *name) { + ksys_proc_table_t table; + _ksys_process_info(&table, -1); + + char *out = name ? name : buf; + // PID is also unique for each thread + sprintf(out, "/tmp0/1/%x_%x.tmp", table.pid, static_index++); + return out; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/vfprintf.c b/programs/develop/libraries/kolibri-libc/source/stdio/vfprintf.c new file mode 100644 index 0000000000..3ffa86e754 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/vfprintf.c @@ -0,0 +1,32 @@ + +#include +#include +#include +#include + +int vfprintf(FILE * file, const char *format, va_list arg) +{ + static char *buf=NULL; + int printed=0, rc = 0; + + if(!file){ + errno = EBADF; + return errno; + } + if(!format){ + errno = EINVAL; + return errno; + } + + buf = malloc(STDIO_MAX_MEM); + + if(!buf){ + errno = ENOMEM; + return errno; + } + + printed = vsnprintf(buf, STDIO_MAX_MEM, format,arg); + rc = fwrite(buf, sizeof(char), printed, file); + free(buf); + return rc; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/vfscanf.c b/programs/develop/libraries/kolibri-libc/source/stdio/vfscanf.c new file mode 100644 index 0000000000..8ff8dcebbe --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/vfscanf.c @@ -0,0 +1,55 @@ +#include +#include +#include +//#include "format_scan.h" +#include + +// non standard realization - support for virtually change ONLY ONE char + +static int __ungetc_emu(int c, FILE* stream) +{ + unsigned res; + if(stream){ + errno = EINVAL; + return EOF; + } + if ((stream->mode & 3) != _STDIO_F_R && (stream->mode & _STDIO_F_A) == 0){ + errno = EACCES; + return EOF; + } + ksys_bdfe_t *file_info = malloc(sizeof(ksys_bdfe_t)); + if(file_info==NULL){ + errno = ENOMEM; + return EOF; + } + if(!_ksys_file_get_info(stream->name, file_info)){ + errno = ENFILE; + return EOF; + } + if (stream->position > file_info->size || stream->position == 0 || c == EOF || stream->__ungetc_emu_buff != EOF){ + errno = EOF; + return EOF; + } + + stream->__ungetc_emu_buff = c; + stream->position --; + return c; +} + +static int __virtual_getc_file(void *sp, const void *obj) +{ + FILE *f = (FILE *)obj; + int ch = fgetc(f); + return ch; +} + +static void __virtual_ungetc_file(void *sp, int c, const void *obj) +{ + FILE *f = (FILE *)obj; + if (f) __ungetc_emu(c, f); +} + +int vfscanf(FILE * stream, const char * format, va_list arg) +{ + return _format_scan(stream, format, arg, &__virtual_getc_file, &__virtual_ungetc_file); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/vprintf.c b/programs/develop/libraries/kolibri-libc/source/stdio/vprintf.c new file mode 100644 index 0000000000..8e29314379 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/vprintf.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include +#include + +#include "conio.h" +#include +#include +#include +//#include "format_print.h" + +int vprintf ( const char * format, va_list arg ) +{ + int len = 0; + char *s = malloc(STDIO_MAX_MEM); + if(!s){ + errno = ENOMEM; + return errno; + } + __con_init(); + len = vsnprintf(s, STDIO_MAX_MEM, format, arg); + __con_write_string(s, len); + free(s); + return(len); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/vscanf.c b/programs/develop/libraries/kolibri-libc/source/stdio/vscanf.c new file mode 100644 index 0000000000..878a953d8a --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/vscanf.c @@ -0,0 +1,49 @@ +#include + +char *__scanf_buffer=NULL; +typedef int (*virtual_getc)(void *sp, const void *obj); +typedef void (*virtual_ungetc)(void *sp, int c, const void *obj); + +char *__scanf_buffer; + +extern int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc); + +static int __virtual_getc_con(void *sp, const void *obj) +// get next chat from string obj, save point is ptr to string char ptr +{ + int ch; + const char**spc= (const char**)sp; + if (!spc) return EOF; // error + if (!*spc) *spc = __scanf_buffer; // first call, init savepoint + + while (!**spc) // need to read more + { + if(!gets(__scanf_buffer)) return EOF; + *spc = __scanf_buffer; + strcat(__scanf_buffer,"\n"); // imitate delimiter + } + if (**spc == 26 || **spc == 3) // ^C ^Z end of scan, clear buffer + { + *spc = __scanf_buffer; + *__scanf_buffer = 0; + return EOF; // ^C ^Z + } + + ch = **spc; (*spc)++ ; + return ch; +} + +static void __virtual_ungetc_con(void *sp, int c, const void *obj) +// if can, one step back savepoint in s +{ + const char**spc= (const char**)sp; + + if (spc && *spc > __scanf_buffer) (*spc)--; +//printf("Ungetc '%c'[%d];", c, c); +} + + +int vscanf(const char * format, va_list arg) +{ + return _format_scan(NULL, format, arg, &__virtual_getc_con, &__virtual_ungetc_con); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/vsnprintf.c b/programs/develop/libraries/kolibri-libc/source/stdio/vsnprintf.c new file mode 100644 index 0000000000..baf1990a38 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/vsnprintf.c @@ -0,0 +1,6 @@ +//#include "format_print.h" + +int vsnprintf(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdio/vsscanf.c b/programs/develop/libraries/kolibri-libc/source/stdio/vsscanf.c new file mode 100644 index 0000000000..b840046088 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdio/vsscanf.c @@ -0,0 +1,32 @@ +//#include "format_scan.h" + +static int __virtual_getc_str(void *sp, const void *obj) +// get next chat from string obj, save point is ptr to string char ptr +{ + int ch; + const char *s = (const char *)obj; + const char**spc= (const char**)sp; + if (!s || !spc) return EOF; // error + + if (!*spc) *spc = s; // first call, init savepoint + + if (!**spc) return EOF; // EOS + + ch = **spc; (*spc)++ ; + + return ch; +} + +void __virtual_ungetc_str(void *sp, int c, const void *obj) +// if can, one step back savepoint in s +{ + const char *s = (const char *)obj; + const char**spc= (const char**)sp; + + if (s && spc && *spc > s) (*spc)--; +} + +int vsscanf(const char * s, const char * format, va_list arg) +{ + return _format_scan(s, format, arg, &__virtual_getc_str, &__virtual_ungetc_str); +}; \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/___chkstk_ms.c b/programs/develop/libraries/kolibri-libc/source/stdlib/___chkstk_ms.c new file mode 100644 index 0000000000..c446841ab4 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/___chkstk_ms.c @@ -0,0 +1 @@ +void ___chkstk_ms() {} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/abs.c b/programs/develop/libraries/kolibri-libc/source/stdlib/abs.c new file mode 100644 index 0000000000..0e7cebef28 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/abs.c @@ -0,0 +1,6 @@ +#include + +int abs(int a) +{ + return a>0 ? a : -a; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/atoi.c b/programs/develop/libraries/kolibri-libc/source/stdlib/atoi.c new file mode 100644 index 0000000000..5252fc8a20 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/atoi.c @@ -0,0 +1,21 @@ +#include +#include + +/* +** atoi(s) - convert s to integer. +*/ +int atoi(const char *s) +{ + int sign, n; + while(isspace(*s)) ++s; + sign = 1; + + switch(*s) { + case '-': sign = -1; + case '+': ++s; + } + + n = 0; + while(isdigit(*s)) n = 10 * n + *s++ - '0'; + return (sign * n); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/atol.c b/programs/develop/libraries/kolibri-libc/source/stdlib/atol.c new file mode 100644 index 0000000000..fc6251e6a9 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/atol.c @@ -0,0 +1,17 @@ +#include +#include + +long atol(const char *s) +{ + long n=0; + int neg=0; + while (isspace(*s)) s++; + switch (*s) { + case '-': neg=1; + case '+': s++; + } + /* Compute n as a negative number to avoid overflow on LONG_MIN */ + while (isdigit(*s)) + n = 10*n - (*s++ - '0'); + return neg ? n : -n; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/atoll.c b/programs/develop/libraries/kolibri-libc/source/stdlib/atoll.c new file mode 100644 index 0000000000..f8060d7546 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/atoll.c @@ -0,0 +1,17 @@ +#include +#include + +long long atoll(const char *s) +{ + long long n=0; + int neg=0; + while (isspace(*s)) s++; + switch (*s) { + case '-': neg=1; + case '+': s++; + } + /* Compute n as a negative number to avoid overflow on LLONG_MIN */ + while (isdigit(*s)) + n = 10*n - (*s++ - '0'); + return neg ? n : -n; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/calloc.c b/programs/develop/libraries/kolibri-libc/source/stdlib/calloc.c new file mode 100644 index 0000000000..846096c52c --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/calloc.c @@ -0,0 +1,6 @@ +#include +#include + +void *calloc(size_t num, size_t size) { + return _ksys_alloc(num*size); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/difftime.c b/programs/develop/libraries/kolibri-libc/source/stdlib/difftime.c new file mode 100644 index 0000000000..44c7323c28 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/difftime.c @@ -0,0 +1,6 @@ +#include + +double difftime (time_t end, time_t beginning) +{ + return end - beginning; +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/div.c b/programs/develop/libraries/kolibri-libc/source/stdlib/div.c new file mode 100644 index 0000000000..99bce10157 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/div.c @@ -0,0 +1,6 @@ +#include + +div_t div(int num, int den) +{ + return (div_t){ num/den, num%den }; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/exit.c b/programs/develop/libraries/kolibri-libc/source/stdlib/exit.c new file mode 100644 index 0000000000..202f2002e1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/exit.c @@ -0,0 +1,12 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include "../stdio/conio.h" +#include + +void exit(int status) +{ + if(__con_is_load){ + __con_exit(status); + } + _ksys_exit(); +} diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/free.c b/programs/develop/libraries/kolibri-libc/source/stdlib/free.c new file mode 100644 index 0000000000..b87df191b4 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/free.c @@ -0,0 +1,6 @@ +#include +#include + +void free(void *ptr) { + _ksys_free(ptr); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/itoa.c b/programs/develop/libraries/kolibri-libc/source/stdlib/itoa.c new file mode 100644 index 0000000000..f82140faab --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/itoa.c @@ -0,0 +1,42 @@ +#include +#include + +char *__reverse(char *str) +{ + char tmp, *src, *dst; + size_t len; + if (str != NULL){ + len = strlen (str); + if (len > 1) { + src = str; + dst = src + len - 1; + while (src < dst) { + tmp = *src; + *src++ = *dst; + *dst-- = tmp; + } + } + } + return str; +} + +/* itoa from K&R */ +void itoa(int n, char s[]) +{ + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + + if (sign < 0) + s[i++] = '-'; + + __reverse(s); + s[i] = '\0'; + return; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/labs.c b/programs/develop/libraries/kolibri-libc/source/stdlib/labs.c new file mode 100644 index 0000000000..2aca5fc182 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/labs.c @@ -0,0 +1,6 @@ +#include + +long labs(long a) +{ + return a>0 ? a : -a; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/ldiv.c b/programs/develop/libraries/kolibri-libc/source/stdlib/ldiv.c new file mode 100644 index 0000000000..e19a084ea2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/ldiv.c @@ -0,0 +1,6 @@ +#include + +ldiv_t ldiv(long num, long den) +{ + return (ldiv_t){ num/den, num%den }; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/libtcc1.c b/programs/develop/libraries/kolibri-libc/source/stdlib/libtcc1.c new file mode 100644 index 0000000000..e67ea59ea5 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/libtcc1.c @@ -0,0 +1,763 @@ +/* TCC runtime library. + Parts of this code are (c) 2002 Fabrice Bellard + + Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +//#include +#define TCC_TARGET_I386 + +#define W_TYPE_SIZE 32 +#define BITS_PER_UNIT 8 + +typedef int Wtype; +typedef unsigned int UWtype; +typedef unsigned int USItype; +typedef long long DWtype; +typedef unsigned long long UDWtype; + +struct DWstruct { + Wtype low, high; +}; + +typedef union +{ + struct DWstruct s; + DWtype ll; +} DWunion; + +typedef long double XFtype; +#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) +#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) + +/* the following deal with IEEE single-precision numbers */ +#define EXCESS 126 +#define SIGNBIT 0x80000000 +#define HIDDEN (1 << 23) +#define SIGN(fp) ((fp) & SIGNBIT) +#define EXP(fp) (((fp) >> 23) & 0xFF) +#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) +#define PACK(s,e,m) ((s) | ((e) << 23) | (m)) + +/* the following deal with IEEE double-precision numbers */ +#define EXCESSD 1022 +#define HIDDEND (1 << 20) +#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) +#define SIGND(fp) ((fp.l.upper) & SIGNBIT) +#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ + (fp.l.lower >> 22)) +#define HIDDEND_LL ((long long)1 << 52) +#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL) +#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m)) + +/* the following deal with x86 long double-precision numbers */ +#define EXCESSLD 16382 +#define EXPLD(fp) (fp.l.upper & 0x7fff) +#define SIGNLD(fp) ((fp.l.upper) & 0x8000) + +/* only for x86 */ +union ldouble_long { + long double ld; + struct { + unsigned long long lower; + unsigned short upper; + } l; +}; + +union double_long { + double d; +#if 1 + struct { + unsigned int lower; + int upper; + } l; +#else + struct { + int upper; + unsigned int lower; + } l; +#endif + long long ll; +}; + +union float_long { + float f; + unsigned int l; +}; + +/* XXX: we don't support several builtin supports for now */ +#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM) + +/* XXX: use gcc/tcc intrinsic ? */ +#if defined(TCC_TARGET_I386) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("divl %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#else +#error unsupported CPU type +#endif + +/* most of this code is taken from libgcc2.c from gcc */ +UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + DWunion ww; + DWunion nn, dd; + DWunion rr; + UWtype d0, d1, n0, n1, n2; + UWtype q0, q1; + UWtype b, bm; + + nn.ll = n; + dd.ll = d; + + d0 = dd.s.low; + d1 = dd.s.high; + n0 = nn.s.low; + n1 = nn.s.high; + +#if !defined(UDIV_NEEDS_NORMALIZATION) + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd (q1, n1, 0, n1, d0); + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = 0; + *rp = rr.ll; + } + } + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + count_leading_zeros (bm, d0); + + if (bm != 0) + { + /* Normalize, i.e. make the most significant bit of the + denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros (bm, d0); + + if (bm == 0) + { + /* From (n1 >= d0) /\ (the most significant bit of d0 is set), + conclude (the most significant bit of n1 is set) /\ (the + leading quotient digit q1 = 1). + + This special case is necessary, not an optimization. + (Shifts counts of W_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + if (rp != 0) + { + rr.s.low = n0 >> bm; + rr.s.high = 0; + *rp = rr.ll; + } + } +#endif /* UDIV_NEEDS_NORMALIZATION */ + + else + { + if (d1 > n1) + { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + /* 0q = NN / dd */ + + count_leading_zeros (bm, d1); + if (bm == 0) + { + /* From (n1 >= d1) /\ (the most significant bit of d1 is set), + conclude (the most significant bit of n1 is set) /\ (the + quotient digit q0 = 0 or 1). + + This special case is necessary, not an optimization. */ + + /* The condition on the next line takes advantage of that + n1 >= d1 (true due to program flow). */ + if (n1 > d1 || n0 >= d0) + { + q0 = 1; + sub_ddmmss (n1, n0, n1, n0, d1, d0); + } + else + q0 = 0; + + q1 = 0; + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + UWtype m1, m0; + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q0, n1, n2, n1, d1); + umul_ppmm (m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) + { + q0--; + sub_ddmmss (m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + if (rp != 0) + { + sub_ddmmss (n1, n0, n1, n0, m1, m0); + rr.s.low = (n1 << b) | (n0 >> bm); + rr.s.high = n1 >> bm; + *rp = rr.ll; + } + } + } + } + + ww.s.low = q0; + ww.s.high = q1; + return ww.ll; +} + +#define __negdi2(a) (-(a)) + +long long __divdi3(long long u, long long v) +{ + int c = 0; + DWunion uu, vv; + DWtype w; + + uu.ll = u; + vv.ll = v; + + if (uu.s.high < 0) { + c = ~c; + uu.ll = __negdi2 (uu.ll); + } + if (vv.s.high < 0) { + c = ~c; + vv.ll = __negdi2 (vv.ll); + } + w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); + if (c) + w = __negdi2 (w); + return w; +} + +// https://github.com/KaMeHb-UA/UE4m/blob/1d9ad5bfead06520570c7f24dad062f9f8717c1a/\ +Engine/Extras/ThirdPartyNotUE/emsdk/emscripten/incoming/system/lib/compiler-rt/lib/\ +builtins/divmoddi4.c +long long __divmoddi4(long long a, long long b, long long* rem) +{ + long long d = __divdi3(a, b); + *rem = a - (d * b); + return d; +} + +long long __moddi3(long long u, long long v) +{ + int c = 0; + DWunion uu, vv; + DWtype w; + + uu.ll = u; + vv.ll = v; + + if (uu.s.high < 0) { + c = ~c; + uu.ll = __negdi2 (uu.ll); + } + if (vv.s.high < 0) + vv.ll = __negdi2 (vv.ll); + + __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w); + if (c) + w = __negdi2 (w); + return w; +} + +unsigned long long __udivdi3(unsigned long long u, unsigned long long v) +{ + return __udivmoddi4 (u, v, (UDWtype *) 0); +} + +unsigned long long __umoddi3(unsigned long long u, unsigned long long v) +{ + UDWtype w; + + __udivmoddi4 (u, v, &w); + return w; +} + +/* XXX: fix tcc's code generator to do this instead */ +long long __ashrdi3(long long a, int b) +{ +#ifdef __TINYC__ + DWunion u; + u.ll = a; + if (b >= 32) { + u.s.low = u.s.high >> (b - 32); + u.s.high = u.s.high >> 31; + } else if (b != 0) { + u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b)); + u.s.high = u.s.high >> b; + } + return u.ll; +#else + return a >> b; +#endif +} + +/* XXX: fix tcc's code generator to do this instead */ +unsigned long long __lshrdi3(unsigned long long a, int b) +{ +#ifdef __TINYC__ + DWunion u; + u.ll = a; + if (b >= 32) { + u.s.low = (unsigned)u.s.high >> (b - 32); + u.s.high = 0; + } else if (b != 0) { + u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b)); + u.s.high = (unsigned)u.s.high >> b; + } + return u.ll; +#else + return a >> b; +#endif +} + +/* XXX: fix tcc's code generator to do this instead */ +long long __ashldi3(long long a, int b) +{ +#ifdef __TINYC__ + DWunion u; + u.ll = a; + if (b >= 32) { + u.s.high = (unsigned)u.s.low << (b - 32); + u.s.low = 0; + } else if (b != 0) { + u.s.high = ((unsigned)u.s.high << b) | ((unsigned)u.s.low >> (32 - b)); + u.s.low = (unsigned)u.s.low << b; + } + return u.ll; +#else + return a << b; +#endif +} + +#ifndef COMMIT_4ad186c5ef61_IS_FIXED +long long __tcc_cvt_ftol(long double x) +{ + unsigned c0, c1; + long long ret; + __asm__ __volatile__ ("fnstcw %0" : "=m" (c0)); + c1 = c0 | 0x0C00; + __asm__ __volatile__ ("fldcw %0" : : "m" (c1)); + __asm__ __volatile__ ("fistpll %0" : "=m" (ret)); + __asm__ __volatile__ ("fldcw %0" : : "m" (c0)); + return ret; +} +#endif + +#endif /* !__x86_64__ */ + +/* XXX: fix tcc's code generator to do this instead */ +float __floatundisf(unsigned long long a) +{ + DWunion uu; + XFtype r; + + uu.ll = a; + if (uu.s.high >= 0) { + return (float)uu.ll; + } else { + r = (XFtype)uu.ll; + r += 18446744073709551616.0; + return (float)r; + } +} + +double __floatundidf(unsigned long long a) +{ + DWunion uu; + XFtype r; + + uu.ll = a; + if (uu.s.high >= 0) { + return (double)uu.ll; + } else { + r = (XFtype)uu.ll; + r += 18446744073709551616.0; + return (double)r; + } +} + +long double __floatundixf(unsigned long long a) +{ + DWunion uu; + XFtype r; + + uu.ll = a; + if (uu.s.high >= 0) { + return (long double)uu.ll; + } else { + r = (XFtype)uu.ll; + r += 18446744073709551616.0; + return (long double)r; + } +} + +unsigned long long __fixunssfdi (float a1) +{ + register union float_long fl1; + register int exp; + register unsigned long l; + + fl1.f = a1; + + if (fl1.l == 0) + return (0); + + exp = EXP (fl1.l) - EXCESS - 24; + + l = MANT(fl1.l); + if (exp >= 41) + return (unsigned long long)-1; + else if (exp >= 0) + return (unsigned long long)l << exp; + else if (exp >= -23) + return l >> -exp; + else + return 0; +} + +unsigned long long __fixunsdfdi (double a1) +{ + register union double_long dl1; + register int exp; + register unsigned long long l; + + dl1.d = a1; + + if (dl1.ll == 0) + return (0); + + exp = EXPD (dl1) - EXCESSD - 53; + + l = MANTD_LL(dl1); + + if (exp >= 12) + return (unsigned long long)-1; + else if (exp >= 0) + return l << exp; + else if (exp >= -52) + return l >> -exp; + else + return 0; +} + +unsigned long long __fixunsxfdi (long double a1) +{ + register union ldouble_long dl1; + register int exp; + register unsigned long long l; + + dl1.ld = a1; + + if (dl1.l.lower == 0 && dl1.l.upper == 0) + return (0); + + exp = EXPLD (dl1) - EXCESSLD - 64; + + l = dl1.l.lower; + + if (exp > 0) + return (unsigned long long)-1; + else if (exp >= -63) + return l >> -exp; + else + return 0; +} + +long long __fixsfdi (float a1) +{ + long long ret; int s; + ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); + return s ? ret : -ret; +} + +long long __fixdfdi (double a1) +{ + long long ret; int s; + ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); + return s ? ret : -ret; +} + +long long __fixxfdi (long double a1) +{ + long long ret; int s; + ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); + return s ? ret : -ret; +} + +#if defined(TCC_TARGET_X86_64) && !defined(_WIN64) + +#ifndef __TINYC__ +#include +#include +#include +#else +/* Avoid including stdlib.h because it is not easily available when + cross compiling */ +#include /* size_t definition is needed for a x86_64-tcc to parse memset() */ + void *malloc(unsigned long long); + void *memset(void *s, int c, size_t n); + void free(void*); + void abort(void); +#endif + +enum __va_arg_type { + __va_gen_reg, __va_float_reg, __va_stack +}; + +//This should be in sync with the declaration on our include/stdarg.h +/* GCC compatible definition of va_list. */ +typedef struct { + unsigned int gp_offset; + unsigned int fp_offset; + union { + unsigned int overflow_offset; + char *overflow_arg_area; + }; + char *reg_save_area; +} __va_list_struct; + +#undef __va_start +#undef __va_arg +#undef __va_copy +#undef __va_end + +void __va_start(__va_list_struct *ap, void *fp) +{ + memset(ap, 0, sizeof(__va_list_struct)); + *ap = *(__va_list_struct *)((char *)fp - 16); + ap->overflow_arg_area = (char *)fp + ap->overflow_offset; + ap->reg_save_area = (char *)fp - 176 - 16; +} + +void *__va_arg(__va_list_struct *ap, + enum __va_arg_type arg_type, + int size, int align) +{ + size = (size + 7) & ~7; + align = (align + 7) & ~7; + switch (arg_type) { + case __va_gen_reg: + if (ap->gp_offset + size <= 48) { + ap->gp_offset += size; + return ap->reg_save_area + ap->gp_offset - size; + } + goto use_overflow_area; + + case __va_float_reg: + if (ap->fp_offset < 128 + 48) { + ap->fp_offset += 16; + return ap->reg_save_area + ap->fp_offset - 16; + } + size = 8; + goto use_overflow_area; + + case __va_stack: + use_overflow_area: + ap->overflow_arg_area += size; + ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align); + return ap->overflow_arg_area - size; + + default: +#ifndef __TINYC__ + fprintf(stderr, "unknown ABI type for __va_arg\n"); +#endif + abort(); + } +} + +#endif /* __x86_64__ */ + +/* Flushing for tccrun */ +#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386) + +void __clear_cache(void *beginning, void *end) +{ +} + +#elif defined(TCC_TARGET_ARM) + +#define _GNU_SOURCE +#include +#include +#include + +void __clear_cache(void *beginning, void *end) +{ +/* __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 */ +#if 1 + syscall(__ARM_NR_cacheflush, beginning, end, 0); +#else + __asm__ ("push {r7}\n\t" + "mov r7, #0xf0002\n\t" + "mov r2, #0\n\t" + "swi 0\n\t" + "pop {r7}\n\t" + "ret"); +#endif +} + +#else +#warning __clear_cache not defined for this architecture, avoid using tcc -run +#endif diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/llabs.c b/programs/develop/libraries/kolibri-libc/source/stdlib/llabs.c new file mode 100644 index 0000000000..87a10037f2 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/llabs.c @@ -0,0 +1,6 @@ +#include + +long long llabs(long long a) +{ + return a>0 ? a : -a; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/lldiv.c b/programs/develop/libraries/kolibri-libc/source/stdlib/lldiv.c new file mode 100644 index 0000000000..7d589145c5 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/lldiv.c @@ -0,0 +1,6 @@ +#include + +lldiv_t lldiv(long long num, long long den) +{ + return (lldiv_t){ num/den, num%den }; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/localtime.c b/programs/develop/libraries/kolibri-libc/source/stdlib/localtime.c new file mode 100644 index 0000000000..b9a2f97c23 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/localtime.c @@ -0,0 +1,32 @@ +#include +#include + +struct tm buffertime; + +struct tm * localtime (const time_t * timer) +/* non-standard! ignore parameter and return just time now */ +{ + int kos_date, kos_time; + kos_date = _ksys_get_date(); + kos_time = _ksys_get_clock(); + + int bcd_day = (kos_date >> 16); + int bcd_mon = ((kos_date & 0xFF00) >> 8); + int bcd_year = (kos_date & 0xFF); + 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_year = ((bcd_year & 0xF0)>>4)*10 + (bcd_year & 0x0F) + 100; + + buffertime.tm_wday = buffertime.tm_yday = buffertime.tm_isdst = -1; /* temporary */ + + int bcd_sec = (kos_time >> 16); + int bcd_min = ((kos_time & 0xFF00) >> 8); + int bcd_hour = (kos_time & 0xFF); + + buffertime.tm_sec = ((bcd_sec & 0xF0)>>4)*10 + (bcd_sec & 0x0F); + buffertime.tm_min = ((bcd_min & 0xF0)>>4)*10 + (bcd_min & 0x0F); + buffertime.tm_hour = ((bcd_hour & 0xF0)>>4)*10 + (bcd_hour & 0x0F); + + return &buffertime; +} + diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/malloc.c b/programs/develop/libraries/kolibri-libc/source/stdlib/malloc.c new file mode 100644 index 0000000000..e8d6a43984 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/malloc.c @@ -0,0 +1,6 @@ +#include +#include + +void *malloc(size_t size) { + return _ksys_alloc(size); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/mktime.c b/programs/develop/libraries/kolibri-libc/source/stdlib/mktime.c new file mode 100644 index 0000000000..a41c5c4f20 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/mktime.c @@ -0,0 +1,23 @@ +#include + +time_t mktime (struct tm * timeptr) +{ + int utcdiff = -3; + const int mon_days [] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + unsigned long int tyears, tdays, leaps, utc_hrs; + int i; + + tyears = timeptr->tm_year - 70 ;// tm->tm_year is from 1900. + leaps = (tyears + 2) / 4; // no of next two lines until year 2100. + i = (timeptr->tm_year - 100) / 100; + leaps -= ( (i/4)*3 + i%4 ); + tdays = 0; + for (i=0; i < timeptr->tm_mon; i++) tdays += mon_days[i]; + + tdays += timeptr->tm_mday-1; // days of month passed. + tdays = tdays + (tyears * 365) + leaps; + + utc_hrs = timeptr->tm_hour + utcdiff; // for your time zone. + return (tdays * 86400) + (utc_hrs * 3600) + (timeptr->tm_min * 60) + timeptr->tm_sec; +} + diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/realloc.c b/programs/develop/libraries/kolibri-libc/source/stdlib/realloc.c new file mode 100644 index 0000000000..0eb04767ac --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/realloc.c @@ -0,0 +1,6 @@ +#include +#include + +void *realloc(void *ptr, size_t newsize) { + return _ksys_realloc(ptr, newsize); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/strtol.c b/programs/develop/libraries/kolibri-libc/source/stdlib/strtol.c new file mode 100644 index 0000000000..a9141520e3 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/strtol.c @@ -0,0 +1,78 @@ +#include +#include +#include + +#define LONG_MIN (-2147483647L-1) +#define LONG_MAX (2147483647L) +#define ULONG_MAX (4294967295UL) + + +int getdigit(char ch, int base) +{ + if (isdigit(ch)) ch-= '0'; + else + if (isalpha(ch) && ch <= 'Z') ch = 10 + ch - 'A'; + else + if (isalpha(ch)) ch = 10 + ch - 'a'; + else + return -1; + + if (ch / base != 0) return -1; + + return ch; +} + + +long int strtol (const char* str, char** endptr, int base) +{ + long int res = 0; + int sign = 1; + + if (base > 36) + { + errno = EINVAL; + goto bye; + } + + while (isspace(*str)) str++; + + if (*str == '-') { sign = -1; str++; } + else + if (*str == '+') str++; + + if (base == 0 || base == 16) + { + if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) + { + base = 16; + str += 2; + } + } + + if (base == 0 && *str == '0') base = 8; + + if (base == 0) base = 10; + + + int digit; + while ((digit = getdigit(*str, base)) >= 0) + { + res = base * res + digit; + str++; + if (res < 0) + { + errno = ERANGE; + if (sign > 0) + res = LONG_MAX; + else + res = LONG_MIN; + } + } + +bye: + if (endptr) + *endptr = (char*)str; + + return res * sign; +} + diff --git a/programs/develop/libraries/kolibri-libc/source/stdlib/time.c b/programs/develop/libraries/kolibri-libc/source/stdlib/time.c new file mode 100644 index 0000000000..0e8af1dc50 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/stdlib/time.c @@ -0,0 +1,9 @@ +#include +#include + +time_t time (time_t* timer) +{ + time_t t = mktime(localtime(0)); + if (timer) *timer = t; + return t; +} diff --git a/programs/develop/libraries/kolibri-libc/source/string/memccpy.c b/programs/develop/libraries/kolibri-libc/source/string/memccpy.c new file mode 100644 index 0000000000..884cb76ccf --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/memccpy.c @@ -0,0 +1,14 @@ +#include + +void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + + c = (unsigned char)c; + for (; n && (*d=*s)!=c; n--, s++, d++); + +tail: + if (n) return d+1; + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/string/memchr.c b/programs/develop/libraries/kolibri-libc/source/string/memchr.c new file mode 100644 index 0000000000..348db6bece --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/memchr.c @@ -0,0 +1,24 @@ +/* memchr( const 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 + +void * memchr( const void * s, int c, size_t n ) +{ + const unsigned char * p = ( const unsigned char * ) s; + + while ( n-- ) + { + if ( *p == ( unsigned char ) c ) + { + return ( void * ) p; + } + + ++p; + } + + return NULL; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/memcmp.c b/programs/develop/libraries/kolibri-libc/source/string/memcmp.c new file mode 100644 index 0000000000..de156091b1 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/memcmp.c @@ -0,0 +1,26 @@ +/* memcmp( const 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 + +int memcmp( const void * s1, const void * s2, size_t n ) +{ + const unsigned char * p1 = ( const unsigned char * ) s1; + const unsigned char * p2 = ( const unsigned char * ) s2; + + while ( n-- ) + { + if ( *p1 != *p2 ) + { + return *p1 - *p2; + } + + ++p1; + ++p2; + } + + return 0; +} diff --git a/programs/develop/libraries/kolibri-libc/source/string/memcpy.c b/programs/develop/libraries/kolibri-libc/source/string/memcpy.c new file mode 100644 index 0000000000..0d707df047 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/memcpy.c @@ -0,0 +1,20 @@ +/* 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 + +void * memcpy( void * s1, const void * s2, size_t n ) +{ + char * dest = ( char * ) s1; + const char * src = ( const char * ) s2; + + while ( n-- ) + { + *dest++ = *src++; + } + + return s1; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/memmove.c b/programs/develop/libraries/kolibri-libc/source/string/memmove.c new file mode 100644 index 0000000000..e4dc719288 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/memmove.c @@ -0,0 +1,33 @@ +/* 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 + +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; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/memset.c b/programs/develop/libraries/kolibri-libc/source/string/memset.c new file mode 100644 index 0000000000..225f349d87 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/memset.c @@ -0,0 +1,20 @@ +/* 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 +#include + +void * memset( void * s, int c, size_t n ) +{ + unsigned char * p = ( unsigned char * ) s; + + while ( n-- ) + { + *p++ = ( unsigned char ) c; + } + + return s; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strcat.c b/programs/develop/libraries/kolibri-libc/source/string/strcat.c new file mode 100644 index 0000000000..bd90c10c33 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strcat.c @@ -0,0 +1,27 @@ +/* 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 + +char * strcat( char * s1, const char * s2 ) +{ + char * rc = s1; + + if ( *s1 ) + { + while ( *++s1 ) + { + /* EMPTY */ + } + } + + while ( ( *s1++ = *s2++ ) ) + { + /* EMPTY */ + } + + return rc; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strchr.c b/programs/develop/libraries/kolibri-libc/source/string/strchr.c new file mode 100644 index 0000000000..98bc094a93 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strchr.c @@ -0,0 +1,20 @@ +/* strchr( const char *, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +char * strchr( const char * s, int c ) +{ + do + { + if ( *s == ( char ) c ) + { + return ( char * ) s; + } + } while ( *s++ ); + + return NULL; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strcmp.c b/programs/develop/libraries/kolibri-libc/source/string/strcmp.c new file mode 100644 index 0000000000..93667668aa --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strcmp.c @@ -0,0 +1,14 @@ +/* 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 +#include +#include + +int strcmp(const char * s1, const char * s2) +{ + return _ksys_strcmp(s1, s2); +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strcoll.c b/programs/develop/libraries/kolibri-libc/source/string/strcoll.c new file mode 100644 index 0000000000..1ea0837f01 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strcoll.c @@ -0,0 +1,13 @@ +/* strcoll( 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 + +int strcoll( const char * s1, const char * s2 ) +{ + /* FIXME: This should access _PDCLIB_lc_collate. */ + return strcmp( s1, s2 ); +} diff --git a/programs/develop/libraries/kolibri-libc/source/string/strcpy.c b/programs/develop/libraries/kolibri-libc/source/string/strcpy.c new file mode 100644 index 0000000000..ce9176b85e --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strcpy.c @@ -0,0 +1,19 @@ +/* strcpy( 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 + +char * strcpy( char * s1, const char * s2 ) +{ + char * rc = s1; + + while ( ( *s1++ = *s2++ ) ) + { + /* EMPTY */ + } + + return rc; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strcspn.c b/programs/develop/libraries/kolibri-libc/source/string/strcspn.c new file mode 100644 index 0000000000..074d800560 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strcspn.c @@ -0,0 +1,30 @@ +/* strcspn( 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 + +size_t strcspn( const char * s1, const char * s2 ) +{ + size_t len = 0; + const char * p; + + while ( s1[len] ) + { + p = s2; + + while ( *p ) + { + if ( s1[len] == *p++ ) + { + return len; + } + } + + ++len; + } + + return len; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strdup.c b/programs/develop/libraries/kolibri-libc/source/string/strdup.c new file mode 100644 index 0000000000..73e3ac9efc --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strdup.c @@ -0,0 +1,10 @@ +#include +#include + +char* strdup(const char *str) +{ + char *buf = malloc(strlen(str) + 1); + buf[strlen(str)] = '\0'; + strcpy(buf, str); + return buf; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strerror.c b/programs/develop/libraries/kolibri-libc/source/string/strerror.c new file mode 100644 index 0000000000..43e174668f --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strerror.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include + +int errno; + +char* strerror(int err) +{ + char *msg; + switch(err){ + 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 EDOM: msg = "Numerical argument out of domain"; break; + case ERANGE: msg = "Result too large"; 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 EINPROGRESS: msg = "Operation now in progress"; break; + case EOPNOTSUPP: msg = "Operation not supported on transport endpoint"; break; + case EWOULDBLOCK: msg = "Operation would block"; break; + case ENOTCONN: msg = "Transport endpoint is not connected"; break; + case EALREADY: msg = "Operation already in progress"; break; + case EMSGSIZE: msg = "Message too long"; break; + case EADDRINUSE: msg = "Address already in use"; break; + case ECONNREFUSED: msg = "Connection refused"; break; + case ECONNRESET: msg = "Connection reset by peer"; break; + case EISCONN: msg = "Transport endpoint is already connected"; break; + case ETIMEDOUT: msg = "Connection timed out"; break; + case ECONNABORTED: msg = "Software caused connection abort"; break; + default: msg = "Unknown error"; break; + } + return msg; +} diff --git a/programs/develop/libraries/kolibri-libc/source/string/strlen.c b/programs/develop/libraries/kolibri-libc/source/string/strlen.c new file mode 100644 index 0000000000..fc3a1b6baa --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strlen.c @@ -0,0 +1,19 @@ +/* strlen( 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 + +size_t strlen( const char * s ) +{ + size_t rc = 0; + + while ( s[rc] ) + { + ++rc; + } + + return rc; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strncat.c b/programs/develop/libraries/kolibri-libc/source/string/strncat.c new file mode 100644 index 0000000000..5ec655e561 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strncat.c @@ -0,0 +1,29 @@ +/* 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 + +char * strncat( char * s1, const char * s2, size_t n ) +{ + char * rc = s1; + + while ( *s1 ) + { + ++s1; + } + + while ( n && ( *s1++ = *s2++ ) ) + { + --n; + } + + if ( n == 0 ) + { + *s1 = '\0'; + } + + return rc; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strncmp.c b/programs/develop/libraries/kolibri-libc/source/string/strncmp.c new file mode 100644 index 0000000000..72b54b4184 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strncmp.c @@ -0,0 +1,26 @@ +/* strncmp( const 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 + +int strncmp( const char * s1, const char * s2, size_t n ) +{ + while ( n && *s1 && ( *s1 == *s2 ) ) + { + ++s1; + ++s2; + --n; + } + + if ( n == 0 ) + { + return 0; + } + else + { + return ( *( unsigned char * )s1 - * ( unsigned char * )s2 ); + } +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strncpy.c b/programs/develop/libraries/kolibri-libc/source/string/strncpy.c new file mode 100644 index 0000000000..91e05621cd --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strncpy.c @@ -0,0 +1,29 @@ +/* strncpy( 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 + +char * strncpy( char * s1, const char * s2, size_t n ) +{ + char * rc = s1; + + while ( n && ( *s1++ = *s2++ ) ) + { + /* Cannot do "n--" in the conditional as size_t is unsigned and we have + to check it again for >0 in the next loop below, so we must not risk + underflow. + */ + --n; + } + + /* Checking against 1 as we missed the last --n in the loop above. */ + while ( n-- > 1 ) + { + *s1++ = '\0'; + } + + return rc; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strpbrk.c b/programs/develop/libraries/kolibri-libc/source/string/strpbrk.c new file mode 100644 index 0000000000..c58f87433e --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strpbrk.c @@ -0,0 +1,30 @@ +/* strpbrk( 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 + +char * strpbrk( const char * s1, const char * s2 ) +{ + const char * p1 = s1; + const char * p2; + + while ( *p1 ) + { + p2 = s2; + + while ( *p2 ) + { + if ( *p1 == *p2++ ) + { + return ( char * ) p1; + } + } + + ++p1; + } + + return NULL; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strrchr.c b/programs/develop/libraries/kolibri-libc/source/string/strrchr.c new file mode 100644 index 0000000000..4a36793424 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strrchr.c @@ -0,0 +1,27 @@ +/* strrchr( const char *, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +char * strrchr( const char * s, int c ) +{ + size_t i = 0; + + while ( s[i++] ) + { + /* EMPTY */ + } + + do + { + if ( s[--i] == ( char ) c ) + { + return ( char * ) s + i; + } + } while ( i ); + + return NULL; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strrev.c b/programs/develop/libraries/kolibri-libc/source/string/strrev.c new file mode 100644 index 0000000000..e96d5e2d8a --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strrev.c @@ -0,0 +1,15 @@ +#include + +char* strrev(char *p) +{ + char *q = p, *res = p, z; + while(q && *q) ++q; /* find eos */ + for(--q; p < q; ++p, --q) + { + z = *p; + *p = *q; + *q = z; + } + return res; +} + \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strspn.c b/programs/develop/libraries/kolibri-libc/source/string/strspn.c new file mode 100644 index 0000000000..96ce6d67b8 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strspn.c @@ -0,0 +1,37 @@ +/* strspn( 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 + +size_t strspn( const char * s1, const char * s2 ) +{ + size_t len = 0; + const char * p; + + while ( s1[ len ] ) + { + p = s2; + + while ( *p ) + { + if ( s1[len] == *p ) + { + break; + } + + ++p; + } + + if ( ! *p ) + { + return len; + } + + ++len; + } + + return len; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strstr.c b/programs/develop/libraries/kolibri-libc/source/string/strstr.c new file mode 100644 index 0000000000..d1f28b1ff9 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strstr.c @@ -0,0 +1,34 @@ +/* strstr( 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 + +char * strstr( const char * s1, const char * s2 ) +{ + const char * p1 = s1; + const char * p2; + + while ( *s1 ) + { + p2 = s2; + + while ( *p2 && ( *p1 == *p2 ) ) + { + ++p1; + ++p2; + } + + if ( ! *p2 ) + { + return ( char * ) s1; + } + + ++s1; + p1 = s1; + } + + return NULL; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/string/strtok.c b/programs/develop/libraries/kolibri-libc/source/string/strtok.c new file mode 100644 index 0000000000..1f756940e9 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strtok.c @@ -0,0 +1,30 @@ +/* strtok( 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 + +char* strtok(char* s, const char* delim) +{ + static char* savep; + char* res; + + if(s) + savep = NULL; + else + s = savep; + + if (*s == '\0') + return NULL; + s += strspn(s, delim); + if (*s == '\0') + return NULL; + res = s; + s += strcspn(s, delim); + savep = s + 1; + *s = '\0'; + return res; +} + diff --git a/programs/develop/libraries/kolibri-libc/source/string/strxfrm.c b/programs/develop/libraries/kolibri-libc/source/string/strxfrm.c new file mode 100644 index 0000000000..f24afd534d --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/string/strxfrm.c @@ -0,0 +1,26 @@ +/* strxfrm( 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 + +size_t strxfrm( char * s1, const char * s2, size_t n ) +{ + size_t len = strlen( s2 ); + + if ( len < n ) + { + /* Cannot use strncpy() here as the filling of s1 with '\0' is not part + of the spec. + */ + /* FIXME: This should access _PDCLIB_lc_collate. */ + while ( n-- && ( *s1++ = ( unsigned char )*s2++ ) ) + { + /* EMPTY */ + } + } + + return len; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/symbols.txt b/programs/develop/libraries/kolibri-libc/source/symbols.txt new file mode 100644 index 0000000000..50acbeb28f --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/symbols.txt @@ -0,0 +1,128 @@ +!____STDIO______ +clearerr +debug_printf +fclose +feof +ferror +fflush +fgetc +fgetpos +fgets +fopen +fprintf +fputc +fputs +fread +freopen +fscanf +fseek +fsetpos +ftell +fwrite +getchar +gets +perror +printf +puts +remove +rename +rewind +scanf +setbuf +setvbuf +snprintf +sprintf +sscanf +tmpfile +tmpnam +vfscanf +vprintf +vfscanf +vsnprintf +vsscanf +!____STDLIB____ +abs +atoi +atol +atoll +calloc +difftime +div +exit +free +itoa +labs +ldiv +llabs +lldiv +localtime +malloc +mktime +realloc +strtol +time +!____STRING____ +memcpy +memchr +memcmp +memmove +memset +strncat +strchr +strcmp +strcoll +strcpy +strcspn +strdup +strerror +strlen +strncat +strncmp +strncpy +strrchr +strrev +strspn +strstr +strtok +strxfrm +!____SYS____ +closedir +opendir +readdir +rewinddir +seekdir +telldir +!____UNISTD____ +!____MATH____ +acosh +asinh +atanh +acosh +frexp +hypot +ldexp +sinh +tanh +acos +asin +atan +atan2 +ceil +cos +exp +fabs +floor +fmod +log +modf +modfl +pow +pow2 +pow10 +!____LONGJMP____ +longjmp +setjmp +!____CTYPE____ +__is +!___CONIO___ +con_set_title diff --git a/programs/develop/libraries/kolibri-libc/source/sys/closedir.c b/programs/develop/libraries/kolibri-libc/source/sys/closedir.c new file mode 100644 index 0000000000..9dcca25f44 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/sys/closedir.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include + +int closedir(DIR *dir){ + if(dir == NULL){ + return -1; + }else{ + free(dir->objs); + free(dir); + return 0; + } +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/sys/opendir.c b/programs/develop/libraries/kolibri-libc/source/sys/opendir.c new file mode 100644 index 0000000000..7a44e40198 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/sys/opendir.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include +#include +#include +#include + +#define CHECK_DIR_ERR() if(_ksys_work_files(&inf)){ \ + free((void*)inf.p16); \ + errno = ENOTDIR; \ + return NULL; \ + } + +DIR* opendir(const char* path) +{ + DIR* list = malloc(sizeof(DIR)); + if(list==NULL){ + errno = ENOMEM; + return NULL; + } + + list->pos=0; + unsigned num_of_file=0; + ksys70_t inf; + + inf.p00 = 1; + inf.p04 = 0; + inf.p12 = 2; + inf.p16 = (unsigned) malloc(32+inf.p12*560); + inf.p20 = 0; + inf.p21 = (char*)path; + + CHECK_DIR_ERR(); + + num_of_file = *(unsigned*)(inf.p16+8); + inf.p12 = num_of_file; + free((void*)inf.p16); + inf.p16 = (unsigned) malloc(32+inf.p12*560); + list->objs = (struct dirent*)malloc(num_of_file*sizeof(struct dirent)); + + CHECK_DIR_ERR(); + + for(int i=0; iobjs[i].d_ino = i; + list->objs[i].d_type = *(unsigned*)(inf.p16+32+(264+40)*i); + strcpy(list->objs[i].d_name,(char*)(inf.p16+32+40+(264+40)*i)); + } + list->num_objs = num_of_file; + return list; +} + + diff --git a/programs/develop/libraries/kolibri-libc/source/sys/readdir.c b/programs/develop/libraries/kolibri-libc/source/sys/readdir.c new file mode 100644 index 0000000000..e5e68dbcdd --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/sys/readdir.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include +#include + +struct dirent* readdir(DIR *dir) +{ + if(dir->num_objs>dir->pos){ + dir->pos++; + return &dir->objs[dir->pos-1]; + }else{ + return NULL; + } +} diff --git a/programs/develop/libraries/kolibri-libc/source/sys/rewinddir.c b/programs/develop/libraries/kolibri-libc/source/sys/rewinddir.c new file mode 100644 index 0000000000..3fc549857b --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/sys/rewinddir.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include + +void rewinddir(DIR *dir){ + if(dir!=NULL){ + dir->pos=0; + } +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/sys/seekdir.c b/programs/develop/libraries/kolibri-libc/source/sys/seekdir.c new file mode 100644 index 0000000000..cb6c8e9463 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/sys/seekdir.c @@ -0,0 +1,12 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include + +void seekdir(DIR *dir, unsigned pos) +{ + if(dir==NULL || pos>dir->num_objs){ + return; + } + dir->pos=pos; + return; +} \ No newline at end of file diff --git a/programs/develop/libraries/kolibri-libc/source/sys/telldir.c b/programs/develop/libraries/kolibri-libc/source/sys/telldir.c new file mode 100644 index 0000000000..e3647a47c5 --- /dev/null +++ b/programs/develop/libraries/kolibri-libc/source/sys/telldir.c @@ -0,0 +1,12 @@ +/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */ + +#include + +unsigned telldir(DIR *dir) +{ + if(dir!=NULL){ + return dir->pos; + }else{ + return 0; + } +} \ No newline at end of file