forked from KolibriOS/kolibrios
release ktcc 0.9.26
git-svn-id: svn://kolibrios.org@6424 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
97bb3982a6
commit
af35cc6783
@ -10,7 +10,7 @@ set CC=kos32-tcc
|
|||||||
set CFLAGS=-c -nostdinc -DGNUC -I"%cd%\%INCLUDE%" -Wall
|
set CFLAGS=-c -nostdinc -DGNUC -I"%cd%\%INCLUDE%" -Wall
|
||||||
set AR=kos32-ar
|
set AR=kos32-ar
|
||||||
set ASM=fasm
|
set ASM=fasm
|
||||||
set dirs=stdio memory kolibrisys string stdlib
|
set dirs=stdio memory kolibrisys string stdlib math
|
||||||
rem #### END OF CONFIG SECTION ####
|
rem #### END OF CONFIG SECTION ####
|
||||||
|
|
||||||
set objs=
|
set objs=
|
||||||
|
@ -4,31 +4,31 @@
|
|||||||
** dependable answers.
|
** dependable answers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ALNUM 1
|
#define __ALNUM 1
|
||||||
#define ALPHA 2
|
#define __ALPHA 2
|
||||||
#define CNTRL 4
|
#define __CNTRL 4
|
||||||
#define DIGIT 8
|
#define __DIGIT 8
|
||||||
#define GRAPH 16
|
#define __GRAPH 16
|
||||||
#define LOWER 32
|
#define __LOWER 32
|
||||||
#define PRINT 64
|
#define __PRINT 64
|
||||||
#define PUNCT 128
|
#define __PUNCT 128
|
||||||
#define BLANK 256
|
#define __BLANK 256
|
||||||
#define UPPER 512
|
#define __UPPER 512
|
||||||
#define XDIGIT 1024
|
#define __XDIGIT 1024
|
||||||
|
|
||||||
extern char _is[128];
|
extern char __is[128];
|
||||||
|
|
||||||
#define isalnum(c)(_is[c] & ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */
|
#define isalnum(c)(__is[c] & __ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */
|
||||||
#define isalpha(c)(_is[c] & ALPHA ) /* 'a'-'z', 'A'-'Z' */
|
#define isalpha(c)(__is[c] & __ALPHA ) /* 'a'-'z', 'A'-'Z' */
|
||||||
#define iscntrl(c)(_is[c] & CNTRL ) /* 0-31, 127 */
|
#define iscntrl(c)(__is[c] & __CNTRL ) /* 0-31, 127 */
|
||||||
#define isdigit(c)(_is[c] & DIGIT ) /* '0'-'9' */
|
#define isdigit(c)(__is[c] & __DIGIT ) /* '0'-'9' */
|
||||||
#define isgraph(c)(_is[c] & GRAPH ) /* '!'-'~' */
|
#define isgraph(c)(__is[c] & __GRAPH ) /* '!'-'~' */
|
||||||
#define islower(c)(_is[c] & LOWER ) /* 'a'-'z' */
|
#define islower(c)(__is[c] & __LOWER ) /* 'a'-'z' */
|
||||||
#define isprint(c)(_is[c] & PRINT ) /* ' '-'~' */
|
#define isprint(c)(__is[c] & __PRINT ) /* ' '-'~' */
|
||||||
#define ispunct(c)(_is[c] & PUNCT ) /* !alnum && !cntrl && !space */
|
#define ispunct(c)(__is[c] & __PUNCT ) /* !alnum && !cntrl && !space */
|
||||||
#define isspace(c)(_is[c] & BLANK ) /* HT, LF, VT, FF, CR, ' ' */
|
#define isspace(c)(__is[c] & __BLANK ) /* HT, LF, VT, FF, CR, ' ' */
|
||||||
#define isupper(c)(_is[c] & UPPER ) /* 'A'-'Z' */
|
#define isupper(c)(__is[c] & __UPPER ) /* 'A'-'Z' */
|
||||||
#define isxdigit(c)(_is[c] & XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */
|
#define isxdigit(c)(__is[c] & __XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */
|
||||||
|
|
||||||
#define isascii(c) (!((c)&(~0x7f)))
|
#define isascii(c) (!((c)&(~0x7f)))
|
||||||
#define toascii(c) ((c)&0x7f)
|
#define toascii(c) ((c)&0x7f)
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#define DBL_MAX_10_EXP 308
|
#define DBL_MAX_10_EXP 308
|
||||||
|
|
||||||
/* horrible intel long double */
|
/* horrible intel long double */
|
||||||
#ifdef __i386__
|
#if defined __i386__ || defined __x86_64__
|
||||||
|
|
||||||
#define LDBL_MANT_DIG 64
|
#define LDBL_MANT_DIG 64
|
||||||
#define LDBL_DIG 18
|
#define LDBL_DIG 18
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
|
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
|
||||||
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
|
/* 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 acos(double _x);
|
||||||
extern double asin(double _x);
|
extern double asin(double _x);
|
||||||
@ -163,6 +163,11 @@ extern float log1pf(float);
|
|||||||
extern float gammaf_r(float, int *);
|
extern float gammaf_r(float, int *);
|
||||||
extern float lgammaf_r(float, int *);
|
extern float lgammaf_r(float, int *);
|
||||||
|
|
||||||
|
double round (double x);
|
||||||
|
long double roundl (long double x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//#endif /* !_POSIX_SOURCE */
|
//#endif /* !_POSIX_SOURCE */
|
||||||
//#endif /* !__STRICT_ANSI__ */
|
//#endif /* !__STRICT_ANSI__ */
|
||||||
//#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */
|
//#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */
|
||||||
|
@ -1,15 +1,75 @@
|
|||||||
#ifndef _STDARG_H
|
#ifndef _STDARG_H
|
||||||
#define _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 */
|
/* only correct for i386 */
|
||||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
#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_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)
|
#define va_end(ap)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* fix a buggy dependency on GCC in libio.h */
|
/* fix a buggy dependency on GCC in libio.h */
|
||||||
typedef va_list __gnuc_va_list;
|
typedef va_list __gnuc_va_list;
|
||||||
#define _VA_LIST_DEFINED
|
#define _VA_LIST_DEFINED
|
||||||
|
|
||||||
#endif
|
#endif /* _STDARG_H */
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
#define bool _Bool
|
#define bool _Bool
|
||||||
#define true 1
|
#define true 1
|
||||||
#define false 0
|
#define false 0
|
||||||
|
#define __bool_true_false_are_defined 1
|
||||||
|
|
||||||
#endif /* _STDBOOL_H */
|
#endif /* _STDBOOL_H */
|
||||||
|
@ -1,21 +1,46 @@
|
|||||||
#ifndef _STDDEF_H
|
#ifndef _STDDEF_H
|
||||||
#define _STDDEF_H
|
#define _STDDEF_H
|
||||||
|
|
||||||
#define NULL ((void *)0)
|
|
||||||
typedef __SIZE_TYPE__ size_t;
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||||
typedef __WCHAR_TYPE__ wchar_t;
|
typedef __WCHAR_TYPE__ wchar_t;
|
||||||
typedef __PTRDIFF_TYPE__ ptrdiff_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
|
#ifndef __int8_t_defined
|
||||||
presence of 'long long' without __GNUC__, or TCC should define
|
|
||||||
__GNUC__ ? */
|
|
||||||
#if !defined(__int8_t_defined) && !defined(__dietlibc__)
|
|
||||||
#define __int8_t_defined
|
#define __int8_t_defined
|
||||||
typedef char int8_t;
|
typedef signed char int8_t;
|
||||||
typedef short int int16_t;
|
typedef signed short int int16_t;
|
||||||
typedef int int32_t;
|
typedef signed int int32_t;
|
||||||
typedef long long int int64_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
|
#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
|
#endif
|
||||||
|
@ -2,14 +2,18 @@
|
|||||||
#define stdio_h
|
#define stdio_h
|
||||||
|
|
||||||
#include "kolibrisys.h"
|
#include "kolibrisys.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
/* use stdarg.h
|
||||||
typedef char *va_list;
|
typedef char *va_list;
|
||||||
#define _roundsize(n) ( (sizeof(n) + 3) & ~3 )
|
#define _roundsize(n) ( (sizeof(n) + 3) & ~3 )
|
||||||
#define va_start(ap,v) (ap = (va_list)&v+_roundsize(v))
|
#define va_start(ap,v) (ap = (va_list)&v+_roundsize(v))
|
||||||
#define va_arg(ap,t) ( *(t *)((ap += _roundsize(t)) - _roundsize(t)) )
|
#define va_arg(ap,t) ( *(t *)((ap += _roundsize(t)) - _roundsize(t)) )
|
||||||
#define va_end(ap) (ap = (va_list)0)
|
#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);
|
int format_print(char *dest, size_t maxlen,const char *fmt0, va_list argp);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -21,6 +25,9 @@ typedef struct {
|
|||||||
int mode;
|
int mode;
|
||||||
} FILE;
|
} FILE;
|
||||||
|
|
||||||
|
#define stderr ((FILE*)3) /* works inly for fprintf!!! */
|
||||||
|
|
||||||
|
|
||||||
#define FILE_OPEN_READ 0
|
#define FILE_OPEN_READ 0
|
||||||
#define FILE_OPEN_WRITE 1
|
#define FILE_OPEN_WRITE 1
|
||||||
#define FILE_OPEN_APPEND 2
|
#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,...);
|
extern int cdecl sprintf(char *dest,const char *format,...);
|
||||||
|
|
||||||
#define getc(a) fgetc(a)
|
#define getc(a) fgetc(a)
|
||||||
|
char * fgets ( char * str, int num, FILE * stream );
|
||||||
|
int putchar ( int character );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,4 +21,10 @@ extern void* stdcall realloc(void* pointer,dword size);
|
|||||||
extern int rand (void);
|
extern int rand (void);
|
||||||
extern void srand (unsigned int seed);
|
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
|
#endif
|
@ -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
|
#ifndef _VARARGS_H
|
||||||
#define _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
|
#endif
|
||||||
|
23
programs/develop/ktcc/trunk/libc/math/acos.asm
Normal file
23
programs/develop/ktcc/trunk/libc/math/acos.asm
Normal file
@ -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
|
||||||
|
|
6
programs/develop/ktcc/trunk/libc/math/asin.c
Normal file
6
programs/develop/ktcc/trunk/libc/math/asin.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double asin(double x)
|
||||||
|
{
|
||||||
|
return atan(sqrt(x * x / (1.0 - x * x)));
|
||||||
|
}
|
15
programs/develop/ktcc/trunk/libc/math/atan.asm
Normal file
15
programs/develop/ktcc/trunk/libc/math/atan.asm
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
format ELF
|
||||||
|
include 'proc32.inc'
|
||||||
|
section '.text' executable
|
||||||
|
|
||||||
|
public atan_ as "atan"
|
||||||
|
|
||||||
|
atan_:
|
||||||
|
|
||||||
|
fld qword[esp+4]
|
||||||
|
fld1
|
||||||
|
fpatan
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
15
programs/develop/ktcc/trunk/libc/math/atan2.asm
Normal file
15
programs/develop/ktcc/trunk/libc/math/atan2.asm
Normal file
@ -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
|
||||||
|
|
14
programs/develop/ktcc/trunk/libc/math/cos.asm
Normal file
14
programs/develop/ktcc/trunk/libc/math/cos.asm
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
format ELF
|
||||||
|
include 'proc32.inc'
|
||||||
|
section '.text' executable
|
||||||
|
|
||||||
|
public cos_ as "cos"
|
||||||
|
|
||||||
|
cos_:
|
||||||
|
|
||||||
|
fld qword[esp+4]
|
||||||
|
fcos
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
6
programs/develop/ktcc/trunk/libc/math/cosh.c
Normal file
6
programs/develop/ktcc/trunk/libc/math/cosh.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double cosh (double x)
|
||||||
|
{
|
||||||
|
return (exp(x) + exp(-x)) / 2;
|
||||||
|
}
|
60
programs/develop/ktcc/trunk/libc/math/exp.asm
Normal file
60
programs/develop/ktcc/trunk/libc/math/exp.asm
Normal file
@ -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
|
||||||
|
|
||||||
|
|
754
programs/develop/ktcc/trunk/libc/math/libtcc1.c
Normal file
754
programs/develop/ktcc/trunk/libc/math/libtcc1.c
Normal file
@ -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
|
18
programs/develop/ktcc/trunk/libc/math/log.asm
Normal file
18
programs/develop/ktcc/trunk/libc/math/log.asm
Normal file
@ -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
|
18
programs/develop/ktcc/trunk/libc/math/log10.asm
Normal file
18
programs/develop/ktcc/trunk/libc/math/log10.asm
Normal file
@ -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
|
6
programs/develop/ktcc/trunk/libc/math/pow.c
Normal file
6
programs/develop/ktcc/trunk/libc/math/pow.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double pow(double x, double y)
|
||||||
|
{
|
||||||
|
return exp(y * log(x));
|
||||||
|
}
|
9
programs/develop/ktcc/trunk/libc/math/round.c
Normal file
9
programs/develop/ktcc/trunk/libc/math/round.c
Normal file
@ -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);
|
||||||
|
}
|
9
programs/develop/ktcc/trunk/libc/math/roundl.c
Normal file
9
programs/develop/ktcc/trunk/libc/math/roundl.c
Normal file
@ -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);
|
||||||
|
}
|
14
programs/develop/ktcc/trunk/libc/math/sin.asm
Normal file
14
programs/develop/ktcc/trunk/libc/math/sin.asm
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
format ELF
|
||||||
|
include 'proc32.inc'
|
||||||
|
section '.text' executable
|
||||||
|
|
||||||
|
public sin_ as "sin"
|
||||||
|
|
||||||
|
sin_:
|
||||||
|
|
||||||
|
fld qword[esp+4]
|
||||||
|
fsin
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
6
programs/develop/ktcc/trunk/libc/math/sinh.c
Normal file
6
programs/develop/ktcc/trunk/libc/math/sinh.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double sinh (double x)
|
||||||
|
{
|
||||||
|
return (exp(x) - exp(-x)) / 2;
|
||||||
|
}
|
15
programs/develop/ktcc/trunk/libc/math/tan.asm
Normal file
15
programs/develop/ktcc/trunk/libc/math/tan.asm
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
format ELF
|
||||||
|
include 'proc32.inc'
|
||||||
|
section '.text' executable
|
||||||
|
|
||||||
|
public tan_ as "tan"
|
||||||
|
|
||||||
|
tan_:
|
||||||
|
|
||||||
|
fld qword[esp+4]
|
||||||
|
fptan
|
||||||
|
fxch
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
8
programs/develop/ktcc/trunk/libc/math/tanh.c
Normal file
8
programs/develop/ktcc/trunk/libc/math/tanh.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double tanh (double x)
|
||||||
|
{
|
||||||
|
double ex = exp(x), exm = exp(-x);
|
||||||
|
|
||||||
|
return (ex - exm) / (ex + exm);
|
||||||
|
}
|
@ -1,30 +1,32 @@
|
|||||||
format ELF
|
format ELF
|
||||||
section '.text' executable
|
section '.text' executable
|
||||||
public start
|
public start
|
||||||
extrn mf_init
|
public start as '_start'
|
||||||
|
;extrn mf_init
|
||||||
extrn main
|
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
|
virtual at 0
|
||||||
db 'MENUET01' ; 1. Magic number (8 bytes)
|
db 'MENUET01' ; 1. Magic number (8 bytes)
|
||||||
dd 0x01 ; 2. Version of executable file
|
dd 0x01 ; 2. Version of executable file
|
||||||
dd 0x0 ; 3. Start address
|
dd start ; 3. Start address
|
||||||
dd 0x0 ; 4. Size of image
|
dd 0x0 ; 4. Size of image
|
||||||
dd 0x100000 ; 5. Size of needed memory
|
dd 0x100000 ; 5. Size of needed memory
|
||||||
dd 0x100000 ; 6. Pointer to stack
|
dd 0x100000 ; 6. Pointer to stack
|
||||||
hparams dd 0x0 ; 7. Pointer to program arguments
|
hparams dd 0x0 ; 7. Pointer to program arguments
|
||||||
hpath dd 0x0 ; 8. Pointer to program path
|
hpath dd 0x0 ; 8. Pointer to program path
|
||||||
end virtual
|
end virtual
|
||||||
|
|
||||||
start:
|
start:
|
||||||
DEBUGF 1,'Start programm\n'
|
;DEBUGF 'Start programm\n'
|
||||||
xor eax,eax
|
;init heap of memory
|
||||||
call mf_init
|
mov eax,68
|
||||||
DEBUGF 1,' path "%s"\n params "%s"\n', path, params
|
mov ebx,11
|
||||||
|
int 0x40
|
||||||
|
|
||||||
|
;DEBUGF ' path "%s"\n params "%s"\n', .path, .params
|
||||||
; check for overflow
|
; check for overflow
|
||||||
mov al, [path+buf_len-1]
|
mov al, [path+buf_len-1]
|
||||||
or al, [params+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
|
jmp .parse
|
||||||
|
|
||||||
.run:
|
.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
|
if __DEBUG__ = 1
|
||||||
mov ecx, [argc]
|
mov ecx, [argc]
|
||||||
@@:
|
@@:
|
||||||
lea esi, [ecx * 4 + argv-4]
|
lea esi, [ecx * 4 + argv-4]
|
||||||
DEBUGF 1,'%d) "%s"\n', cx, [esi]
|
DEBUGF '0x%x) "%s"\n', cx, [esi]
|
||||||
loop @b
|
loop @b
|
||||||
end if
|
end if
|
||||||
push argv
|
push argv
|
||||||
push [argc]
|
push [argc]
|
||||||
call main
|
call main
|
||||||
.exit:
|
.exit:
|
||||||
DEBUGF 1,'Exit from prog with code: %x\n', eax;
|
;DEBUGF 'Exit from prog\n';
|
||||||
xor eax,eax
|
xor eax,eax
|
||||||
dec eax
|
dec eax
|
||||||
int 0x40
|
int 0x40
|
||||||
dd -1
|
dd -1
|
||||||
.crash:
|
.crash:
|
||||||
DEBUGF 1,'E:buffer overflowed\n'
|
;DEBUGF 'E:buffer overflowed\n'
|
||||||
jmp .exit
|
jmp .exit
|
||||||
;============================
|
;============================
|
||||||
push_param:
|
push_param:
|
||||||
@ -120,6 +122,7 @@ push_param:
|
|||||||
.dont_add:
|
.dont_add:
|
||||||
ret
|
ret
|
||||||
;==============================
|
;==============================
|
||||||
|
public argc as '__argc'
|
||||||
public params as '__argv'
|
public params as '__argv'
|
||||||
public path as '__path'
|
public path as '__path'
|
||||||
|
|
||||||
@ -131,5 +134,5 @@ argv rd max_parameters
|
|||||||
path rb buf_len
|
path rb buf_len
|
||||||
params rb buf_len
|
params rb buf_len
|
||||||
|
|
||||||
section '.data'
|
;section '.data'
|
||||||
include_debug_strings ; ALWAYS present in data section
|
;include_debug_strings ; ALWAYS present in data section
|
25
programs/develop/ktcc/trunk/libc/stdio/fgets.c
Normal file
25
programs/develop/ktcc/trunk/libc/stdio/fgets.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,213 +1,230 @@
|
|||||||
/*
|
/*
|
||||||
function for format output to the string
|
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 <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
//#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.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;
|
flag_unsigned = 0x02,
|
||||||
double nbefor;
|
flag_register = 0x04,
|
||||||
double nafter;
|
flag_plus = 0x08,
|
||||||
double v,v2;
|
flag_left_just = 0x10,
|
||||||
long intdigit;
|
flag_lead_zeros = 0x20,
|
||||||
long beforpointdigit;
|
flag_space_plus = 0x40,
|
||||||
long div;
|
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 i;
|
||||||
int pos;
|
char* size;
|
||||||
int size;
|
|
||||||
int fmt1;
|
int fmt1;
|
||||||
int fmt2;
|
int fmt2;
|
||||||
long mul;
|
char buf[100], *pbuf = buf;
|
||||||
char buf[200];
|
char buf_low[50], *pbuf_lo = buf_low;
|
||||||
|
|
||||||
size=(int)s;
|
if((flags & flag_point) == 0) format2 = 6; // default prec if no point spec
|
||||||
n=(double)number;
|
|
||||||
if (n<0) {*s='-';s++;n=-n;}
|
|
||||||
|
|
||||||
fmt1=format1;
|
size = s;
|
||||||
fmt2=format2;
|
if (number < 0) {*s++ = '-'; number = -number; }
|
||||||
if (fmt2>18) {fmt2=18;} //maximum of size long long type
|
|
||||||
|
|
||||||
//clear array befor output
|
|
||||||
for(i=0;i<=200;i++) {buf[i]=0;}
|
|
||||||
|
|
||||||
if ((fmt1>=0) && (n<1))
|
|
||||||
{ //formatted output if 0<=n<1
|
|
||||||
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++)
|
|
||||||
{
|
|
||||||
div=intdigit/mul;
|
|
||||||
buf[pos]=(char)div;
|
|
||||||
pos++;
|
|
||||||
intdigit=intdigit-div*mul;
|
|
||||||
mul=mul/10;
|
|
||||||
if (mul==1) break;
|
|
||||||
}
|
|
||||||
buf[pos]=(char)intdigit;
|
|
||||||
*s='0';s++;
|
|
||||||
*s='.';s++;
|
|
||||||
for(i=0;i<format2;i++)
|
|
||||||
{
|
|
||||||
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
||||||
else {*s='0';}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
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 (flags & flag_plus) *s++ = '+'; else
|
||||||
if ((beforpointdigit/mul)==0) {fmt1=i+1;break;}
|
if (flags & flag_space_plus) *s++ = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
pos=0;
|
fmt1 = 1;
|
||||||
mul=mul/10;
|
fmt2 = format2;
|
||||||
for(i=0;i<fmt1-1;i++)
|
if (fmt2 > 18) fmt2 = 18; //maximum size of long long type
|
||||||
{
|
|
||||||
div=beforpointdigit/mul;
|
|
||||||
buf[pos]=(char)div;
|
|
||||||
pos++;
|
|
||||||
beforpointdigit=beforpointdigit-div*mul;
|
|
||||||
mul=mul/10;
|
|
||||||
if (mul==1) break;
|
|
||||||
}
|
|
||||||
buf[pos]=(char)beforpointdigit;
|
|
||||||
|
|
||||||
for(i=0;i<fmt1;i++)
|
beforpointdigit = floor(number + 0.00000000000001);
|
||||||
|
nafter = number - beforpointdigit;
|
||||||
|
|
||||||
|
//print part of number before point
|
||||||
|
mul = 1;
|
||||||
|
for(i = 0; i < sizeof buf - 1; i++)
|
||||||
{
|
{
|
||||||
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
mul *= 10;
|
||||||
s++;
|
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 /= 10;
|
||||||
|
while(mul > 1)
|
||||||
|
{
|
||||||
|
div = beforpointdigit / mul;
|
||||||
|
*pbuf++ = (char)div + '0';
|
||||||
|
beforpointdigit = beforpointdigit - div * mul;
|
||||||
|
mul /= 10;
|
||||||
|
}
|
||||||
|
*pbuf++=(char)beforpointdigit + '0';
|
||||||
|
|
||||||
//print part of number after point
|
//print part of number after point
|
||||||
mul=1;
|
mul = 1;
|
||||||
for(i=0;i<fmt2;i++)
|
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;
|
|
||||||
|
|
||||||
pos=0;
|
|
||||||
mul=mul/10;
|
|
||||||
for(i=0;i<fmt2-1;i++)
|
|
||||||
{
|
{
|
||||||
div=intdigit/mul;
|
nafter = nafter*10;
|
||||||
buf[pos]=(char)div;
|
mul *= 10;
|
||||||
pos++;
|
|
||||||
intdigit=intdigit-div*mul;
|
|
||||||
mul=mul/10;
|
|
||||||
if (mul==1) break;
|
|
||||||
}
|
|
||||||
buf[pos]=(char)intdigit;
|
|
||||||
*s='.';s++;
|
|
||||||
for(i=0;i<format2;i++)
|
|
||||||
{
|
|
||||||
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
||||||
else {*s='0';}
|
|
||||||
s++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intdigit = roundl(nafter);
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
size=(int)s-size;
|
*pbuf_lo++ = (char)intdigit + '0';
|
||||||
return(size);
|
|
||||||
|
|
||||||
|
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
|
||||||
|
pbuf[i] = ' ';
|
||||||
|
|
||||||
|
return format1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s - 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 i;
|
||||||
int pos;
|
|
||||||
int fmt;
|
int fmt;
|
||||||
int size;
|
char* size = s;
|
||||||
int difference_pos;
|
long long digit;
|
||||||
long digit;
|
long long mul;
|
||||||
long mul;
|
int div;
|
||||||
long div;
|
char buf[100], *pbuf = buf;
|
||||||
char buf[200];
|
|
||||||
|
|
||||||
//clear array befor output
|
if (number == -9223372036854775807LL - 1) // overflow all our math, cant minus this
|
||||||
for(i=0;i<200;i++) {buf[i]=0;}
|
|
||||||
digit=number;
|
|
||||||
|
|
||||||
size=(int)s;
|
|
||||||
if (digit<0) {*s='-';s++;digit=-digit;}
|
|
||||||
if (digit==0) {*s='0';s++;goto end;}
|
|
||||||
|
|
||||||
mul=1;
|
|
||||||
for(i=0;i<200-2;i++)
|
|
||||||
{
|
{
|
||||||
mul=mul*10;
|
strcpy(buf, "9223372036854775808");
|
||||||
if ((digit/mul)==0) {fmt=i+1;break;}
|
pbuf += 19;
|
||||||
|
*s++ = '-';
|
||||||
|
goto verybig;
|
||||||
}
|
}
|
||||||
|
|
||||||
difference_pos=i+1;
|
if (flags & flag_point) flags &= ~flag_lead_zeros; // conflicting flags
|
||||||
|
|
||||||
pos=0;
|
if (number < 0) {*s++ = '-'; number = -number; }
|
||||||
mul=mul/10;
|
|
||||||
for(i=0;i<fmt-1;i++)
|
|
||||||
{
|
|
||||||
div=digit/mul;
|
|
||||||
buf[pos]=(char)div;
|
|
||||||
pos++;
|
|
||||||
digit=digit-div*mul;
|
|
||||||
mul=mul/10;
|
|
||||||
if (mul==1) break;
|
|
||||||
}
|
|
||||||
buf[pos]=(char)digit;
|
|
||||||
|
|
||||||
if (fmt1>=difference_pos) fmt=fmt1;
|
|
||||||
else
|
|
||||||
fmt=difference_pos;
|
|
||||||
|
|
||||||
for(i=0;i<fmt;i++)
|
|
||||||
{
|
|
||||||
if (i<difference_pos)
|
|
||||||
{
|
|
||||||
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*s=' ';
|
if (flags & flag_plus) *s++ = '+'; else
|
||||||
|
if (flags & flag_space_plus) *s++ = ' ';
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
end:
|
|
||||||
size=(int)s-size;
|
// add leading zeros
|
||||||
return(size);
|
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 flag_register,char *s)
|
int formatted_hex_to_string(long long number, int fmt1, char *s, int flags)
|
||||||
{
|
{
|
||||||
long n;
|
long n;
|
||||||
int i,pos;
|
int i,pos;
|
||||||
int fmt;
|
// int fmt;
|
||||||
long size;
|
long size;
|
||||||
int difference_pos;
|
int difference_pos;
|
||||||
char xdigs_lower[16]="0123456789abcdef";
|
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);
|
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;
|
long n;
|
||||||
int i,pos;
|
int i,pos;
|
||||||
int fmt;
|
// int fmt;
|
||||||
long size;
|
long size;
|
||||||
int difference_pos;
|
int difference_pos;
|
||||||
char xdigs_lower[16]="012345678";
|
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);
|
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 i;
|
||||||
int length;
|
int length;
|
||||||
int fmt1,fmt2,stepen;
|
int fmt1, fmt2; // width, precision
|
||||||
size_t pos,posc;
|
size_t pos, posc;
|
||||||
long long intdigit;
|
long long intdigit;
|
||||||
long double doubledigit;
|
long double doubledigit;
|
||||||
float floatdigit;
|
// float floatdigit;
|
||||||
const char *fmt,*fmtc;
|
const char *fmt, *fmtc; // first point to %, fmtc points to specifier
|
||||||
char *s;
|
char *s; // pointer to current dest char
|
||||||
char *str;
|
char *str;
|
||||||
char buffmt1[30];
|
char buf[200]; // buffer for current argument value print representation
|
||||||
char buffmt2[30];
|
int format_flag;
|
||||||
char buf[1024];
|
int flag_long; // 2 = long double or long long int or wchar
|
||||||
char format_flag;
|
int *point_to_n = NULL;
|
||||||
char flag_point;
|
int flags; // parsed flags
|
||||||
char flag_noformat;
|
|
||||||
char flag_long;
|
|
||||||
char flag_unsigned;
|
|
||||||
char flag_register;
|
|
||||||
char flag_plus;
|
|
||||||
|
|
||||||
fmt=fmt0;
|
fmt = fmt0;
|
||||||
s=dest;
|
s = dest;
|
||||||
pos=0;
|
pos = 0;
|
||||||
while(pos<maxlen)
|
while(pos < maxlen)
|
||||||
{
|
{
|
||||||
if (*fmt=='%')
|
if (*fmt != '%') // usual char
|
||||||
{
|
{
|
||||||
|
if ('\0' == (*s++ = *fmt++)) break;
|
||||||
if (*(fmt+1)=='%')
|
|
||||||
{
|
|
||||||
*s='%';
|
|
||||||
s++;
|
|
||||||
fmt=fmt+2;
|
|
||||||
pos++;
|
pos++;
|
||||||
goto exit_check;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*(fmt + 1) == '%') // %%
|
||||||
|
{
|
||||||
|
*s++ = '%'; pos++;
|
||||||
|
fmt += 2;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
//checking to containg format in the string
|
//checking to containg format in the string
|
||||||
fmtc=fmt;
|
fmtc = fmt;
|
||||||
posc=pos;
|
posc = pos;
|
||||||
format_flag=0;
|
|
||||||
flag_long=0;
|
flags = 0;
|
||||||
flag_unsigned=0;
|
format_flag = 0;
|
||||||
flag_register=0;
|
flag_long = 0; // 2 = long double or long long int or wchar
|
||||||
flag_plus=0;
|
|
||||||
while((*fmtc!='\0') || (*fmtc!=0))
|
while(*fmtc != '\0' && !format_flag) // searching end of format
|
||||||
{
|
{
|
||||||
fmtc++;
|
fmtc++; posc++;
|
||||||
posc++;
|
switch( *fmtc )
|
||||||
switch(*fmtc)
|
|
||||||
{
|
{
|
||||||
case 'c':
|
case 'a':
|
||||||
case 'C':
|
format_flag = 1;
|
||||||
format_flag=1;
|
flags |= flag_unsigned;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'A':
|
||||||
case 'D':
|
format_flag = 1;
|
||||||
case 'i':
|
flags |= flag_unsigned | flag_register;
|
||||||
case 'I':
|
|
||||||
format_flag=1;
|
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'c': case 'd': case 'i': case 'e': case 'f': case 'g': case 's': case 'n':
|
||||||
format_flag=1;
|
format_flag = 1;
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E': case 'F': case 'G':
|
||||||
format_flag=1;
|
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;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
flag_long=1;
|
flag_long = flag_long ? 2 : 1; // ll.eq.L
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
flag_long=2;
|
flag_long = 2;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o': case 'u': case 'x': case 'p':
|
||||||
format_flag=1;
|
format_flag = 1;
|
||||||
|
flags |= flag_unsigned;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 'X': case 'P':
|
||||||
case 'S':
|
format_flag = 1;
|
||||||
format_flag=1;
|
flags |= flag_unsigned | flag_register;
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
case 'U':
|
|
||||||
format_flag=1;
|
|
||||||
flag_unsigned=1;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
case 'p':
|
|
||||||
format_flag=1;
|
|
||||||
break;
|
|
||||||
case 'X':
|
|
||||||
case 'P':
|
|
||||||
flag_register=1;
|
|
||||||
format_flag=1;
|
|
||||||
break;
|
|
||||||
case 'z':
|
|
||||||
case 'Z':
|
|
||||||
format_flag=1;
|
|
||||||
flag_unsigned=1;
|
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
flag_plus=1;
|
flags |= flag_plus;
|
||||||
break;
|
break;
|
||||||
|
case '-':
|
||||||
default:;
|
flags |= flag_left_just;
|
||||||
|
break;
|
||||||
|
case ' ': // space
|
||||||
|
flags |= flag_space_plus;
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
flags |= flag_hash_sign;
|
||||||
|
break;
|
||||||
|
case '*': case '.': // just skip
|
||||||
|
break;
|
||||||
|
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)
|
if (format_flag == 0)
|
||||||
{
|
{
|
||||||
*s=*fmt;
|
strncpy(dest, "print format error - % without format specifier", maxlen);
|
||||||
fmt++;
|
return -1; // format char not found - user error
|
||||||
s++;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
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);
|
fmt1 = 0;
|
||||||
if (pos + length > maxlen)
|
fmt2 = 0;
|
||||||
length = maxlen - pos;
|
if (posc - pos > 1) // try to read width, precision
|
||||||
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++;
|
fmt++;
|
||||||
flag_point=0;
|
for(i = pos + 1; i < posc; i++)
|
||||||
flag_noformat=0;
|
|
||||||
fmt1=0;
|
|
||||||
fmt2=0;
|
|
||||||
j=0;
|
|
||||||
k=0;
|
|
||||||
for(i=pos+1;i<posc;i++)
|
|
||||||
{
|
{
|
||||||
switch(*fmt)
|
switch(*fmt)
|
||||||
{
|
{
|
||||||
case '0':
|
case '0':
|
||||||
case '1':
|
if(fmt1 == 0 && (flags & flag_point) == 0) flags |= flag_lead_zeros;
|
||||||
case '2':
|
case '1': case '2': case '3': case '4':
|
||||||
case '3':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
case '4':
|
if ((flags & flag_point) == 0)
|
||||||
case '5':
|
fmt1 = fmt1 * 10 + (*fmt -'0');
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
if (flag_point==0)
|
|
||||||
{
|
|
||||||
buffmt1[j]=*fmt-'0';
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
fmt2 = fmt2 * 10 + (*fmt -'0');
|
||||||
buffmt2[k]=*fmt-'0';
|
break;
|
||||||
k++;
|
case '*':
|
||||||
}
|
if (flag_point == 0)
|
||||||
|
fmt1 = va_arg(argp, int);
|
||||||
|
else
|
||||||
|
fmt2 = va_arg(argp, int);
|
||||||
break;
|
break;
|
||||||
case '.':
|
case '.':
|
||||||
flag_point=1;
|
flags |= flag_point;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l': case 'L': case '+': // valid chars - skip
|
||||||
case 'L':
|
case '-': case ' ': case '#':
|
||||||
break;
|
break;
|
||||||
case '+':
|
default: // must be error
|
||||||
break;
|
strncpy(dest, "print format error - %width.precision", maxlen);
|
||||||
default:flag_noformat=1;
|
return -1; // format char not found - user error
|
||||||
}
|
}
|
||||||
if (flag_noformat==1) break;
|
|
||||||
fmt++;
|
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)
|
switch(*fmtc)
|
||||||
{
|
{
|
||||||
case 'f':
|
case 'n':
|
||||||
case 'F':
|
point_to_n = va_arg(argp, int*);
|
||||||
if (flag_long==0) {doubledigit=va_arg(argp,double);}
|
break;
|
||||||
if (flag_long>=1) {doubledigit=va_arg(argp,long double);}
|
case 'c':
|
||||||
//doubledigit=*((double *)argp);
|
if (pos + 1 <= maxlen)
|
||||||
//sargp=argp+8;
|
|
||||||
length=formatted_double_to_string(doubledigit,fmt1,fmt2,buf);
|
|
||||||
if ((pos+length)<maxlen)
|
|
||||||
{
|
{
|
||||||
memcpy(s,buf,length);
|
buf[0] = (char)va_arg(argp, int);
|
||||||
s=s+length;pos=pos+length;
|
length = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 's': // special case - without buf
|
||||||
case 'D':
|
str = va_arg(argp, char*);
|
||||||
case 'i':
|
length = strlen(str);
|
||||||
case 'I':
|
if ((flags & flag_point) && (length > fmt2)) length = fmt2; // cut by precision
|
||||||
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
if (pos + length > maxlen) length = maxlen - pos;
|
||||||
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
memcpy(s, str ,length);
|
||||||
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
s += length;
|
||||||
|
pos += length;
|
||||||
if ((intdigit>0) && (flag_plus==1) && (pos+1<maxlen))
|
break;
|
||||||
{
|
case 'd': case 'i': case 'u': case 'U':
|
||||||
*s='+';
|
if (flag_long == 0) intdigit = va_arg(argp, int); else
|
||||||
s++;
|
if (flag_long == 1) intdigit = va_arg(argp, long); else
|
||||||
pos++;
|
if (flag_long == 2) intdigit = va_arg(argp, long long);
|
||||||
}
|
length = formatted_long_to_string(intdigit, fmt1, fmt2, buf, flags);
|
||||||
length=formatted_long_to_string(intdigit,fmt1,buf);
|
|
||||||
if ((pos+length)<maxlen)
|
|
||||||
{
|
|
||||||
memcpy(s,buf,length);
|
|
||||||
s=s+length;pos=pos+length;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
if (flag_long == 0) intdigit = va_arg(argp, int); else
|
||||||
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
if (flag_long == 1) intdigit = va_arg(argp, long); else
|
||||||
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
if (flag_long == 2) intdigit = va_arg(argp, long long);
|
||||||
length=formatted_octa_to_string(intdigit,fmt1,flag_register,buf);
|
length = formatted_octa_to_string(intdigit, fmt1, buf, flags);
|
||||||
if ((pos+length)<maxlen)
|
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(s,buf,length);
|
memcpy(buf, buf + sizeof buf / 2, i);
|
||||||
s=s+length;pos=pos+length;
|
length = i;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'u':
|
}
|
||||||
case 'U':
|
if (*fmtc != 's' && length > 0) // skip multiple string copying
|
||||||
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
{
|
||||||
if (flag_long==1) {intdigit=va_arg(argp,long int);}
|
if (pos + length > maxlen) length = maxlen - pos;
|
||||||
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
memcpy(s, buf, length);
|
||||||
|
s += length;
|
||||||
if (flag_unsigned==1) {
|
pos += length;
|
||||||
if (intdigit<0) {intdigit=-intdigit;}
|
}
|
||||||
|
fmt = fmtc + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
length=formatted_long_to_string(intdigit,fmt1,buf);
|
if (point_to_n) *point_to_n = pos;
|
||||||
if ((pos+length)<maxlen)
|
|
||||||
{
|
|
||||||
memcpy(s,buf,length);
|
|
||||||
s=s+length;pos=pos+length;
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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,fmt1,buf);
|
|
||||||
if ((pos+length)<maxlen)
|
|
||||||
{
|
|
||||||
memcpy(s,buf,length);
|
|
||||||
s=s+length;pos=pos+length;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt=fmtc+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(*s++ = *fmt++)) break;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
exit_check:;
|
|
||||||
}
|
|
||||||
return(pos);
|
return(pos);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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, ...)
|
int fprintf(FILE* file, const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
@ -15,6 +13,9 @@ int printed;
|
|||||||
//data[0]=(int)&arg-(int)&format;
|
//data[0]=(int)&arg-(int)&format;
|
||||||
|
|
||||||
printed=format_print(buf,8191, format,arg);
|
printed=format_print(buf,8191, format,arg);
|
||||||
|
if (file == stderr)
|
||||||
|
debug_out_str(buf);
|
||||||
|
else
|
||||||
fwrite(buf,printed,1,file);
|
fwrite(buf,printed,1,file);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
|
@ -7,7 +7,11 @@ char* dllname="/sys/lib/console.obj";
|
|||||||
int console_init_status;
|
int console_init_status;
|
||||||
|
|
||||||
char* imports[] = {"START","version","con_init","con_write_asciiz","con_printf","con_exit",NULL};
|
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;
|
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_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]);
|
_ksys_cofflib_getproc(exp, imports[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int init_console(void)
|
int init_console(void)
|
||||||
{
|
{
|
||||||
struct import * hDll;
|
struct import * hDll;
|
||||||
@ -41,15 +46,15 @@ int init_console(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf_link(hDll, imports);
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int printf(const char *format,...)
|
int printf(const char *format,...)
|
||||||
{
|
{
|
||||||
int i;
|
int i = 0;
|
||||||
int printed_simbols;
|
int printed_simbols;
|
||||||
va_list arg;
|
va_list arg;
|
||||||
char simbol[]={"%s"};
|
char simbol[]={"%s"};
|
||||||
|
7
programs/develop/ktcc/trunk/libc/stdio/putchar.c
Normal file
7
programs/develop/ktcc/trunk/libc/stdio/putchar.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int putchar ( int ch )
|
||||||
|
{
|
||||||
|
printf("%c", ch);
|
||||||
|
return ch;
|
||||||
|
}
|
70
programs/develop/ktcc/trunk/libc/stdlib/strtod.c
Normal file
70
programs/develop/ktcc/trunk/libc/stdlib/strtod.c
Normal file
@ -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);
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
#include "ctype.h"
|
#include "ctype.h"
|
||||||
int __is[128] = {
|
char __is[128] = {
|
||||||
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
||||||
0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004,
|
0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004,
|
||||||
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
||||||
|
Loading…
Reference in New Issue
Block a user