diff --git a/programs/develop/ktcc/trunk/libc/build.bat b/programs/develop/ktcc/trunk/libc/build.bat index 9d5fc9a16f..cc8ef624d3 100644 --- a/programs/develop/ktcc/trunk/libc/build.bat +++ b/programs/develop/ktcc/trunk/libc/build.bat @@ -6,11 +6,11 @@ echo #################################################### rem #### CONFIG SECTION #### set LIBNAME=libck.a set INCLUDE=include -set CC=kos32-tcc +set CC=kos32-tcc set CFLAGS=-c -nostdinc -DGNUC -I"%cd%\%INCLUDE%" -Wall set AR=kos32-ar set ASM=fasm -set dirs=stdio memory kolibrisys string stdlib +set dirs=stdio memory kolibrisys string stdlib math rem #### END OF CONFIG SECTION #### set objs= diff --git a/programs/develop/ktcc/trunk/libc/include/ctype.h b/programs/develop/ktcc/trunk/libc/include/ctype.h index f4b79a0bbf..af84cfb694 100644 --- a/programs/develop/ktcc/trunk/libc/include/ctype.h +++ b/programs/develop/ktcc/trunk/libc/include/ctype.h @@ -4,31 +4,31 @@ ** 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 +#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 -extern char _is[128]; +extern char __is[128]; -#define isalnum(c)(_is[c] & ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */ -#define isalpha(c)(_is[c] & ALPHA ) /* 'a'-'z', 'A'-'Z' */ -#define iscntrl(c)(_is[c] & CNTRL ) /* 0-31, 127 */ -#define isdigit(c)(_is[c] & DIGIT ) /* '0'-'9' */ -#define isgraph(c)(_is[c] & GRAPH ) /* '!'-'~' */ -#define islower(c)(_is[c] & LOWER ) /* 'a'-'z' */ -#define isprint(c)(_is[c] & PRINT ) /* ' '-'~' */ -#define ispunct(c)(_is[c] & PUNCT ) /* !alnum && !cntrl && !space */ -#define isspace(c)(_is[c] & BLANK ) /* HT, LF, VT, FF, CR, ' ' */ -#define isupper(c)(_is[c] & UPPER ) /* 'A'-'Z' */ -#define isxdigit(c)(_is[c] & XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */ +#define isalnum(c)(__is[c] & __ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */ +#define isalpha(c)(__is[c] & __ALPHA ) /* 'a'-'z', 'A'-'Z' */ +#define iscntrl(c)(__is[c] & __CNTRL ) /* 0-31, 127 */ +#define isdigit(c)(__is[c] & __DIGIT ) /* '0'-'9' */ +#define isgraph(c)(__is[c] & __GRAPH ) /* '!'-'~' */ +#define islower(c)(__is[c] & __LOWER ) /* 'a'-'z' */ +#define isprint(c)(__is[c] & __PRINT ) /* ' '-'~' */ +#define ispunct(c)(__is[c] & __PUNCT ) /* !alnum && !cntrl && !space */ +#define isspace(c)(__is[c] & __BLANK ) /* HT, LF, VT, FF, CR, ' ' */ +#define isupper(c)(__is[c] & __UPPER ) /* 'A'-'Z' */ +#define isxdigit(c)(__is[c] & __XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */ #define isascii(c) (!((c)&(~0x7f))) #define toascii(c) ((c)&0x7f) diff --git a/programs/develop/ktcc/trunk/libc/include/float.h b/programs/develop/ktcc/trunk/libc/include/float.h index 5f1c6f73c7..f16f1f0cb5 100644 --- a/programs/develop/ktcc/trunk/libc/include/float.h +++ b/programs/develop/ktcc/trunk/libc/include/float.h @@ -27,7 +27,7 @@ #define DBL_MAX_10_EXP 308 /* horrible intel long double */ -#ifdef __i386__ +#if defined __i386__ || defined __x86_64__ #define LDBL_MANT_DIG 64 #define LDBL_DIG 18 diff --git a/programs/develop/ktcc/trunk/libc/include/math.h b/programs/develop/ktcc/trunk/libc/include/math.h index bc1f9fb319..bdf37d7d64 100644 --- a/programs/develop/ktcc/trunk/libc/include/math.h +++ b/programs/develop/ktcc/trunk/libc/include/math.h @@ -2,7 +2,7 @@ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -extern int stdcall integer(float number); +//extern int stdcall integer(float number); extern double acos(double _x); extern double asin(double _x); @@ -163,6 +163,11 @@ extern float log1pf(float); extern float gammaf_r(float, int *); extern float lgammaf_r(float, int *); +double round (double x); +long double roundl (long double x); + + + //#endif /* !_POSIX_SOURCE */ //#endif /* !__STRICT_ANSI__ */ //#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ diff --git a/programs/develop/ktcc/trunk/libc/include/stdarg.h b/programs/develop/ktcc/trunk/libc/include/stdarg.h index d562d6ddcc..06d592b93a 100644 --- a/programs/develop/ktcc/trunk/libc/include/stdarg.h +++ b/programs/develop/ktcc/trunk/libc/include/stdarg.h @@ -1,15 +1,75 @@ #ifndef _STDARG_H #define _STDARG_H -typedef char *va_list; +#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]; + +void __va_start(__va_list_struct *ap, void *fp); +void *__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 +#endif /* _STDARG_H */ diff --git a/programs/develop/ktcc/trunk/libc/include/stdbool.h b/programs/develop/ktcc/trunk/libc/include/stdbool.h index 6ed13a611a..d2ee446e70 100644 --- a/programs/develop/ktcc/trunk/libc/include/stdbool.h +++ b/programs/develop/ktcc/trunk/libc/include/stdbool.h @@ -6,5 +6,6 @@ #define bool _Bool #define true 1 #define false 0 +#define __bool_true_false_are_defined 1 #endif /* _STDBOOL_H */ diff --git a/programs/develop/ktcc/trunk/libc/include/stddef.h b/programs/develop/ktcc/trunk/libc/include/stddef.h index 89bd7b0941..791ba318cc 100644 --- a/programs/develop/ktcc/trunk/libc/include/stddef.h +++ b/programs/develop/ktcc/trunk/libc/include/stddef.h @@ -1,21 +1,46 @@ #ifndef _STDDEF_H #define _STDDEF_H -#define NULL ((void *)0) typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ssize_t; typedef __WCHAR_TYPE__ wchar_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; -#define offsetof(type, field) ((size_t) &((type *)0)->field) +typedef __PTRDIFF_TYPE__ intptr_t; +typedef __SIZE_TYPE__ uintptr_t; -/* need to do that because of glibc 2.1 bug (should have a way to test - presence of 'long long' without __GNUC__, or TCC should define - __GNUC__ ? */ -#if !defined(__int8_t_defined) && !defined(__dietlibc__) +#ifndef __int8_t_defined #define __int8_t_defined -typedef char int8_t; -typedef short int int16_t; -typedef int int32_t; -typedef long long int int64_t; +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; #endif +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offsetof(type, field) ((size_t)&((type *)0)->field) + +void *alloca(size_t size); + +#endif + +/* Older glibc require a wint_t from (when requested + by __need_wint_t, as otherwise stddef.h isn't allowed to + define this type). Note that this must be outside the normal + _STDDEF_H guard, so that it works even when we've included the file + already (without requiring wint_t). Some other libs define _WINT_T + if they've already provided that type, so we can use that as guard. + TCC defines __WINT_TYPE__ for us. */ +#if defined (__need_wint_t) +#ifndef _WINT_T +#define _WINT_T +typedef __WINT_TYPE__ wint_t; +#endif +#undef __need_wint_t #endif diff --git a/programs/develop/ktcc/trunk/libc/include/stdio.h b/programs/develop/ktcc/trunk/libc/include/stdio.h index aa5e5b612f..ff3ba8cd80 100644 --- a/programs/develop/ktcc/trunk/libc/include/stdio.h +++ b/programs/develop/ktcc/trunk/libc/include/stdio.h @@ -2,14 +2,18 @@ #define stdio_h #include "kolibrisys.h" - +#include +/* use stdarg.h typedef char *va_list; #define _roundsize(n) ( (sizeof(n) + 3) & ~3 ) #define va_start(ap,v) (ap = (va_list)&v+_roundsize(v)) #define va_arg(ap,t) ( *(t *)((ap += _roundsize(t)) - _roundsize(t)) ) #define va_end(ap) (ap = (va_list)0) +*/ +#ifndef NULL +# define NULL ((void*)0) +#endif -#define NULL ((void*)0) int format_print(char *dest, size_t maxlen,const char *fmt0, va_list argp); typedef struct { @@ -21,6 +25,9 @@ typedef struct { int mode; } FILE; +#define stderr ((FILE*)3) /* works inly for fprintf!!! */ + + #define FILE_OPEN_READ 0 #define FILE_OPEN_WRITE 1 #define FILE_OPEN_APPEND 2 @@ -55,5 +62,7 @@ extern int cdecl snprintf(char *dest, size_t size, const char *format,...); extern int cdecl sprintf(char *dest,const char *format,...); #define getc(a) fgetc(a) +char * fgets ( char * str, int num, FILE * stream ); +int putchar ( int character ); #endif diff --git a/programs/develop/ktcc/trunk/libc/include/stdlib.h b/programs/develop/ktcc/trunk/libc/include/stdlib.h index d1d91f2579..a474733a10 100644 --- a/programs/develop/ktcc/trunk/libc/include/stdlib.h +++ b/programs/develop/ktcc/trunk/libc/include/stdlib.h @@ -21,4 +21,10 @@ extern void* stdcall realloc(void* pointer,dword size); extern int rand (void); extern void srand (unsigned int seed); +double strtod (const char* str, char** endptr); +long double strtold (const char* str, char** endptr); +float strtof (const char* str, char** endptr); + + +#define exit(a) _ksys_exit() #endif \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/include/varargs.h b/programs/develop/ktcc/trunk/libc/include/varargs.h index daee29e874..d614366edb 100644 --- a/programs/develop/ktcc/trunk/libc/include/varargs.h +++ b/programs/develop/ktcc/trunk/libc/include/varargs.h @@ -1,11 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ #ifndef _VARARGS_H #define _VARARGS_H -#include - -#define va_dcl -#define va_alist __va_alist -#undef va_start -#define va_start(ap) ap = __builtin_varargs_start +#error "TinyCC no longer implements ." +#error "Revise your code to use ." #endif diff --git a/programs/develop/ktcc/trunk/libc/math/acos.asm b/programs/develop/ktcc/trunk/libc/math/acos.asm new file mode 100644 index 0000000000..ce7dc21ef0 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/acos.asm @@ -0,0 +1,23 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public acos_ as "acos" + +acos_: + +; acos(x) = atan(sqrt((1-x*x)/(x*x))) + + fld qword[esp+4] + fld st0 ;Duplicate X on tos. + fmul st0, st1 ;Compute X**2. + fld st0 ;Duplicate X**2 on tos. + fld1 ;Compute 1-X**2. + fsub st0, st1 + fdiv st0, st1 ;Compute (1-x**2)/X**2. + fsqrt ;Compute sqrt((1-X**2)/X**2). + fld1 ;To compute full arctangent. + fpatan ;Compute atan of the above. + ret + diff --git a/programs/develop/ktcc/trunk/libc/math/asin.c b/programs/develop/ktcc/trunk/libc/math/asin.c new file mode 100644 index 0000000000..fd7af3b0c7 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/asin.c @@ -0,0 +1,6 @@ +#include + +double asin(double x) +{ + return atan(sqrt(x * x / (1.0 - x * x))); +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/math/atan.asm b/programs/develop/ktcc/trunk/libc/math/atan.asm new file mode 100644 index 0000000000..6b7355150b --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/atan.asm @@ -0,0 +1,15 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public atan_ as "atan" + +atan_: + + fld qword[esp+4] + fld1 + fpatan + + ret + diff --git a/programs/develop/ktcc/trunk/libc/math/atan2.asm b/programs/develop/ktcc/trunk/libc/math/atan2.asm new file mode 100644 index 0000000000..b08e30fc5f --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/atan2.asm @@ -0,0 +1,15 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public atan2_ as "atan2" + +atan2_: + + fld qword[esp+8] + fld qword[esp+4] + fpatan + + ret + diff --git a/programs/develop/ktcc/trunk/libc/math/cos.asm b/programs/develop/ktcc/trunk/libc/math/cos.asm new file mode 100644 index 0000000000..fdbb3b9b56 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/cos.asm @@ -0,0 +1,14 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public cos_ as "cos" + +cos_: + + fld qword[esp+4] + fcos + + ret + diff --git a/programs/develop/ktcc/trunk/libc/math/cosh.c b/programs/develop/ktcc/trunk/libc/math/cosh.c new file mode 100644 index 0000000000..56f0f0aee7 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/cosh.c @@ -0,0 +1,6 @@ +#include + +double cosh (double x) +{ + return (exp(x) + exp(-x)) / 2; +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/math/exp.asm b/programs/develop/ktcc/trunk/libc/math/exp.asm new file mode 100644 index 0000000000..83c1a89963 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/exp.asm @@ -0,0 +1,60 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public exp_ as "exp" +public exp2_ as "exp2" + +SaveCW dw ? +MaskedCW dw ? + +; 2**x = 2**int(x) * 2**frac(x). +; We can easily compute 2**int(x) with fscale and +; 2**frac(x) using f2xm1. +exp2_int: + fstcw [SaveCW] + +; Modify the control word to truncate when rounding. + + fstcw [MaskedCW] + or byte ptr MaskedCW + 1, 1100b + fldcw [MaskedCW] + + fld st0 ;Duplicate tos. + fld st0 + frndint ;Compute integer portion. + + fxch ;Swap whole and int values. + fsub st0, st1 ;Compute fractional part. + + f2xm1 ;Compute 2**frac(x)-1. + fld1 + faddp st1, st0 ;Compute 2**frac(x). + + fxch ;Get integer portion. + fld1 ;Compute 1*2**int(x). + fscale + fstp st1 ;Remove st(1) (which is 1). + + fmulp st1, st0 ;Compute 2**int(x) * 2**frac(x). + fstp st1 ;Remove st1 + + fldcw [SaveCW] ;Restore rounding mode. + ret + +exp_: +; exp(x) = 2**(x * lg(e)) + + fld qword[esp+4] + fldl2e ;Put lg(e) onto the stack. + fmulp st1, st0 ;Compute x*lg(e). + call exp2_int;Compute 2**(x * lg(e)) + ret + +exp2_: + fld qword[esp+4] + call exp2_int;Compute 2 ** x + ret + + diff --git a/programs/develop/ktcc/trunk/libc/math/libtcc1.c b/programs/develop/ktcc/trunk/libc/math/libtcc1.c new file mode 100644 index 0000000000..2d36a205a1 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/libtcc1.c @@ -0,0 +1,754 @@ +/* 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 */ + +static 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; +} + +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() */ +extern void *malloc(unsigned long long); +extern void *memset(void *s, int c, size_t n); +extern void free(void*); +extern 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/ktcc/trunk/libc/math/log.asm b/programs/develop/ktcc/trunk/libc/math/log.asm new file mode 100644 index 0000000000..a9c0c58c4b --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/log.asm @@ -0,0 +1,18 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public log_ as "log" + +log_: + +; ln(x) = lg(x)/lg(e). + + fld qword[esp+4] + fld1 + fxch + fyl2x ;Compute 1*lg(x). + fldl2e ;Load lg(e). + fdivp st1, st0 ;Compute lg(x)/lg(e). + ret diff --git a/programs/develop/ktcc/trunk/libc/math/log10.asm b/programs/develop/ktcc/trunk/libc/math/log10.asm new file mode 100644 index 0000000000..34340e0c04 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/log10.asm @@ -0,0 +1,18 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public log10_ as "log10" + +log10_: + +; ln(x) = lg(x)/lg(e). + + fld qword[esp+4] + fld1 + fxch + fyl2x ;Compute 1*lg(x). + fldl2t ;Load lg(10). + fdivp st1, st0 ;Compute lg(x)/lg(10). + ret diff --git a/programs/develop/ktcc/trunk/libc/math/pow.c b/programs/develop/ktcc/trunk/libc/math/pow.c new file mode 100644 index 0000000000..c2485f3e2c --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/pow.c @@ -0,0 +1,6 @@ +#include + +double pow(double x, double y) +{ + return exp(y * log(x)); +} diff --git a/programs/develop/ktcc/trunk/libc/math/round.c b/programs/develop/ktcc/trunk/libc/math/round.c new file mode 100644 index 0000000000..73b297f6ee --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/round.c @@ -0,0 +1,9 @@ +#include + +double round (double x) +{ + if (x > 0) + return floor(x + 0.5); + else + return ceil(x - 0.5); +} diff --git a/programs/develop/ktcc/trunk/libc/math/roundl.c b/programs/develop/ktcc/trunk/libc/math/roundl.c new file mode 100644 index 0000000000..8ebf5637a4 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/roundl.c @@ -0,0 +1,9 @@ +#include + +long double roundl (long double x) +{ + if (x > 0) + return floor(x + 0.5); + else + return ceil(x - 0.5); +} diff --git a/programs/develop/ktcc/trunk/libc/math/sin.asm b/programs/develop/ktcc/trunk/libc/math/sin.asm new file mode 100644 index 0000000000..469bf7cb42 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/sin.asm @@ -0,0 +1,14 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public sin_ as "sin" + +sin_: + + fld qword[esp+4] + fsin + + ret + diff --git a/programs/develop/ktcc/trunk/libc/math/sinh.c b/programs/develop/ktcc/trunk/libc/math/sinh.c new file mode 100644 index 0000000000..1969267dd2 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/sinh.c @@ -0,0 +1,6 @@ +#include + +double sinh (double x) +{ + return (exp(x) - exp(-x)) / 2; +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/math/tan.asm b/programs/develop/ktcc/trunk/libc/math/tan.asm new file mode 100644 index 0000000000..0fc3b14f39 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/tan.asm @@ -0,0 +1,15 @@ + +format ELF +include 'proc32.inc' +section '.text' executable + +public tan_ as "tan" + +tan_: + + fld qword[esp+4] + fptan + fxch + + ret + diff --git a/programs/develop/ktcc/trunk/libc/math/tanh.c b/programs/develop/ktcc/trunk/libc/math/tanh.c new file mode 100644 index 0000000000..3c3a0190aa --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/math/tanh.c @@ -0,0 +1,8 @@ +#include + +double tanh (double x) +{ + double ex = exp(x), exm = exp(-x); + + return (ex - exm) / (ex + exm); +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/start/start.asm b/programs/develop/ktcc/trunk/libc/start/start.asm index eae03a659f..090dda6c73 100644 --- a/programs/develop/ktcc/trunk/libc/start/start.asm +++ b/programs/develop/ktcc/trunk/libc/start/start.asm @@ -1,30 +1,32 @@ format ELF section '.text' executable public start -extrn mf_init +public start as '_start' +;extrn mf_init extrn main -public argc as '__ARGS' - -__DEBUG__ equ 1 -__DEBUG_LEVEL__ equ 1 - -include 'DEBUG-FDO.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 0x0 ; 3. Start address + 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 1,'Start programm\n' - xor eax,eax - call mf_init -DEBUGF 1,' path "%s"\n params "%s"\n', path, params +;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 mov al, [path+buf_len-1] or al, [params+buf_len-1] @@ -83,25 +85,25 @@ DEBUGF 1,' path "%s"\n params "%s"\n', path, params jmp .parse .run: -DEBUGF 1,'call main(%x, %x) with params:\n', [argc], argv +;DEBUGF 'call main(%x, %x) with params:\n', [argc], argv if __DEBUG__ = 1 mov ecx, [argc] @@: lea esi, [ecx * 4 + argv-4] - DEBUGF 1,'%d) "%s"\n', cx, [esi] + DEBUGF '0x%x) "%s"\n', cx, [esi] loop @b end if push argv push [argc] call main .exit: -DEBUGF 1,'Exit from prog with code: %x\n', eax; +;DEBUGF 'Exit from prog\n'; xor eax,eax dec eax int 0x40 dd -1 .crash: -DEBUGF 1,'E:buffer overflowed\n' +;DEBUGF 'E:buffer overflowed\n' jmp .exit ;============================ push_param: @@ -120,6 +122,7 @@ push_param: .dont_add: ret ;============================== +public argc as '__argc' public params as '__argv' public path as '__path' @@ -131,5 +134,5 @@ argv rd max_parameters path rb buf_len params rb buf_len -section '.data' -include_debug_strings ; ALWAYS present in data section \ No newline at end of file +;section '.data' +;include_debug_strings ; ALWAYS present in data section \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/stdio/fgets.c b/programs/develop/ktcc/trunk/libc/stdio/fgets.c new file mode 100644 index 0000000000..574ec73b0e --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/stdio/fgets.c @@ -0,0 +1,25 @@ +#include + +char * fgets ( char * str, int num, FILE * stream ) +{ + int rd = 0; + char c; + while (rd < num - 1) + { + c = fgetc(stream); + if (EOF == c) break; + if ('\n' == c) + { + str[rd++] = c; + break; + } + else + str[rd++] = c; + } + if (0 == rd) return NULL; + else + { + str[rd] = '\0'; + return str; + } +} diff --git a/programs/develop/ktcc/trunk/libc/stdio/format_print.c b/programs/develop/ktcc/trunk/libc/stdio/format_print.c index 72c285d477..ed76d2d96b 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/format_print.c +++ b/programs/develop/ktcc/trunk/libc/stdio/format_print.c @@ -1,213 +1,230 @@ /* function for format output to the string + +Siemargl update formats as http://www.cplusplus.com/reference/cstdio/printf/, no wchar though +http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html is used too +%g explain https://support.microsoft.com/en-us/kb/43392 + +todo: +-%e +-simplify justifying +-fix %o, %x +-fix precision in %g +-%a +-NAN, INF +-%n nothing printed +-%17.18f digits maximum format +%C as w_char L'x' */ -#include + +//#include #include #include -//#include +#include #include +#include -int formatted_double_to_string(long double number,int format1,int format2,char *s) +enum flags_t { - double n; - double nbefor; - double nafter; - double v,v2; - long intdigit; - long beforpointdigit; - long div; - int i; - int pos; - int size; - int fmt1; - int fmt2; - long mul; - char buf[200]; + 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 +}; - size=(int)s; - n=(double)number; - if (n<0) {*s='-';s++;n=-n;} +int formatted_double_to_string_scientific(long double number, int format1, int format2, char *s, int flags) +{ + strcpy(s, "%e not implemented yet, sorry"); + return strlen(s); +} - fmt1=format1; - fmt2=format2; - if (fmt2>18) {fmt2=18;} //maximum of size long long type +int formatted_double_to_string(long double number, int format1, int format2, char *s, int flags) +{ + long double nafter, beforpointdigit; + long long intdigit, mul; + int div; + int i; + char* size; + int fmt1; + int fmt2; + char buf[100], *pbuf = buf; + char buf_low[50], *pbuf_lo = buf_low; - //clear array befor output - for(i=0;i<=200;i++) {buf[i]=0;} + if((flags & flag_point) == 0) format2 = 6; // default prec if no point spec - if ((fmt1>=0) && (n<1)) - { //formatted output if 0<=n<1 - mul=1; - for(i=0;i=0) && (buf[i]<=9)) {*s='0'+buf[i];} - else {*s='0';} - s++; - } - } + size = s; + if (number < 0) {*s++ = '-'; number = -number; } else - { //if n>=1 - //v=floorf(n+0.00000000000001); - beforpointdigit=floor(n+0.00000000000001); - //beforpointdigit=n; - nbefor=beforpointdigit; - nafter=n-nbefor; - - //print part of number befor point - mul=1; - for(i=0;i<200-2;i++) - { - mul=mul*10; - if ((beforpointdigit/mul)==0) {fmt1=i+1;break;} - } - - pos=0; - mul=mul/10; - for(i=0;i=0) && (buf[i]<=9)) {*s='0'+buf[i];} - s++; - } - - //print part of number after point - mul=1; - for(i=0;i=0) && (buf[i]<=9)) {*s='0'+buf[i];} - else {*s='0';} - s++; - } - + { + if (flags & flag_plus) *s++ = '+'; else + if (flags & flag_space_plus) *s++ = ' '; } - size=(int)s-size; - return(size); -} -int formatted_long_to_string(long long number,int fmt1,char *s) -{ - int i; - int pos; - int fmt; - int size; - int difference_pos; - long digit; - long mul; - long div; - char buf[200]; + fmt1 = 1; + fmt2 = format2; + if (fmt2 > 18) fmt2 = 18; //maximum size of long long type - //clear array befor output - for(i=0;i<200;i++) {buf[i]=0;} - digit=number; + beforpointdigit = floor(number + 0.00000000000001); + nafter = number - beforpointdigit; - size=(int)s; - if (digit<0) {*s='-';s++;digit=-digit;} - if (digit==0) {*s='0';s++;goto end;} + //print part of number before point + mul = 1; + for(i = 0; i < sizeof buf - 1; i++) + { + mul *= 10; + if ((beforpointdigit/mul) < 1.0) { fmt1 = i + 1; break; } + } + if (i == sizeof buf - 1 || fmt1 > 17) + { + strcpy(s, "[too big number for %f, %a]"); + return strlen(s); + } - mul=1; - for(i=0;i<200-2;i++) - { - mul=mul*10; - if ((digit/mul)==0) {fmt=i+1;break;} - } + mul /= 10; + while(mul > 1) + { + div = beforpointdigit / mul; + *pbuf++ = (char)div + '0'; + beforpointdigit = beforpointdigit - div * mul; + mul /= 10; + } + *pbuf++=(char)beforpointdigit + '0'; - difference_pos=i+1; + //print part of number after point + mul = 1; + for(i = 0; i < fmt2; i++) + { + nafter = nafter*10; + mul *= 10; + } - pos=0; - mul=mul/10; - for(i=0;i=difference_pos) fmt=fmt1; + mul /= 10; + for(i = 0; i < fmt2 - 1; i++) + { + div = intdigit / mul; + *pbuf_lo++=(char)div + '0'; + intdigit = intdigit - div * mul; + mul /= 10; + if (mul == 1) break; + } + *pbuf_lo++ = (char)intdigit + '0'; + + + memcpy(s, buf, pbuf - buf); s += pbuf - buf; + if (roundl(nafter) != 0 || fmt2 != 0) + { + *s++ = '.'; + memcpy(s, buf_low, pbuf_lo - buf_low); s += pbuf_lo - buf_low; + } else if (flags & flag_hash_sign) + *s++ = '.'; + + // right justifiyng and forward zeros + div = (s - size); + if ((flags & flag_left_just) == 0 && div < format1) + { + pbuf = size; + if ((flags & flag_lead_zeros) != 0) + if (*pbuf == '+' || *pbuf == '-' || *pbuf == ' ') { pbuf++; div--; } // sign already at place + for (i = 0; i < div; i++) + size[format1 - i - 1] = pbuf[div - 1 - i]; + for (i = 0; i < format1 - div - (pbuf - size); i++) + if (flags & flag_lead_zeros) + pbuf[i] = '0'; else - fmt=difference_pos; + pbuf[i] = ' '; - for(i=0;i=0) && (buf[i]<=9)) {*s='0'+buf[i];} - } - else - { - *s=' '; - } - s++; - } - end: - size=(int)s-size; - return(size); + return format1; + } + + return s - size; } -int formatted_hex_to_string(long long number,int fmt1,char flag_register,char *s) +int formatted_long_to_string(long long number, int format1, int prec, char *s, int flags) +{ + int i; + int fmt; + char* size = s; + long long digit; + long long mul; + int div; + char buf[100], *pbuf = buf; + + if (number == -9223372036854775807LL - 1) // overflow all our math, cant minus this + { + strcpy(buf, "9223372036854775808"); + pbuf += 19; + *s++ = '-'; + goto verybig; + } + + if (flags & flag_point) flags &= ~flag_lead_zeros; // conflicting flags + + if (number < 0) {*s++ = '-'; number = -number; } + else + { + if (flags & flag_plus) *s++ = '+'; else + if (flags & flag_space_plus) *s++ = ' '; + } + + digit = number; + + mul = (digit < 0) ? -1 : 1; + + for(i = 0; i < sizeof buf - 2; i++) + { + if (digit / mul < 10) { fmt = i + 1; break; } + mul *= 10; + } + + // add leading zeros + for(i = 0; i < prec - fmt; i++) *pbuf++ = '0'; + + for(i = 0; i < fmt - 1; i++) + { + div = digit / mul; + *pbuf++ = (char)div + '0'; + digit = digit - div * mul; + mul /= 10; + if (mul == 1 || mul == -1) break; + } + *pbuf++ = (char)digit + '0'; + +verybig: + memcpy(s, buf, pbuf - buf); s += pbuf - buf; + + // right justifiyng and forward zeros + div = (s - size); + if ((flags & flag_left_just) == 0 && div < format1) + { + pbuf = size; + if ((flags & flag_lead_zeros) != 0) + if (*pbuf == '+' || *pbuf == '-' || *pbuf == ' ') { pbuf++; div--; } // sign already at place + for (i = 0; i < div; i++) + size[format1 - i - 1] = pbuf[div - 1 - i]; + for (i = 0; i < format1 - div - (pbuf - size); i++) + if (flags & flag_lead_zeros) + pbuf[i] = '0'; + else + pbuf[i] = ' '; + + return format1; + } + + return s - size; +} + +int formatted_hex_to_string(long long number, int fmt1, char *s, int flags) { long n; int i,pos; - int fmt; +// int fmt; long size; int difference_pos; char xdigs_lower[16]="0123456789abcdef"; @@ -262,11 +279,11 @@ int formatted_hex_to_string(long long number,int fmt1,char flag_register,char *s return(size); } -int formatted_octa_to_string(long long number,int fmt1,char flag_register,char *s) +int formatted_octa_to_string(long long number, int fmt1, char *s, int flags) { long n; int i,pos; - int fmt; +// int fmt; long size; int difference_pos; char xdigs_lower[16]="012345678"; @@ -311,414 +328,225 @@ int formatted_octa_to_string(long long number,int fmt1,char flag_register,char * return(size); } -int format_print(char *dest, size_t maxlen,const char *fmt0, va_list argp) +//int vsnprintf (char * s, size_t n, const char * format, va_list arg ); +int format_print(char *dest, size_t maxlen, const char *fmt0, va_list argp) { - int i,j,k; - int length; - int fmt1,fmt2,stepen; - size_t pos,posc; - long long intdigit; - long double doubledigit; - float floatdigit; - const char *fmt,*fmtc; - char *s; - char *str; - char buffmt1[30]; - char buffmt2[30]; - char buf[1024]; - char format_flag; - char flag_point; - char flag_noformat; - char flag_long; - char flag_unsigned; - char flag_register; - char flag_plus; + int i; + int length; + int fmt1, fmt2; // width, precision + size_t pos, posc; + long long intdigit; + long double doubledigit; +// float floatdigit; + const char *fmt, *fmtc; // first point to %, fmtc points to specifier + char *s; // pointer to current dest char + char *str; + char buf[200]; // buffer for current argument value print representation + int format_flag; + int flag_long; // 2 = long double or long long int or wchar + int *point_to_n = NULL; + int flags; // parsed flags - fmt=fmt0; - s=dest; - pos=0; - while(pos maxlen) - length = maxlen - pos; - memcpy(s,str,length); - s=s+length;pos=pos+length; - break; - case 'd': - case 'D': - case 'i': - case 'I': - if (flag_long==0) {intdigit=va_arg(argp,int);} - if (flag_long==1) {intdigit=va_arg(argp,long);} - if (flag_long==2) {intdigit=va_arg(argp,long long);} - //intdigit=*((long*)argp); - //argp=argp+4; - if ((intdigit>0) && (flag_plus==1) && (pos+1<=maxlen)) - { - *s='+'; - s++; - pos++; - } - length=formatted_long_to_string(intdigit,0,buf); - if (pos + length > maxlen) - length = maxlen - pos; - memcpy(s,buf,length); - s=s+length;pos=pos+length; - break; - case 'o': - if (flag_long==0) {intdigit=va_arg(argp,int);} - if (flag_long==1) {intdigit=va_arg(argp,long);} - if (flag_long==2) {intdigit=va_arg(argp,long long);} - //intdigit=*((long int *)argp); - //argp=argp+4; - - length=formatted_octa_to_string(intdigit,0,flag_register,buf); - if (pos + length > maxlen) - length = maxlen - pos; - memcpy(s,buf,length); - s=s+length;pos=pos+length; - break; - case 'u': - case 'U': - if (flag_long==0) {intdigit=va_arg(argp,int);} - if (flag_long==1) {intdigit=va_arg(argp,long int);} - if (flag_long==2) {intdigit=va_arg(argp,long long);} - - if (flag_unsigned==1) { - if (intdigit<0) {intdigit=-intdigit;} - } - - length=formatted_long_to_string(intdigit,0,buf); - if (pos + length > maxlen) - length = maxlen - pos; - memcpy(s,buf,length); - s=s+length;pos=pos+length; - break; - case 'p': - case 'P': - case 'x': - case 'X': - if (flag_long==0) {intdigit=va_arg(argp,int);} - if (flag_long==1) {intdigit=va_arg(argp,long);} - if (flag_long==2) {intdigit=va_arg(argp,long long);} - //intdigit=*((long int *)argp); - //argp=argp+4; - - length=formatted_hex_to_string(intdigit,0,flag_register,buf); - if (pos + length > maxlen) - length = maxlen - pos; - memcpy(s,buf,length); - s=s+length;pos=pos+length; - break; - case 'z': - case 'Z': - intdigit=va_arg(argp,size_t); - - if (flag_unsigned==1) { - if (intdigit<0) {intdigit=-intdigit;} - } - - length=formatted_long_to_string(intdigit,0,buf); - if (pos + length > maxlen) - length = maxlen - pos; - memcpy(s,buf,length); - s=s+length;pos=pos+length; - break; - default:; - - } - } - else - { - fmt++; - flag_point=0; - flag_noformat=0; - fmt1=0; - fmt2=0; - j=0; - k=0; - for(i=pos+1;i=0;i--) - { - fmt1=fmt1+buffmt1[i]*stepen; - stepen=stepen*10; - } - stepen=1; - for(i=k-1;i>=0;i--) - { - fmt2=fmt2+buffmt2[i]*stepen; - stepen=stepen*10; - } - switch(*fmtc) - { - case 'f': - case 'F': - if (flag_long==0) {doubledigit=va_arg(argp,double);} - if (flag_long>=1) {doubledigit=va_arg(argp,long double);} - //doubledigit=*((double *)argp); - //sargp=argp+8; - length=formatted_double_to_string(doubledigit,fmt1,fmt2,buf); - if ((pos+length)0) && (flag_plus==1) && (pos+1 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 '*': + if (flag_point == 0) + fmt1 = va_arg(argp, int); + else + fmt2 = va_arg(argp, int); + break; + case '.': + flags |= flag_point; + break; + case 'l': case 'L': case '+': // valid chars - skip + case '-': case ' ': case '#': + break; + default: // must be error + strncpy(dest, "print format error - %width.precision", maxlen); + return -1; // format char not found - user error + } + fmt++; + } + } + + // do real work - format arguments values + + length = 0; + switch(*fmtc) + { + case 'n': + point_to_n = va_arg(argp, int*); + break; + case 'c': + if (pos + 1 <= maxlen) + { + buf[0] = (char)va_arg(argp, int); + length = 1; + } + break; + case 's': // special case - without buf + str = va_arg(argp, char*); + length = strlen(str); + if ((flags & flag_point) && (length > fmt2)) length = fmt2; // cut by precision + if (pos + length > maxlen) length = maxlen - pos; + memcpy(s, str ,length); + s += length; + pos += length; + break; + case 'd': case 'i': case 'u': case 'U': + if (flag_long == 0) intdigit = va_arg(argp, int); else + if (flag_long == 1) intdigit = va_arg(argp, long); else + if (flag_long == 2) intdigit = va_arg(argp, long long); + length = formatted_long_to_string(intdigit, fmt1, fmt2, buf, flags); + break; + case 'o': + if (flag_long == 0) intdigit = va_arg(argp, int); else + if (flag_long == 1) intdigit = va_arg(argp, long); else + if (flag_long == 2) intdigit = va_arg(argp, long long); + length = formatted_octa_to_string(intdigit, fmt1, buf, flags); + break; + case 'p': case 'P': case 'x': case 'X': + if (flag_long == 0) intdigit = va_arg(argp, int); else + if (flag_long == 1) intdigit = va_arg(argp, long); else + if (flag_long == 2) intdigit = va_arg(argp, long long); + length=formatted_hex_to_string(intdigit, fmt1, buf, flags); + break; + case 'a': case 'A': case 'f': case 'F': + if (flag_long <= 1) doubledigit = va_arg(argp, double); else + if (flag_long == 2) doubledigit = va_arg(argp, long double); + length = formatted_double_to_string(doubledigit, fmt1, fmt2, buf, flags); + break; + case 'e': case 'E': + if (flag_long <= 1) doubledigit = va_arg(argp, double); else + if (flag_long == 2) doubledigit = va_arg(argp, long double); + length = formatted_double_to_string_scientific(doubledigit, fmt1, fmt2, buf, flags); + break; + case 'g': case 'G': + //prec special case, this is just workaround + if (flag_long <= 1) doubledigit = va_arg(argp, double); else + if (flag_long == 2) doubledigit = va_arg(argp, long double); + length = formatted_double_to_string(doubledigit, fmt1, fmt2, buf, flags); + i = formatted_double_to_string_scientific(doubledigit, fmt1, fmt2, buf + sizeof buf / 2, flags); + if(length > i) + { + memcpy(buf, buf + sizeof buf / 2, i); + length = i; + } + break; + } + if (*fmtc != 's' && length > 0) // skip multiple string copying + { + if (pos + length > maxlen) length = maxlen - pos; + memcpy(s, buf, length); + s += length; + pos += length; + } + fmt = fmtc + 1; + } + + if (point_to_n) *point_to_n = pos; + return(pos); } diff --git a/programs/develop/ktcc/trunk/libc/stdio/fprintf.c b/programs/develop/ktcc/trunk/libc/stdio/fprintf.c index 5d42c1c31e..38ca22ec8a 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fprintf.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fprintf.c @@ -1,8 +1,6 @@ #include #include -int format_print(char *dest, size_t maxlen, const char *fmt,va_list argp); - int fprintf(FILE* file, const char* format, ...) { va_list arg; @@ -15,7 +13,10 @@ int printed; //data[0]=(int)&arg-(int)&format; printed=format_print(buf,8191, format,arg); - fwrite(buf,printed,1,file); + if (file == stderr) + debug_out_str(buf); + else + fwrite(buf,printed,1,file); free(buf); return(printed); diff --git a/programs/develop/ktcc/trunk/libc/stdio/printf.c b/programs/develop/ktcc/trunk/libc/stdio/printf.c index ed19a91f87..2e2535b1c2 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/printf.c +++ b/programs/develop/ktcc/trunk/libc/stdio/printf.c @@ -7,7 +7,11 @@ char* dllname="/sys/lib/console.obj"; int console_init_status; char* imports[] = {"START","version","con_init","con_write_asciiz","con_printf","con_exit",NULL}; -char* caption = "Console test - colors"; +char* caption = "Console app"; +extern int __argc; +extern char** __argv; +extern char* __path; + dword* dll_ver; void stdcall (* con_init)(dword wnd_width, dword wnd_height, dword scr_width, dword scr_height, const char* title); @@ -32,6 +36,7 @@ void printf_link(struct import *exp, char** imports){ _ksys_cofflib_getproc(exp, imports[5]); } + int init_console(void) { struct import * hDll; @@ -41,15 +46,15 @@ int init_console(void) return 1; } printf_link(hDll, imports); - debug_out_str("dll loaded\n"); +// debug_out_str("dll loaded\n"); - con_init(-1, -1, -1, -1, caption); + con_init(-1, -1, -1, -1, caption); //__argv[0] && __path dont work return(0); } int printf(const char *format,...) { - int i; + int i = 0; int printed_simbols; va_list arg; char simbol[]={"%s"}; diff --git a/programs/develop/ktcc/trunk/libc/stdio/putchar.c b/programs/develop/ktcc/trunk/libc/stdio/putchar.c new file mode 100644 index 0000000000..ffddbfece7 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/stdio/putchar.c @@ -0,0 +1,7 @@ +#include + +int putchar ( int ch ) +{ + printf("%c", ch); + return ch; +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libc/stdlib/strtod.c b/programs/develop/ktcc/trunk/libc/stdlib/strtod.c new file mode 100644 index 0000000000..29b2bfaf3b --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/stdlib/strtod.c @@ -0,0 +1,70 @@ +#include +#include + +double strtod (const char* str, char** endptr) +{ + double res = 0.0; + int pwr = 0, pwr1, esign = 1, sign = 1; + + while (isspace(*str)) str++; + + if (*str == '-') { sign = -1; str++; } + else + if (*str == '+') str++; + + + while (isdigit(*str)) + { + res = 10 * res + (*str - '0'); + str++; + } + + if (*str =='.') + { + str++; + double div = 10.0; + while (isdigit(*str)) + { + res += (*str - '0') / div; + str++; + div *= 10; + } + } + + if (*str =='e' || *str =='E') + { + str++; + if (*str == '-') { esign = -1; str++; } + else + if (*str == '+') str++; + + while (isdigit(*str)) + { + pwr = 10.0 * pwr + (*str - '0'); + str++; + } + + // fck, i've no pow() yet + // res = res * pow(10, pwr); + for (pwr1 = pwr; pwr1 !=0; pwr1--) + if (esign == 1) + res *= 10; + else + res /= 10; + + } + if (endptr) + *endptr = (char*)str; + + return res * sign; +} + +long double strtold (const char* str, char** endptr) +{ + return (long double)strtod(str, endptr); +} + +float strtof (const char* str, char** endptr) +{ + return (float)strtod(str, endptr); +} diff --git a/programs/develop/ktcc/trunk/libc/string/is.c b/programs/develop/ktcc/trunk/libc/string/is.c index 9213614423..19265ec0d1 100644 --- a/programs/develop/ktcc/trunk/libc/string/is.c +++ b/programs/develop/ktcc/trunk/libc/string/is.c @@ -1,5 +1,5 @@ #include "ctype.h" -int __is[128] = { +char __is[128] = { 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,