/programs/develop/ktcc/trunk/libc/build.bat |
---|
10,7 → 10,7 |
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= |
/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) |
/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 |
/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 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 */ |
/programs/develop/ktcc/trunk/libc/include/stdarg.h |
---|
1,15 → 1,75 |
#ifndef _STDARG_H |
#define _STDARG_H |
#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 */ |
/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 */ |
/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 <stddef.h> (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 |
/programs/develop/ktcc/trunk/libc/include/stdio.h |
---|
2,14 → 2,18 |
#define stdio_h |
#include "kolibrisys.h" |
#include <stdarg.h> |
/* 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 |
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 sprintf(char *dest,const char *format,...); |
#define getc(a) fgetc(a) |
char * fgets ( char * str, int num, FILE * stream ); |
int putchar ( int character ); |
#endif |
/programs/develop/ktcc/trunk/libc/include/stdlib.h |
---|
21,4 → 21,10 |
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 |
/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 <stdarg.h> |
#error "TinyCC no longer implements <varargs.h>." |
#error "Revise your code to use <stdarg.h>." |
#define va_dcl |
#define va_alist __va_alist |
#undef va_start |
#define va_start(ap) ap = __builtin_varargs_start |
#endif |
/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 |
/programs/develop/ktcc/trunk/libc/math/asin.c |
---|
0,0 → 1,6 |
#include <math.h> |
double asin(double x) |
{ |
return atan(sqrt(x * x / (1.0 - x * x))); |
} |
/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 |
/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 |
/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 |
/programs/develop/ktcc/trunk/libc/math/cosh.c |
---|
0,0 → 1,6 |
#include <math.h> |
double cosh (double x) |
{ |
return (exp(x) + exp(-x)) / 2; |
} |
/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 |
/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 <stdint.h> |
#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 <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#else |
/* Avoid including stdlib.h because it is not easily available when |
cross compiling */ |
#include <stddef.h> /* 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 <unistd.h> |
#include <sys/syscall.h> |
#include <stdio.h> |
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 |
/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 |
/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 |
/programs/develop/ktcc/trunk/libc/math/pow.c |
---|
0,0 → 1,6 |
#include <math.h> |
double pow(double x, double y) |
{ |
return exp(y * log(x)); |
} |
/programs/develop/ktcc/trunk/libc/math/round.c |
---|
0,0 → 1,9 |
#include <math.h> |
double round (double x) |
{ |
if (x > 0) |
return floor(x + 0.5); |
else |
return ceil(x - 0.5); |
} |
/programs/develop/ktcc/trunk/libc/math/roundl.c |
---|
0,0 → 1,9 |
#include <math.h> |
long double roundl (long double x) |
{ |
if (x > 0) |
return floor(x + 0.5); |
else |
return ceil(x - 0.5); |
} |
/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 |
/programs/develop/ktcc/trunk/libc/math/sinh.c |
---|
0,0 → 1,6 |
#include <math.h> |
double sinh (double x) |
{ |
return (exp(x) - exp(-x)) / 2; |
} |
/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 |
/programs/develop/ktcc/trunk/libc/math/tanh.c |
---|
0,0 → 1,8 |
#include <math.h> |
double tanh (double x) |
{ |
double ex = exp(x), exm = exp(-x); |
return (ex - exm) / (ex + exm); |
} |
/programs/develop/ktcc/trunk/libc/start/start.asm |
---|
1,19 → 1,17 |
format ELF |
section '.text' executable |
public start |
extrn mf_init |
public start as '_start' |
;extrn mf_init |
extrn main |
public argc as '__ARGS' |
;include 'debug2.inc' |
__DEBUG__=0 |
__DEBUG__ equ 1 |
__DEBUG_LEVEL__ equ 1 |
include 'DEBUG-FDO.INC' |
;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 |
20,11 → 18,15 |
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,12 → 85,12 |
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 |
95,13 → 97,13 |
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 |
.dont_add: |
ret |
;============================== |
public argc as '__argc' |
public params as '__argv' |
public path as '__path' |
131,5 → 134,5 |
path rb buf_len |
params rb buf_len |
section '.data' |
include_debug_strings ; ALWAYS present in data section |
;section '.data' |
;include_debug_strings ; ALWAYS present in data section |
/programs/develop/ktcc/trunk/libc/stdio/fgets.c |
---|
0,0 → 1,25 |
#include <stdio.h> |
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; |
} |
} |
/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 <kolibrisys.h> |
//#include <kolibrisys.h> |
#include <string.h> |
#include <stdio.h> |
//#include <ctype.h> |
#include <ctype.h> |
#include <math.h> |
#include <stdarg.h> |
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; |
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 |
}; |
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); |
} |
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; |
int pos; |
int size; |
char* size; |
int fmt1; |
int fmt2; |
long mul; |
char buf[200]; |
char buf[100], *pbuf = buf; |
char buf_low[50], *pbuf_lo = buf_low; |
size=(int)s; |
n=(double)number; |
if (n<0) {*s='-';s++;n=-n;} |
if((flags & flag_point) == 0) format2 = 6; // default prec if no point spec |
fmt1=format1; |
size = s; |
if (number < 0) {*s++ = '-'; number = -number; } |
else |
{ |
if (flags & flag_plus) *s++ = '+'; else |
if (flags & flag_space_plus) *s++ = ' '; |
} |
fmt1 = 1; |
fmt2=format2; |
if (fmt2>18) {fmt2=18;} //maximum of size long long type |
if (fmt2 > 18) fmt2 = 18; //maximum size of long long type |
//clear array befor output |
for(i=0;i<=200;i++) {buf[i]=0;} |
beforpointdigit = floor(number + 0.00000000000001); |
nafter = number - beforpointdigit; |
if ((fmt1>=0) && (n<1)) |
{ //formatted output if 0<=n<1 |
//print part of number before point |
mul=1; |
for(i=0;i<fmt2;i++) |
{n=n*10;mul=mul*10;} |
n=n*10; |
n=ceil(n); |
intdigit=floor(n); |
//intdigit=n; |
intdigit=(intdigit/10); |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt2-1;i++) |
for(i = 0; i < sizeof buf - 1; i++) |
{ |
div=intdigit/mul; |
buf[pos]=(char)div; |
pos++; |
intdigit=intdigit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
mul *= 10; |
if ((beforpointdigit/mul) < 1.0) { fmt1 = i + 1; break; } |
} |
buf[pos]=(char)intdigit; |
*s='0';s++; |
*s='.';s++; |
for(i=0;i<format2;i++) |
if (i == sizeof buf - 1 || fmt1 > 17) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
else {*s='0';} |
s++; |
strcpy(s, "[too big number for %f, %a]"); |
return strlen(s); |
} |
} |
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 /= 10; |
while(mul > 1) |
{ |
mul=mul*10; |
if ((beforpointdigit/mul)==0) {fmt1=i+1;break;} |
} |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt1-1;i++) |
{ |
div=beforpointdigit/mul; |
buf[pos]=(char)div; |
pos++; |
*pbuf++ = (char)div + '0'; |
beforpointdigit=beforpointdigit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
mul /= 10; |
} |
buf[pos]=(char)beforpointdigit; |
*pbuf++=(char)beforpointdigit + '0'; |
for(i=0;i<fmt1;i++) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
s++; |
} |
//print part of number after point |
mul=1; |
for(i=0;i<fmt2;i++) |
{nafter=nafter*10;mul=mul*10;} |
{ |
nafter=nafter*10; |
nafter=ceil(nafter); |
intdigit=floor(nafter); |
//intdigit=nafter; |
intdigit=intdigit/10; |
mul *= 10; |
} |
pos=0; |
mul=mul/10; |
intdigit = roundl(nafter); |
mul /= 10; |
for(i=0;i<fmt2-1;i++) |
{ |
div=intdigit/mul; |
buf[pos]=(char)div; |
pos++; |
*pbuf_lo++=(char)div + '0'; |
intdigit=intdigit-div*mul; |
mul=mul/10; |
mul /= 10; |
if (mul==1) break; |
} |
buf[pos]=(char)intdigit; |
*s='.';s++; |
for(i=0;i<format2;i++) |
*pbuf_lo++ = (char)intdigit + '0'; |
memcpy(s, buf, pbuf - buf); s += pbuf - buf; |
if (roundl(nafter) != 0 || fmt2 != 0) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
else {*s='0';} |
s++; |
*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 |
pbuf[i] = ' '; |
return format1; |
} |
return s - size; |
} |
size=(int)s-size; |
return(size); |
} |
int formatted_long_to_string(long long number,int fmt1,char *s) |
int formatted_long_to_string(long long number, int format1, int prec, char *s, int flags) |
{ |
int i; |
int pos; |
int fmt; |
int size; |
int difference_pos; |
long digit; |
long mul; |
long div; |
char buf[200]; |
char* size = s; |
long long digit; |
long long mul; |
int div; |
char buf[100], *pbuf = buf; |
//clear array befor output |
for(i=0;i<200;i++) {buf[i]=0;} |
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; |
size=(int)s; |
if (digit<0) {*s='-';s++;digit=-digit;} |
if (digit==0) {*s='0';s++;goto end;} |
mul = (digit < 0) ? -1 : 1; |
mul=1; |
for(i=0;i<200-2;i++) |
for(i = 0; i < sizeof buf - 2; i++) |
{ |
mul=mul*10; |
if ((digit/mul)==0) {fmt=i+1;break;} |
if (digit / mul < 10) { fmt = i + 1; break; } |
mul *= 10; |
} |
difference_pos=i+1; |
// add leading zeros |
for(i = 0; i < prec - fmt; i++) *pbuf++ = '0'; |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt-1;i++) |
{ |
div=digit/mul; |
buf[pos]=(char)div; |
pos++; |
*pbuf++ = (char)div + '0'; |
digit=digit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
mul /= 10; |
if (mul == 1 || mul == -1) break; |
} |
buf[pos]=(char)digit; |
*pbuf++ = (char)digit + '0'; |
if (fmt1>=difference_pos) fmt=fmt1; |
else |
fmt=difference_pos; |
verybig: |
memcpy(s, buf, pbuf - buf); s += pbuf - buf; |
for(i=0;i<fmt;i++) |
// right justifiyng and forward zeros |
div = (s - size); |
if ((flags & flag_left_just) == 0 && div < format1) |
{ |
if (i<difference_pos) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
} |
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 |
{ |
*s=' '; |
pbuf[i] = ' '; |
return format1; |
} |
s++; |
return s - size; |
} |
end: |
size=(int)s-size; |
return(size); |
} |
int formatted_hex_to_string(long long number,int fmt1,char flag_register,char *s) |
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 |
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,28 → 328,24 |
return(size); |
} |
//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 i; |
int length; |
int fmt1,fmt2,stepen; |
int fmt1, fmt2; // width, precision |
size_t pos,posc; |
long long intdigit; |
long double doubledigit; |
float floatdigit; |
const char *fmt,*fmtc; |
char *s; |
// float floatdigit; |
const char *fmt, *fmtc; // first point to %, fmtc points to specifier |
char *s; // pointer to current dest char |
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; |
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; |
339,386 → 352,201 |
pos=0; |
while(pos<maxlen) |
{ |
if (*fmt=='%') |
if (*fmt != '%') // usual char |
{ |
if ('\0' == (*s++ = *fmt++)) break; |
pos++; |
continue; |
} |
if (*(fmt+1)=='%') |
if (*(fmt + 1) == '%') // %% |
{ |
*s='%'; |
s++; |
fmt=fmt+2; |
pos++; |
goto exit_check; |
*s++ = '%'; pos++; |
fmt += 2; |
continue; |
} |
//checking to containg format in the string |
fmtc=fmt; |
posc=pos; |
flags = 0; |
format_flag=0; |
flag_long=0; |
flag_unsigned=0; |
flag_register=0; |
flag_plus=0; |
while((*fmtc!='\0') || (*fmtc!=0)) |
flag_long = 0; // 2 = long double or long long int or wchar |
while(*fmtc != '\0' && !format_flag) // searching end of format |
{ |
fmtc++; |
posc++; |
fmtc++; posc++; |
switch(*fmtc) |
{ |
case 'c': |
case 'C': |
case 'a': |
format_flag=1; |
flags |= flag_unsigned; |
break; |
case 'd': |
case 'D': |
case 'i': |
case 'I': |
case 'A': |
format_flag=1; |
flags |= flag_unsigned | flag_register; |
break; |
case 'e': |
case 'c': case 'd': case 'i': case 'e': case 'f': case 'g': case 's': case 'n': |
format_flag=1; |
break; |
case 'E': |
case 'E': case 'F': case 'G': |
format_flag=1; |
flag_long=1; |
flags |= flag_register; |
break; |
case 'f': |
format_flag=1; |
break; |
case 'F': |
format_flag=1; |
flag_long=1; |
break; |
case 'g': |
format_flag=1; |
break; |
case 'G': |
format_flag=1; |
flag_long=1; |
break; |
case 'l': |
flag_long=1; |
flag_long = flag_long ? 2 : 1; // ll.eq.L |
break; |
case 'L': |
flag_long=2; |
break; |
case 'o': |
case 'o': case 'u': case 'x': case 'p': |
format_flag=1; |
flags |= flag_unsigned; |
break; |
case 's': |
case 'S': |
case 'X': case 'P': |
format_flag=1; |
flags |= flag_unsigned | flag_register; |
break; |
case 'u': |
case 'U': |
format_flag=1; |
flag_unsigned=1; |
case '+': |
flags |= flag_plus; |
break; |
case 'x': |
case 'p': |
format_flag=1; |
case '-': |
flags |= flag_left_just; |
break; |
case 'X': |
case 'P': |
flag_register=1; |
format_flag=1; |
case ' ': // space |
flags |= flag_space_plus; |
break; |
case 'z': |
case 'Z': |
format_flag=1; |
flag_unsigned=1; |
case '#': |
flags |= flag_hash_sign; |
break; |
case '+': |
flag_plus=1; |
case '*': case '.': // just skip |
break; |
default:; |
default: |
if(isdigit(*fmtc)) break; |
strncpy(dest, "print format error - in % invalid char found", maxlen); |
return -1; // non format char found - user error |
} |
if ((*fmtc=='%') || (*fmtc==' ')) break; |
if (format_flag==1) break; |
} |
if (format_flag==0) |
{ |
*s=*fmt; |
fmt++; |
s++; |
pos++; |
strncpy(dest, "print format error - % without format specifier", maxlen); |
return -1; // format char not found - user error |
} |
else |
{ |
if ((posc-pos)==1) |
{//simbols % and format simbol near tothere(for example %c ) |
fmt=fmtc+1; |
switch(*fmtc) |
{ |
case 'c': |
case 'C': |
if ((pos+1)<=maxlen) |
{ |
//*s=(int)va_arg(argp,char*); |
*s=*((char *)argp); |
argp=argp+4; |
*s++;pos++; |
} |
break; |
case 's': |
case 'S': |
str=va_arg(argp,char*); |
length=strlen(str); |
if (pos + length > 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 |
fmt1 = 0; |
fmt2 = 0; |
if (posc - pos > 1) // try to read width, precision |
{ |
fmt++; |
flag_point=0; |
flag_noformat=0; |
fmt1=0; |
fmt2=0; |
j=0; |
k=0; |
for(i=pos+1;i<posc;i++) |
{ |
switch(*fmt) |
{ |
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
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) |
{ |
buffmt1[j]=*fmt-'0'; |
j++; |
} |
fmt1 = va_arg(argp, int); |
else |
{ |
buffmt2[k]=*fmt-'0'; |
k++; |
} |
fmt2 = va_arg(argp, int); |
break; |
case '.': |
flag_point=1; |
flags |= flag_point; |
break; |
case 'l': |
case 'L': |
case 'l': case 'L': case '+': // valid chars - skip |
case '-': case ' ': case '#': |
break; |
case '+': |
break; |
default:flag_noformat=1; |
default: // must be error |
strncpy(dest, "print format error - %width.precision", maxlen); |
return -1; // format char not found - user error |
} |
if (flag_noformat==1) break; |
fmt++; |
} |
if (flag_noformat==0) |
{ |
stepen=1; |
for(i=j-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; |
} |
// do real work - format arguments values |
length = 0; |
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)<maxlen) |
{ |
memcpy(s,buf,length); |
s=s+length;pos=pos+length; |
} |
case 'n': |
point_to_n = va_arg(argp, int*); |
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);} |
if ((intdigit>0) && (flag_plus==1) && (pos+1<maxlen)) |
case 'c': |
if (pos + 1 <= maxlen) |
{ |
*s='+'; |
s++; |
pos++; |
buf[0] = (char)va_arg(argp, int); |
length = 1; |
} |
length=formatted_long_to_string(intdigit,fmt1,buf); |
if ((pos+length)<maxlen) |
{ |
memcpy(s,buf,length); |
s=s+length;pos=pos+length; |
} |
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);} |
if (flag_long==1) {intdigit=va_arg(argp,long);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
length=formatted_octa_to_string(intdigit,fmt1,flag_register,buf); |
if ((pos+length)<maxlen) |
{ |
memcpy(s,buf,length); |
s=s+length;pos=pos+length; |
} |
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 '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,fmt1,buf); |
if ((pos+length)<maxlen) |
{ |
memcpy(s,buf,length); |
s=s+length;pos=pos+length; |
} |
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 'x': |
case 'X': |
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);} |
length=formatted_hex_to_string(intdigit,fmt1,flag_register,buf); |
if ((pos+length)<maxlen) |
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(s,buf,length); |
s=s+length;pos=pos+length; |
memcpy(buf, buf + sizeof buf / 2, i); |
length = i; |
} |
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,fmt1,buf); |
if ((pos+length)<maxlen) |
if (*fmtc != 's' && length > 0) // skip multiple string copying |
{ |
if (pos + length > maxlen) length = maxlen - pos; |
memcpy(s,buf,length); |
s=s+length;pos=pos+length; |
s += length; |
pos += length; |
} |
break; |
default:; |
} |
} |
fmt=fmtc+1; |
} |
} |
} |
else |
{ |
if (!(*s++ = *fmt++)) break; |
pos++; |
} |
exit_check:; |
} |
if (point_to_n) *point_to_n = pos; |
return(pos); |
} |
/programs/develop/ktcc/trunk/libc/stdio/fprintf.c |
---|
1,8 → 1,6 |
#include <stdio.h> |
#include <stdlib.h> |
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,6 → 13,9 |
//data[0]=(int)&arg-(int)&format; |
printed=format_print(buf,8191, format,arg); |
if (file == stderr) |
debug_out_str(buf); |
else |
fwrite(buf,printed,1,file); |
free(buf); |
/programs/develop/ktcc/trunk/libc/stdio/printf.c |
---|
7,8 → 7,12 |
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); |
void stdcall (* con_write_asciiz)(const char* string); |
32,6 → 36,7 |
_ksys_cofflib_getproc(exp, imports[5]); |
} |
int init_console(void) |
{ |
struct import * hDll; |
41,15 → 46,15 |
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"}; |
/programs/develop/ktcc/trunk/libc/stdio/putchar.c |
---|
0,0 → 1,7 |
#include <stdio.h> |
int putchar ( int ch ) |
{ |
printf("%c", ch); |
return ch; |
} |
/programs/develop/ktcc/trunk/libc/stdlib/strtod.c |
---|
0,0 → 1,70 |
#include <stdlib.h> |
#include <ctype.h> |
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); |
} |
/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, |