forked from KolibriOS/kolibrios
NewLib:
- Duplicate functionality files removed; - Refactoring of file handling functions; - Removed broken impliments. Gears (C + TinyGL): - Removed because it duplicates an existing example on Fasm and uses unsupported wrappers on the KOS API. KosJS: - Removed. The MuJS port is too old and not used anywhere. Support is not profitable. Backy: - Removed useless GCC version. Support is not profitable. DGen-SDL and SQLite3 - Fix after removing broken "dirent.h". Fridge: - Moving the KOS API wrapper to avoid compilation errors. Udis86, uARM and 8086tiny: - Fix after removing redundant "kos_LoadConsole.h". git-svn-id: svn://kolibrios.org@9952 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
c6d4aab9c5
commit
9562f01892
@ -276,16 +276,14 @@ void audio_callback(void *data, unsigned char *stream, int len)
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <sys/kos_LoadConsole.h>
|
||||
#include <conio.h>
|
||||
#define kbhit con_kbhit
|
||||
#define getch con_getch
|
||||
|
||||
// Emulator entry point
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
load_console();
|
||||
con_set_title("8086tiny");
|
||||
|
||||
//freopen("OUT", "w" ,stdout);
|
||||
#ifndef NO_GRAPHICS
|
||||
// Initialise SDL
|
||||
|
@ -11,7 +11,8 @@
|
||||
//#include <sys/select.h>
|
||||
#include <signal.h>
|
||||
//#include <termios.h>
|
||||
#include <sys/kos_LoadConsole.h>
|
||||
|
||||
#include <conio.h>
|
||||
|
||||
#define getch2 con_getch
|
||||
#define cprintf printf
|
||||
@ -95,8 +96,6 @@ static int readchar(void){
|
||||
if (ret==0xD) {ret=0xA;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -165,8 +164,8 @@ int rootOps(void* userData, UInt32 sector, void* buf, UInt8 op){
|
||||
SoC soc;
|
||||
|
||||
int main(int argc, char** argv){
|
||||
load_console();
|
||||
con_set_title("uARM");
|
||||
|
||||
//CONSOLE_INIT("CONSOLE");
|
||||
|
||||
/*
|
||||
@ -228,7 +227,7 @@ void* emu_alloc(UInt32 size){
|
||||
|
||||
return calloc(size,1);
|
||||
}
|
||||
|
||||
|
||||
void emu_free(void* ptr){
|
||||
|
||||
free(ptr);
|
||||
|
@ -6,7 +6,6 @@
|
||||
* See (LICENSE)
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
#include <sys/kos_LoadConsole.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -14,6 +13,8 @@
|
||||
#include "udis86.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <conio.h>
|
||||
|
||||
#if defined(__amd64__) || defined(__x86_64__)
|
||||
# define FMT "l"
|
||||
#else
|
||||
@ -71,8 +72,8 @@ int input_hook_file(ud_t* u);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
load_console();
|
||||
con_set_title("udi disassembler");
|
||||
|
||||
FILE *stream;
|
||||
stream = fopen( "disasm.out", "w" );
|
||||
|
||||
|
@ -116,10 +116,9 @@ CORE_SRCS:= \
|
||||
sys/clock_gettime.c \
|
||||
sys/close.c \
|
||||
sys/conio.c \
|
||||
sys/create.c \
|
||||
sys/chdir.c \
|
||||
sys/getcwd.c \
|
||||
sys/errno.c \
|
||||
sys/finfo.c \
|
||||
sys/fsize.c \
|
||||
sys/fstat.c \
|
||||
sys/gettod.c \
|
||||
sys/io.c \
|
||||
@ -473,16 +472,6 @@ STDIO_SRCS= \
|
||||
wscanf.c \
|
||||
wsetup.c
|
||||
|
||||
DIRENT_SRCS= dir.c \
|
||||
closedir.c \
|
||||
opendir.c \
|
||||
readdir.c \
|
||||
rewinddir.c \
|
||||
seekdir.c \
|
||||
telldir.c \
|
||||
scandir.c \
|
||||
alphasort.c
|
||||
|
||||
MATH_SRCS = e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c e_exp.c e_fmod.c \
|
||||
e_hypot.c e_j0.c e_j1.c e_jn.c e_log.c e_log10.c e_pow.c e_rem_pio2.c \
|
||||
e_remainder.c e_scalb.c e_sinh.c e_sqrt.c ef_acos.c ef_acosh.c ef_asin.c \
|
||||
@ -539,9 +528,6 @@ STRING_OBJS = $(patsubst %.S, string/%.o, $(patsubst %.asm, string/%.o,\
|
||||
STDLIB_OBJS = $(patsubst %.S, stdlib/%.o, $(patsubst %.asm, stdlib/%.o,\
|
||||
$(patsubst %.c, stdlib/%.o, $(STDLIB_SRCS))))
|
||||
|
||||
DIRENT_OBJS = $(patsubst %.S, dirent/%.o, $(patsubst %.asm, dirent/%.o,\
|
||||
$(patsubst %.c, dirent/%.o, $(DIRENT_SRCS))))
|
||||
|
||||
MATH_OBJS = $(patsubst %.S, math/%.o, $(patsubst %.asm, math/%.o,\
|
||||
$(patsubst %.c, math/%.o, $(MATH_SRCS))))
|
||||
|
||||
|
@ -1,461 +0,0 @@
|
||||
|
||||
CC = kos32-gcc
|
||||
AR = kos32-ar
|
||||
LD = kos32-ld
|
||||
|
||||
CFLAGS = -c -O2 -march=pentium-mmx -fomit-frame-pointer -DBUILD_DLL -DMISSING_SYSCALL_NAMES
|
||||
LDFLAGS = -nostdlib -shared -s -T libcdll.lds --output-def libc.orig.def --out-implib libc.dll.a --image-base 0
|
||||
ARFLAGS = crs
|
||||
|
||||
SDK_DIR:= $(abspath ../../..)
|
||||
|
||||
LIBC_TOPDIR = .
|
||||
LIBC_INCLUDES = $(LIBC_TOPDIR)/include
|
||||
|
||||
NAME:= libc
|
||||
|
||||
DEFINES:= -D_IEEE_LIBM
|
||||
|
||||
INCLUDES:= -I $(LIBC_INCLUDES)
|
||||
|
||||
LIBPATH:= -L$(SDK_DIR)/lib -L/home/autobuild/tools/win32/mingw32/lib
|
||||
|
||||
STATIC_SRCS:= \
|
||||
crt/start.S \
|
||||
crt/crt1.c \
|
||||
crt/crt2.c \
|
||||
crt/chkstk.S \
|
||||
crt/exit.S \
|
||||
pe/crtloader.c
|
||||
|
||||
LIBDLL_SRCS:= \
|
||||
crt/dllstart.c \
|
||||
crt/chkstk.S \
|
||||
crt/exit.S \
|
||||
crt/pseudo-reloc.c \
|
||||
crt/setjmp.S
|
||||
|
||||
|
||||
LIBCDLL_SRCS:= \
|
||||
crt/crtdll.c \
|
||||
crt/pseudo-reloc.c \
|
||||
crt/chkstk.S \
|
||||
crt/exit.S \
|
||||
pe/loader.c
|
||||
|
||||
LIBCRT_SRCS:= \
|
||||
crt/start.S \
|
||||
crt/chkstk.S \
|
||||
crt/crt3.c \
|
||||
crt/pseudo-reloc.c \
|
||||
pe/crtloader.c
|
||||
|
||||
CORE_SRCS:= \
|
||||
argz/buf_findstr.c \
|
||||
argz/envz_get.c \
|
||||
crt/emutls.c \
|
||||
crt/thread.S \
|
||||
crt/tls.S \
|
||||
crt/setjmp.S \
|
||||
crt/cpu_features.c \
|
||||
ctype/ctype_.c \
|
||||
ctype/isascii.c \
|
||||
ctype/isblank.c \
|
||||
ctype/isalnum.c \
|
||||
ctype/isalpha.c \
|
||||
ctype/iscntrl.c \
|
||||
ctype/isdigit.c \
|
||||
ctype/islower.c \
|
||||
ctype/isupper.c \
|
||||
ctype/isprint.c \
|
||||
ctype/ispunct.c \
|
||||
ctype/isspace.c \
|
||||
ctype/iswctype.c \
|
||||
ctype/iswalnum.c \
|
||||
ctype/iswalpha.c \
|
||||
ctype/iswblank.c \
|
||||
ctype/iswcntrl.c \
|
||||
ctype/iswdigit.c \
|
||||
ctype/iswgraph.c \
|
||||
ctype/iswlower.c \
|
||||
ctype/iswprint.c \
|
||||
ctype/iswpunct.c \
|
||||
ctype/iswspace.c \
|
||||
ctype/iswupper.c \
|
||||
ctype/iswxdigit.c \
|
||||
ctype/isxdigit.c \
|
||||
ctype/toascii.c \
|
||||
ctype/tolower.c \
|
||||
ctype/toupper.c \
|
||||
ctype/towctrans.c \
|
||||
ctype/towlower.c \
|
||||
ctype/towupper.c \
|
||||
ctype/wctrans.c \
|
||||
ctype/wctype.c \
|
||||
errno/errno.c \
|
||||
locale/locale.c \
|
||||
locale/lctype.c \
|
||||
locale/ldpart.c \
|
||||
reent/impure.c \
|
||||
reent/init_reent.c \
|
||||
reent/getreent.c \
|
||||
reent/mutex.c \
|
||||
reent/gettimeofdayr.c \
|
||||
reent/isattyr.c \
|
||||
reent/openr.c \
|
||||
reent/closer.c \
|
||||
reent/linkr.c \
|
||||
reent/readr.c \
|
||||
reent/lseekr.c \
|
||||
reent/fstatr.c \
|
||||
reent/writer.c \
|
||||
reent/timesr.c \
|
||||
reent/unlinkr.c \
|
||||
search/qsort.c \
|
||||
search/bsearch.c \
|
||||
signal/signal.c \
|
||||
sys/close.c \
|
||||
sys/create.c \
|
||||
sys/delete.c \
|
||||
sys/errno.c \
|
||||
sys/finfo.c \
|
||||
sys/fsize.c \
|
||||
sys/fstat.c \
|
||||
sys/gettod.c \
|
||||
sys/io.c \
|
||||
sys/ioread.c \
|
||||
sys/iowrite.c \
|
||||
sys/isatty.c \
|
||||
sys/lseek.c \
|
||||
sys/open.c \
|
||||
sys/read.c \
|
||||
sys/unlink.c \
|
||||
sys/write.c \
|
||||
sys/io_alloc.S \
|
||||
time/asctime.c \
|
||||
time/asctime_r.c \
|
||||
time/clock.c \
|
||||
time/ctime.c \
|
||||
time/ctime_r.c \
|
||||
time/difftime.c \
|
||||
time/gettzinfo.c \
|
||||
time/gmtime.c \
|
||||
time/gmtime_r.c \
|
||||
time/mktime.c \
|
||||
time/mktm_r.c \
|
||||
time/lcltime.c \
|
||||
time/lcltime_r.c \
|
||||
time/strftime.c \
|
||||
time/time.c \
|
||||
time/timelocal.c \
|
||||
time/tzlock.c \
|
||||
time/tzvars.c
|
||||
|
||||
|
||||
STDLIB_SRCS= \
|
||||
__atexit.c \
|
||||
__call_atexit.c \
|
||||
abort.c \
|
||||
abs.c \
|
||||
assert.c \
|
||||
atexit.c \
|
||||
atof.c \
|
||||
atoi.c \
|
||||
atol.c \
|
||||
div.c \
|
||||
dtoa.c \
|
||||
dtoastub.c \
|
||||
exit.c \
|
||||
gdtoa-gethex.c \
|
||||
gdtoa-hexnan.c \
|
||||
getenv.c \
|
||||
mprec.c \
|
||||
mbtowc.c \
|
||||
mbtowc_r.c \
|
||||
mbrtowc.c \
|
||||
mlock.c \
|
||||
calloc.c \
|
||||
malloc.c \
|
||||
mallocr.c \
|
||||
rand.c \
|
||||
rand_r.c \
|
||||
rand48.c \
|
||||
realloc.c \
|
||||
seed48.c \
|
||||
srand48.c \
|
||||
strtod.c \
|
||||
strtol.c \
|
||||
strtold.c \
|
||||
strtoll.c \
|
||||
strtoll_r.c \
|
||||
strtoul.c \
|
||||
strtoull.c \
|
||||
strtoull_r.c \
|
||||
system.c \
|
||||
wcrtomb.c \
|
||||
wctomb_r.c
|
||||
|
||||
|
||||
STRING_SRCS= memcpy.c \
|
||||
memcmp.c \
|
||||
memmove.c \
|
||||
memset.c \
|
||||
memchr.c \
|
||||
stpcpy.c \
|
||||
stpncpy.c \
|
||||
strcat.c \
|
||||
strchr.c \
|
||||
strcmp.c \
|
||||
strcoll.c \
|
||||
strcasecmp.c \
|
||||
strncasecmp.c \
|
||||
strncat.c \
|
||||
strncmp.c \
|
||||
strncpy.c \
|
||||
strndup.c \
|
||||
strndup_r.c \
|
||||
strnlen.c \
|
||||
strcasestr.c \
|
||||
strdup.c \
|
||||
strdup_r.c \
|
||||
strerror.c \
|
||||
strlen.c \
|
||||
strrchr.c \
|
||||
strpbrk.c \
|
||||
strsep.c \
|
||||
strstr.c \
|
||||
strtok.c \
|
||||
strtok_r.c \
|
||||
strupr.c \
|
||||
strcspn.c \
|
||||
strspn.c \
|
||||
strcpy.c \
|
||||
u_strerr.c
|
||||
|
||||
STDIO_SRCS= \
|
||||
clearerr.c \
|
||||
diprintf.c \
|
||||
dprintf.c \
|
||||
printf.c \
|
||||
putchar.c \
|
||||
fgetc.c \
|
||||
fgets.c \
|
||||
fopen.c \
|
||||
fclose.c \
|
||||
fdopen.c \
|
||||
fflush.c \
|
||||
flags.c \
|
||||
fileno.c \
|
||||
findfp.c \
|
||||
fiprintf.c \
|
||||
fiscanf.c \
|
||||
fprintf.c \
|
||||
fputc.c \
|
||||
fputs.c \
|
||||
fputwc.c \
|
||||
fread.c \
|
||||
freopen.c \
|
||||
fscanf.c \
|
||||
fseek.c \
|
||||
fseeko.c \
|
||||
ftell.c \
|
||||
ftello.c \
|
||||
fwrite.c \
|
||||
fvwrite.c \
|
||||
fwalk.c \
|
||||
putc.c \
|
||||
puts.c \
|
||||
refill.c \
|
||||
rget.c \
|
||||
remove.c \
|
||||
setvbuf.c \
|
||||
stdio.c \
|
||||
tmpfile.c \
|
||||
tmpnam.c \
|
||||
ungetc.c \
|
||||
vasniprintf.c \
|
||||
vasnprintf.c \
|
||||
vdprintf.c \
|
||||
vdiprintf.c \
|
||||
vscanf.c \
|
||||
vsprintf.c \
|
||||
vsnprintf.c \
|
||||
vsscanf.c \
|
||||
makebuf.c \
|
||||
wsetup.c \
|
||||
wbuf.c \
|
||||
sccl.c \
|
||||
siprintf.c \
|
||||
sniprintf.c \
|
||||
snprintf.c \
|
||||
sprintf.c \
|
||||
sscanf.c
|
||||
|
||||
|
||||
MATH_SRCS = e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c e_exp.c e_fmod.c \
|
||||
e_hypot.c e_j0.c e_j1.c e_jn.c e_log.c e_log10.c e_pow.c e_rem_pio2.c \
|
||||
e_remainder.c e_scalb.c e_sinh.c e_sqrt.c ef_acos.c ef_acosh.c ef_asin.c \
|
||||
ef_atan2.c ef_atanh.c ef_cosh.c ef_exp.c ef_fmod.c ef_hypot.c ef_j0.c ef_j1.c \
|
||||
ef_jn.c ef_log.c ef_log10.c ef_pow.c ef_rem_pio2.c ef_remainder.c ef_scalb.c \
|
||||
ef_sinh.c ef_sqrt.c er_gamma.c er_lgamma.c erf_gamma.c erf_lgamma.c f_exp.c \
|
||||
f_expf.c f_llrint.c f_llrintf.c f_llrintl.c f_lrint.c f_lrintf.c f_lrintl.c \
|
||||
f_pow.c f_powf.c f_rint.c f_rintf.c f_rintl.c k_cos.c k_rem_pio2.c k_sin.c \
|
||||
k_standard.c k_tan.c kf_cos.c kf_rem_pio2.c kf_sin.c kf_tan.c s_asinh.c \
|
||||
s_atan.c s_cbrt.c s_ceil.c s_copysign.c s_cos.c s_erf.c s_exp10.c s_expm1.c \
|
||||
s_fabs.c s_fdim.c s_finite.c s_floor.c s_fma.c s_fmax.c s_fmin.c s_fpclassify.c \
|
||||
s_frexp.c s_ilogb.c s_infconst.c s_infinity.c s_isinf.c s_isinfd.c s_isnan.c \
|
||||
s_isnand.c s_ldexp.c s_lib_ver.c s_llrint.c s_llround.c s_log1p.c s_log2.c \
|
||||
s_logb.c s_lrint.c s_lround.c s_matherr.c s_modf.c s_nan.c s_nearbyint.c \
|
||||
s_nextafter.c s_pow10.c s_remquo.c s_rint.c s_round.c s_scalbln.c s_scalbn.c \
|
||||
s_signbit.c s_signif.c s_sin.c s_tan.c s_tanh.c s_trunc.c scalblnl.c scalbnl.c \
|
||||
sf_asinh.c sf_atan.c sf_cbrt.c sf_ceil.c sf_copysign.c sf_cos.c sf_erf.c \
|
||||
sf_exp10.c sf_expm1.c sf_fabs.c sf_fdim.c sf_finite.c sf_floor.c sf_fma.c \
|
||||
sf_fmax.c sf_fmin.c sf_fpclassify.c sf_frexp.c sf_ilogb.c sf_infinity.c \
|
||||
sf_isinf.c sf_isinff.c sf_isnan.c sf_isnanf.c sf_ldexp.c sf_llrint.c \
|
||||
sf_llround.c sf_log1p.c sf_log2.c sf_logb.c sf_lrint.c sf_lround.c sf_modf.c \
|
||||
sf_nan.c sf_nearbyint.c sf_nextafter.c sf_pow10.c sf_remquo.c sf_rint.c \
|
||||
sf_round.c sf_scalbln.c sf_scalbn.c sf_signif.c sf_sin.c sf_tan.c sf_tanh.c \
|
||||
sf_trunc.c w_acos.c w_acosh.c w_asin.c w_atan2.c w_atanh.c w_cosh.c w_drem.c \
|
||||
w_exp.c w_exp2.c w_fmod.c w_gamma.c w_hypot.c w_j0.c w_j1.c w_jn.c w_lgamma.c \
|
||||
w_log.c w_log10.c w_pow.c w_remainder.c w_scalb.c w_sincos.c w_sinh.c w_sqrt.c \
|
||||
w_tgamma.c wf_acos.c wf_acosh.c wf_asin.c wf_atan2.c wf_atanh.c wf_cosh.c \
|
||||
wf_drem.c wf_exp.c wf_exp2.c wf_fmod.c wf_gamma.c wf_hypot.c wf_j0.c wf_j1.c \
|
||||
wf_jn.c wf_lgamma.c wf_log.c wf_log10.c wf_pow.c wf_remainder.c wf_scalb.c \
|
||||
wf_sincos.c wf_sinh.c wf_sqrt.c wf_tgamma.c wr_gamma.c wr_lgamma.c wrf_gamma.c \
|
||||
wrf_lgamma.c \
|
||||
f_atan2.S f_atan2f.S f_frexp.S f_frexpf.S f_ldexp.S f_ldexpf.S f_log.S \
|
||||
f_log10.S f_log10f.S f_logf.S f_tan.S f_tanf.S
|
||||
|
||||
|
||||
STATIC_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(STATIC_SRCS)))
|
||||
|
||||
LIBCRT_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBCRT_SRCS)))
|
||||
|
||||
LIBDLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBDLL_SRCS)))
|
||||
|
||||
LIBCDLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBCDLL_SRCS)))
|
||||
|
||||
CORE_OBJS = $(patsubst %.S, %.o, $(patsubst %.asm, %.obj,\
|
||||
$(patsubst %.c, %.o, $(CORE_SRCS))))
|
||||
|
||||
STDIO_OBJS = $(patsubst %.c, stdio/%.o,$(STDIO_SRCS))
|
||||
|
||||
|
||||
STRING_OBJS = $(patsubst %.S, string/%.o, $(patsubst %.asm, string/%.o,\
|
||||
$(patsubst %.c, string/%.o, $(STRING_SRCS))))
|
||||
|
||||
STDLIB_OBJS = $(patsubst %.S, stdlib/%.o, $(patsubst %.asm, stdlib/%.o,\
|
||||
$(patsubst %.c, stdlib/%.o, $(STDLIB_SRCS))))
|
||||
|
||||
|
||||
MATH_OBJS = $(patsubst %.S, math/%.o, $(patsubst %.asm, math/%.o,\
|
||||
$(patsubst %.c, math/%.o, $(MATH_SRCS))))
|
||||
|
||||
|
||||
PRINTF_OBJS= stdio/vfprintf.o \
|
||||
stdio/vfiprintf.o \
|
||||
stdio/svfprintf.o \
|
||||
stdio/svfiprintf.o \
|
||||
stdio/vfscanf.o \
|
||||
stdio/vfiscanf.o \
|
||||
stdio/svscanf.o \
|
||||
stdio/svfiscanf.o
|
||||
|
||||
ifeq ($(findstring static,$(MAKECMDGOALS)),static)
|
||||
|
||||
LIB_SRCS:= $(STATIC_SRCS)
|
||||
LIB_OBJS:= $(STATIC_OBJS)
|
||||
|
||||
else
|
||||
|
||||
LIB_SRCS:= $(LIBCDLL_SRCS)
|
||||
LIB_OBJS:= $(LIBCDLL_OBJS)
|
||||
|
||||
endif
|
||||
|
||||
LIB_SRCS+= \
|
||||
$(CORE_SRCS) \
|
||||
$(STDIO_SRCS) \
|
||||
$(STRING_SRCS) \
|
||||
$(STDLIB_SRCS)
|
||||
|
||||
LIB_OBJS+= \
|
||||
$(CORE_OBJS) \
|
||||
$(STRING_OBJS) \
|
||||
$(STDLIB_OBJS) \
|
||||
$(STDIO_OBJS) \
|
||||
$(PRINTF_OBJS) \
|
||||
$(MATH_OBJS)
|
||||
|
||||
|
||||
|
||||
shared: $(NAME).dll libapp.a libdll.a
|
||||
|
||||
|
||||
$(NAME).dll: $(LIB_OBJS) $(SRC_DEP) Makefile
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) -o $@ $(LIB_OBJS) -lgcc --version-script libc.ver
|
||||
#sed -e "s/ @[^ ]*//" libc.orig.def > libc.def
|
||||
#sed -f cmd2.sed libc.def > mem
|
||||
#sed -f newlib.sed mem > libc.inc
|
||||
|
||||
install: libc.dll libc.dll.a libapp.a libdll.a
|
||||
mv -f libc.dll $(SDK_DIR)/bin
|
||||
mv -f libc.dll.a $(SDK_DIR)/lib
|
||||
mv -f libapp.a $(SDK_DIR)/lib
|
||||
mv -f libdll.a $(SDK_DIR)/lib
|
||||
|
||||
libapp.a: $(LIBCRT_OBJS) Makefile
|
||||
$(AR) $(ARFLAGS) libapp.a $(LIBCRT_OBJS)
|
||||
|
||||
libdll.a: $(LIBDLL_OBJS) Makefile
|
||||
$(AR) $(ARFLAGS) libdll.a $(LIBDLL_OBJS)
|
||||
|
||||
|
||||
static: $(NAME).a
|
||||
|
||||
$(NAME).a: $(LIB_OBJS) $(SRC_DEP) Makefile
|
||||
$(AR) $(ARFLAGS) $(NAME).a $(LIB_OBJS)
|
||||
|
||||
|
||||
|
||||
stdio/vfprintf.o: stdio/vfprintf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DFLOATING_POINT -c stdio/vfprintf.c -o $@
|
||||
|
||||
stdio/vfiprintf.o: stdio/vfprintf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DINTEGER_ONLY -c stdio/vfprintf.c -o $@
|
||||
|
||||
stdio/svfprintf.o: stdio/vfprintf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DSTRING_ONLY -c stdio/vfprintf.c -o $@
|
||||
|
||||
stdio/svfiprintf.o: stdio/vfprintf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DINTEGER_ONLY -DSTRING_ONLY -c stdio/vfprintf.c -o $@
|
||||
|
||||
|
||||
stdio/vfscanf.o: stdio/vfscanf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) stdio/vfscanf.c -o $@
|
||||
|
||||
stdio/vfiscanf.o: stdio/vfscanf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY $(INCLUDES) stdio/vfscanf.c -o $@
|
||||
|
||||
stdio/svscanf.o: stdio/vfscanf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) -DSTRING_ONLY $(INCLUDES) stdio/vfscanf.c -o $@
|
||||
|
||||
|
||||
stdio/svfiscanf.o: stdio/vfscanf.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY -DSTRING_ONLY $(INCLUDES) stdio/vfscanf.c -o $@
|
||||
|
||||
|
||||
|
||||
%.obj : %.asm Makefile
|
||||
fasm $< $
|
||||
|
||||
%.o : %.c Makefile
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f */*.o
|
||||
|
||||
|
||||
|
||||
|
@ -99,10 +99,9 @@ CORE_SRCS = {
|
||||
"sys/clock_gettime.c",
|
||||
"sys/close.c",
|
||||
"sys/conio.c",
|
||||
"sys/create.c",
|
||||
"sys/chdir.c",
|
||||
"sys/getcwd.c",
|
||||
"sys/errno.c",
|
||||
"sys/finfo.c",
|
||||
"sys/fsize.c",
|
||||
"sys/fstat.c",
|
||||
"sys/gettod.c",
|
||||
"sys/io.c",
|
||||
@ -455,18 +454,6 @@ STDIO_SRCS = {
|
||||
"wsetup.c"
|
||||
}
|
||||
|
||||
DIRENT_SRCS = {
|
||||
"dir.c",
|
||||
"closedir.c",
|
||||
"opendir.c",
|
||||
"readdir.c",
|
||||
"rewinddir.c",
|
||||
"seekdir.c",
|
||||
"telldir.c",
|
||||
"scandir.c",
|
||||
"alphasort.c",
|
||||
}
|
||||
|
||||
MATH_SRCS = {
|
||||
"e_acos.c", "e_acosh.c", "e_asin.c", "e_atan2.c", "e_atanh.c", "e_cosh.c", "e_exp.c", "e_fmod.c",
|
||||
"e_hypot.c", "e_j0.c", "e_j1.c", "e_jn.c", "e_log.c", "e_log10.c", "e_pow.c", "e_rem_pio2.c",
|
||||
@ -518,7 +505,6 @@ LIB_SRCS += CORE_SRCS
|
||||
LIB_SRCS += prepend("stdio/", STDIO_SRCS)
|
||||
LIB_SRCS += prepend("string/", STRING_SRCS)
|
||||
LIB_SRCS += prepend("stdlib/", STDLIB_SRCS)
|
||||
LIB_SRCS += prepend("dirent/", DIRENT_SRCS)
|
||||
LIB_SRCS += prepend("math/", MATH_SRCS)
|
||||
|
||||
ALL_OBJS = {}
|
||||
|
@ -200,6 +200,7 @@ public_jmp con_gets2, 12
|
||||
public_jmp con_cls, 0
|
||||
public_jmp con_getch2, 0
|
||||
public_jmp con_getch, 0
|
||||
public_jmp con_kbhit, 0
|
||||
public_jmp con_set_cursor_pos, 8
|
||||
public_jmp con_get_cursor_pos, 8
|
||||
public_jmp con_write_string, 8
|
||||
@ -257,6 +258,7 @@ import console, \
|
||||
con_cls, 'con_cls', \
|
||||
con_getch2, 'con_getch2', \
|
||||
con_getch, 'con_getch', \
|
||||
con_kbhit, 'con_kbhit', \
|
||||
con_set_cursor_pos, 'con_set_cursor_pos',\
|
||||
con_get_cursor_pos, 'con_get_cursor_pos', \
|
||||
con_write_string, 'con_write_string',\
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/kos_io.h>
|
||||
|
||||
struct app_hdr
|
||||
{
|
||||
|
@ -1,7 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
|
||||
int alphasort(const struct dirent **a, const struct dirent **b)
|
||||
{
|
||||
return strcoll((*a)->d_name, (*b)->d_name);
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include <sys/dirent.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int closedir(DIR *dir){
|
||||
if(dir == NULL){
|
||||
return -1;
|
||||
}else{
|
||||
free(dir->objs);
|
||||
free(dir);
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include "ksys_fs.h"
|
||||
|
||||
int rmdir(const char* dir){
|
||||
return _ksys_file_delete(dir);
|
||||
}
|
||||
|
||||
int mkdir(const char* dir, unsigned fake_mode){
|
||||
return _ksys_mkdir(dir);
|
||||
}
|
||||
|
||||
int chdir(char* dir){
|
||||
_ksys_setcwd(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *getcwd(char *buf, unsigned size){
|
||||
if(!buf){
|
||||
if((buf = malloc(size))==NULL){
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
_ksys_getcwd(buf, size);
|
||||
return(buf);
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#ifndef _KSYS_FS_H_
|
||||
#define _KSYS_FS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define asm_inline __asm__ __volatile__
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct{
|
||||
unsigned p00;
|
||||
union{
|
||||
uint64_t p04;
|
||||
struct {
|
||||
unsigned p04dw;
|
||||
unsigned p08dw;
|
||||
};
|
||||
};
|
||||
unsigned p12;
|
||||
union {
|
||||
unsigned p16;
|
||||
const char *new_name;
|
||||
void *bdfe;
|
||||
void *buf16;
|
||||
const void *cbuf16;
|
||||
};
|
||||
char p20;
|
||||
const char *p21;
|
||||
}ksys70_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned attributes;
|
||||
unsigned name_cp;
|
||||
char creation_time[4];
|
||||
char creation_date[4];
|
||||
char last_access_time[4];
|
||||
char last_access_date[4];
|
||||
char last_modification_time[4];
|
||||
char last_modification_date[4];
|
||||
unsigned long long size;
|
||||
char name[0];
|
||||
}ksys_bdfe_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
static inline
|
||||
int _ksys_work_files(const ksys70_t *k)
|
||||
{
|
||||
int status;
|
||||
asm_inline(
|
||||
"int $0x40"
|
||||
:"=a"(status)
|
||||
:"a"(70), "b"(k)
|
||||
:"memory"
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline
|
||||
int _ksys_file_delete(const char *name)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 8;
|
||||
k.p20 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys_work_files(&k);
|
||||
}
|
||||
|
||||
static inline
|
||||
int _ksys_mkdir(const char *path)
|
||||
{
|
||||
ksys70_t dir_opt;
|
||||
dir_opt.p00 = 9;
|
||||
dir_opt.p21 = path;
|
||||
return _ksys_work_files(&dir_opt);
|
||||
}
|
||||
|
||||
static inline
|
||||
void _ksys_setcwd(char* dir){
|
||||
asm_inline(
|
||||
"int $0x40"
|
||||
::"a"(30), "b"(1), "c"(dir)
|
||||
);
|
||||
}
|
||||
|
||||
static inline
|
||||
void* _ksys_alloc(size_t size){
|
||||
void *val;
|
||||
asm_inline(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(68),"b"(12),"c"(size)
|
||||
);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline
|
||||
int _ksys_free(void *mem)
|
||||
{
|
||||
int val;
|
||||
asm_inline(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(68),"b"(13),"c"(mem)
|
||||
);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline
|
||||
int _ksys_getcwd(char* buf, int bufsize){
|
||||
register int val;
|
||||
asm_inline(
|
||||
"int $0x40"
|
||||
:"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize)
|
||||
);
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,53 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include <sys/dirent.h>
|
||||
#include "ksys_fs.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK_DIR_ERR() if(_ksys_work_files(&inf)){ \
|
||||
free((void*)inf.p16); \
|
||||
errno = ENOTDIR; \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
DIR* opendir(const char* path)
|
||||
{
|
||||
DIR* list = malloc(sizeof(DIR));
|
||||
if(list==NULL){
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list->pos=0;
|
||||
unsigned num_of_file=0;
|
||||
static ksys70_t inf;
|
||||
|
||||
inf.p00 = 1;
|
||||
inf.p04 = 0;
|
||||
inf.p12 = 2;
|
||||
inf.p16 = (unsigned) malloc(32+inf.p12*560);
|
||||
inf.p20 = 0;
|
||||
inf.p21 = (char*)path;
|
||||
|
||||
CHECK_DIR_ERR();
|
||||
|
||||
num_of_file = *(unsigned*)(inf.p16+8);
|
||||
inf.p12 = num_of_file;
|
||||
free((void*)inf.p16);
|
||||
inf.p16 = (unsigned)_ksys_alloc(32+inf.p12*560);
|
||||
list->objs = (struct dirent*) malloc(num_of_file*sizeof(struct dirent));
|
||||
|
||||
CHECK_DIR_ERR();
|
||||
|
||||
for(int i=0; i<num_of_file; i++){
|
||||
list->objs[i].d_ino = i;
|
||||
list->objs[i].d_type = *(unsigned*)(inf.p16+32+(264+40)*i);
|
||||
strcpy(list->objs[i].d_name,(char*)(inf.p16+32+40+(264+40)*i));
|
||||
}
|
||||
list->num_objs = num_of_file;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include <sys/dirent.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct dirent* readdir(DIR *dir)
|
||||
{
|
||||
if(dir->num_objs>dir->pos){
|
||||
dir->pos++;
|
||||
return &dir->objs[dir->pos-1];
|
||||
}else{
|
||||
return NULL;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include <sys/dirent.h>
|
||||
|
||||
void rewinddir(DIR *dir){
|
||||
if(dir!=NULL){
|
||||
dir->pos=0;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define SIZE_MAX 256
|
||||
|
||||
int scandir(const char *path, struct dirent ***res,
|
||||
int (*sel)(const struct dirent *),
|
||||
int (*cmp)(const struct dirent **, const struct dirent **))
|
||||
{
|
||||
DIR *d = opendir(path);
|
||||
struct dirent *de, **names=0, **tmp;
|
||||
size_t cnt=0, len=0;
|
||||
int old_errno = errno;
|
||||
|
||||
if (!d) return -1;
|
||||
|
||||
while ((errno=0), (de = readdir(d))) {
|
||||
if (sel && !sel(de)) continue;
|
||||
if (cnt >= len) {
|
||||
len = 2*len+1;
|
||||
if (len > SIZE_MAX/sizeof *names) break;
|
||||
tmp = realloc(names, len * sizeof *names);
|
||||
if (!tmp) break;
|
||||
names = tmp;
|
||||
}
|
||||
names[cnt] = malloc(sizeof(struct dirent));
|
||||
if (!names[cnt]) break;
|
||||
memcpy(names[cnt++], de, sizeof(struct dirent));
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (errno) {
|
||||
if (names) while (cnt-->0) free(names[cnt]);
|
||||
free(names);
|
||||
return -1;
|
||||
}
|
||||
errno = old_errno;
|
||||
|
||||
if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp);
|
||||
*res = names;
|
||||
return cnt;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include <sys/dirent.h>
|
||||
|
||||
void seekdir(DIR *dir, unsigned pos)
|
||||
{
|
||||
if(dir==NULL || pos>dir->num_objs){
|
||||
return;
|
||||
}
|
||||
dir->pos=pos;
|
||||
return;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
|
||||
|
||||
#include <sys/dirent.h>
|
||||
|
||||
unsigned telldir(DIR *dir)
|
||||
{
|
||||
if(dir!=NULL){
|
||||
return dir->pos;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#ifndef _DIRENT_H_
|
||||
#define _DIRENT_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/dirent.h>
|
||||
|
||||
#if !defined(MAXNAMLEN) && __BSD_VISIBLE
|
||||
#define MAXNAMLEN 1024
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*_DIRENT_H_*/
|
@ -1,679 +0,0 @@
|
||||
#ifndef __KOS_32_SYS_H__
|
||||
#define __KOS_32_SYS_H__
|
||||
|
||||
#include <newlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//#ifdef CONFIG_DEBUF
|
||||
// #define DBG(format,...) printf(format,##__VA_ARGS__)
|
||||
//#else
|
||||
// #define DBG(format,...)
|
||||
//#endif
|
||||
|
||||
#define TYPE_3_BORDER_WIDTH 5
|
||||
#define WIN_STATE_MINIMIZED 0x02
|
||||
#define WIN_STATE_ROLLED 0x04
|
||||
|
||||
typedef unsigned int color_t;
|
||||
|
||||
typedef union __attribute__((packed))
|
||||
{
|
||||
uint32_t val;
|
||||
struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
};
|
||||
}pos_t;
|
||||
|
||||
typedef union __attribute__((packed))
|
||||
{
|
||||
uint32_t val;
|
||||
struct
|
||||
{
|
||||
uint8_t state;
|
||||
uint8_t code;
|
||||
uint16_t ctrl_key;
|
||||
};
|
||||
}oskey_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned handle;
|
||||
unsigned io_code;
|
||||
void *input;
|
||||
int inp_size;
|
||||
void *output;
|
||||
int out_size;
|
||||
}ioctl_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct proc_info
|
||||
{
|
||||
unsigned long cpu_usage;
|
||||
unsigned short pos_in_stack;
|
||||
unsigned short slot;
|
||||
unsigned short reserved2;
|
||||
char name[12];
|
||||
unsigned long address;
|
||||
unsigned long memory_usage;
|
||||
unsigned long ID;
|
||||
unsigned long left,top;
|
||||
unsigned long width,height;
|
||||
unsigned short thread_state;
|
||||
unsigned short reserved3;
|
||||
unsigned long cleft, ctop, cwidth, cheight;
|
||||
unsigned char window_state;
|
||||
unsigned char reserved4[1024-71];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct kolibri_system_colors {
|
||||
color_t frame_area;
|
||||
color_t grab_bar;
|
||||
color_t grab_bar_button;
|
||||
color_t grab_button_text;
|
||||
color_t grab_text;
|
||||
color_t work_area;
|
||||
color_t work_button;
|
||||
color_t work_button_text;
|
||||
color_t work_text;
|
||||
color_t work_graph;
|
||||
};
|
||||
|
||||
static inline void begin_draw(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40" ::"a"(12),"b"(1));
|
||||
};
|
||||
|
||||
static inline
|
||||
void end_draw(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40" ::"a"(12),"b"(2));
|
||||
};
|
||||
|
||||
static inline void
|
||||
put_image(uint16_t x_coord, uint16_t y_coord,
|
||||
uint16_t size_x, uint16_t size_y, void *img)
|
||||
{
|
||||
__asm__ __volatile__("int $0x40"
|
||||
::"a"(25),
|
||||
"b"(img),
|
||||
"c"(size_x<<16 | size_y),
|
||||
"d"(x_coord<<16 | y_coord));
|
||||
};
|
||||
|
||||
|
||||
static inline
|
||||
void sys_create_window(int x, int y, int w, int h, const char *name,
|
||||
color_t workcolor, uint32_t style)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(0),
|
||||
"b"((x << 16) | ((w-1) & 0xFFFF)),
|
||||
"c"((y << 16) | ((h-1) & 0xFFFF)),
|
||||
"d"((style << 24) | (workcolor & 0xFFFFFF)),
|
||||
"D"(name),
|
||||
"S"(0) : "memory");
|
||||
};
|
||||
|
||||
#define OLD -1
|
||||
static inline
|
||||
void sys_change_window(int new_x, int new_y, int new_w, int new_h)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(67), "b"(new_x), "c"(new_y), "d"(new_w),"S"(new_h)
|
||||
);
|
||||
}
|
||||
|
||||
static inline
|
||||
void define_button(uint32_t x_w, uint32_t y_h, uint32_t id, uint32_t color)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(8),
|
||||
"b"(x_w),
|
||||
"c"(y_h),
|
||||
"d"(id),
|
||||
"S"(color));
|
||||
};
|
||||
|
||||
static inline
|
||||
void draw_line(int xs, int ys, int xe, int ye, color_t color)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(38), "d"(color),
|
||||
"b"((xs << 16) | xe),
|
||||
"c"((ys << 16) | ye));
|
||||
}
|
||||
|
||||
static inline
|
||||
void draw_bar(int x, int y, int w, int h, color_t color)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(13), "d"(color),
|
||||
"b"((x << 16) | w),
|
||||
"c"((y << 16) | h));
|
||||
}
|
||||
|
||||
static inline
|
||||
void draw_bitmap(void *bitmap, int x, int y, int w, int h)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(7), "b"(bitmap),
|
||||
"c"((w << 16) | h),
|
||||
"d"((x << 16) | y));
|
||||
}
|
||||
|
||||
static inline
|
||||
void draw_text_sys(const char *text, int x, int y, int len, color_t color)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(4),"d"(text),
|
||||
"b"((x << 16) | y),
|
||||
"S"(len),"c"(color)
|
||||
:"memory");
|
||||
}
|
||||
|
||||
/*
|
||||
void define_button_text(int x, int y, int w, int h, uint32_t id, uint32_t color, char* text)
|
||||
{
|
||||
define_button(x * 65536 + w, y * 65536 + h, id, color);
|
||||
|
||||
int tx = ((((-strlen(text))*8)+w)/2)+x;
|
||||
int ty = h/2-7+y;
|
||||
|
||||
draw_text_sys(text, tx, ty, strlen(text), 0x90000000);
|
||||
};
|
||||
*/
|
||||
|
||||
static inline
|
||||
uint32_t get_skin_height(void)
|
||||
{
|
||||
uint32_t height;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40 \n\t"
|
||||
:"=a"(height)
|
||||
:"a"(48),"b"(4));
|
||||
return height;
|
||||
};
|
||||
|
||||
static inline void BeginDraw(void) __attribute__ ((alias ("begin_draw")));
|
||||
static inline void EndDraw(void) __attribute__ ((alias ("end_draw")));
|
||||
static inline void DrawWindow(int x, int y, int w, int h, const char *name,
|
||||
color_t workcolor, uint32_t style)
|
||||
__attribute__ ((alias ("sys_create_window")));
|
||||
static inline void DefineButton(void) __attribute__ ((alias ("define_button")));
|
||||
static inline void DrawLine(int xs, int ys, int xe, int ye, color_t color)
|
||||
__attribute__ ((alias ("draw_line")));
|
||||
static inline void DrawBar(int x, int y, int w, int h, color_t color)
|
||||
__attribute__ ((alias ("draw_bar")));
|
||||
static inline void DrawBitmap(void *bitmap, int x, int y, int w, int h)
|
||||
__attribute__ ((alias ("draw_bitmap")));
|
||||
static inline uint32_t GetSkinHeight(void) __attribute__ ((alias ("get_skin_height")));
|
||||
|
||||
|
||||
#define POS_SCREEN 0
|
||||
#define POS_WINDOW 1
|
||||
|
||||
static inline
|
||||
pos_t get_mouse_pos(int origin)
|
||||
{
|
||||
pos_t val;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40 \n\t"
|
||||
"rol $16, %%eax"
|
||||
:"=a"(val)
|
||||
:"a"(37),"b"(origin));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t get_mouse_buttons(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(37),"b"(2));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline
|
||||
uint32_t get_mouse_wheels(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40 \n\t"
|
||||
:"=a"(val)
|
||||
:"a"(37),"b"(7));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline uint32_t load_cursor(void *path, uint32_t flags)
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(37), "b"(4), "c"(path), "d"(flags));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t set_cursor(uint32_t cursor)
|
||||
{
|
||||
uint32_t old;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(old)
|
||||
:"a"(37), "b"(5), "c"(cursor));
|
||||
return old;
|
||||
};
|
||||
|
||||
|
||||
#define EVM_REDRAW 1
|
||||
#define EVM_KEY 2
|
||||
#define EVM_BUTTON 4
|
||||
#define EVM_EXIT 8
|
||||
#define EVM_BACKGROUND 16
|
||||
#define EVM_MOUSE 32
|
||||
#define EVM_IPC 64
|
||||
#define EVM_STACK 128
|
||||
#define EVM_DEBUG 256
|
||||
#define EVM_STACK2 512
|
||||
#define EVM_MOUSE_FILTER 0x80000000
|
||||
#define EVM_CURSOR_FILTER 0x40000000
|
||||
|
||||
static inline uint32_t set_wanted_events_mask(uint32_t event_mask)
|
||||
{
|
||||
uint32_t old_event_mask;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(old_event_mask)
|
||||
:"a"(40),"b"(event_mask));
|
||||
|
||||
return old_event_mask;
|
||||
};
|
||||
|
||||
static inline int destroy_cursor(uint32_t cursor)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(ret)
|
||||
:"a"(37), "b"(6), "c"(cursor)
|
||||
:"memory");
|
||||
return ret;
|
||||
};
|
||||
|
||||
static inline pos_t GetMousePos(int origin) __attribute__ ((alias ("get_mouse_pos")));
|
||||
static inline uint32_t GetMouseButtons(void) __attribute__ ((alias ("get_mouse_buttons")));
|
||||
static inline uint32_t GetMouseWheels(void) __attribute__ ((alias ("get_mouse_wheels")));
|
||||
|
||||
static inline uint32_t LoadCursor(void *path, uint32_t flags) __attribute__ ((alias ("load_cursor")));
|
||||
static inline uint32_t SetCursor(uint32_t cursor) __attribute__ ((alias ("set_cursor")));
|
||||
static inline int DestroyCursor(uint32_t cursor) __attribute__ ((alias ("destroy_cursor")));
|
||||
|
||||
|
||||
static inline
|
||||
uint32_t wait_for_event(uint32_t time)
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(23), "b"(time));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline uint32_t check_os_event(void)
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(11));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline uint32_t get_os_event(void)
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(10));
|
||||
return val;
|
||||
};
|
||||
static inline uint32_t GetOsEvent(void) __attribute__ ((alias ("get_os_event")));
|
||||
|
||||
static inline
|
||||
uint32_t get_tick_count(void)
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(26),"b"(9));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline
|
||||
uint64_t get_ns_count(void)
|
||||
{
|
||||
uint64_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=A"(val)
|
||||
:"a"(26), "b"(10));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline
|
||||
oskey_t get_key(void)
|
||||
{
|
||||
oskey_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(2));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t get_os_button(void)
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(17));
|
||||
return val>>8;
|
||||
};
|
||||
|
||||
static inline uint32_t
|
||||
heap_init(void)
|
||||
{
|
||||
uint32_t heapsize;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(heapsize)
|
||||
:"a"(68),"b"(11)
|
||||
);
|
||||
|
||||
return heapsize;
|
||||
}
|
||||
|
||||
static inline uint32_t get_service(char *name)
|
||||
{
|
||||
uint32_t retval = 0;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(retval)
|
||||
:"a"(68),"b"(16),"c"(name)
|
||||
:"memory");
|
||||
|
||||
return retval;
|
||||
};
|
||||
|
||||
static inline int call_service(ioctl_t *io)
|
||||
{
|
||||
int retval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(retval)
|
||||
:"a"(68),"b"(17),"c"(io)
|
||||
:"memory","cc");
|
||||
|
||||
return retval;
|
||||
};
|
||||
|
||||
|
||||
static inline void yield(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(68), "b"(1));
|
||||
};
|
||||
|
||||
static inline void delay(uint32_t time)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(5), "b"(time)
|
||||
:"memory");
|
||||
};
|
||||
|
||||
static inline
|
||||
void *user_alloc(size_t size)
|
||||
{
|
||||
void *val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(68),"b"(12),"c"(size));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline
|
||||
int user_free(void *mem)
|
||||
{
|
||||
int val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(68),"b"(13),"c"(mem));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline
|
||||
void* user_realloc(void *mem, size_t size)
|
||||
{
|
||||
void *val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(68),"b"(20),"c"(size),"d"(mem)
|
||||
:"memory");
|
||||
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline
|
||||
int *user_unmap(void *base, size_t offset, size_t size)
|
||||
{
|
||||
int *val;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(val)
|
||||
:"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size));
|
||||
return val;
|
||||
};
|
||||
|
||||
static inline void *UserAlloc(size_t size) __attribute__ ((alias ("user_alloc")));
|
||||
static inline int UserFree(void *mem) __attribute__ ((alias ("user_free")));
|
||||
static inline void* UserRealloc(void *mem, size_t size) __attribute__ ((alias ("user_realloc")));
|
||||
static inline int *UserUnmap(void *base, size_t offset, size_t size) __attribute__ ((alias ("user_unmap")));
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
void *data;
|
||||
size_t size;
|
||||
};
|
||||
unsigned long long raw;
|
||||
}ufile_t;
|
||||
|
||||
static inline ufile_t load_file(const char *path)
|
||||
{
|
||||
ufile_t uf;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"int $0x40"
|
||||
:"=A"(uf.raw)
|
||||
:"a" (68), "b"(27),"c"(path));
|
||||
|
||||
return uf;
|
||||
};
|
||||
static inline ufile_t LoadFile(const char *path) __attribute__ ((alias ("load_file")));
|
||||
|
||||
static inline int GetScreenSize(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(retval)
|
||||
:"a"(61), "b"(1));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline
|
||||
pos_t max_screen_size()
|
||||
{
|
||||
pos_t size;
|
||||
pos_t size_tmp;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(size_tmp)
|
||||
:"a"(14));
|
||||
size.x = size_tmp.y;
|
||||
size.y = size_tmp.x;
|
||||
return size;
|
||||
};
|
||||
|
||||
static inline void get_system_colors(struct kolibri_system_colors *color_table)
|
||||
{
|
||||
__asm__ volatile ("int $0x40"
|
||||
:
|
||||
:"a"(48),"b"(3),"c"(color_table),"d"(40)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void get_proc_info(char *info)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:
|
||||
:"a"(9), "b"(info), "c"(-1)
|
||||
:"memory");
|
||||
};
|
||||
static inline void GetProcInfo(char *info) __attribute__ ((alias ("get_proc_info")));
|
||||
|
||||
|
||||
struct blit_call
|
||||
{
|
||||
int dstx;
|
||||
int dsty;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
int srcx;
|
||||
int srcy;
|
||||
int srcw;
|
||||
int srch;
|
||||
|
||||
void *bitmap;
|
||||
int stride;
|
||||
};
|
||||
|
||||
static inline void Blit(void *bitmap, int dst_x, int dst_y,
|
||||
int src_x, int src_y, int w, int h,
|
||||
int src_w, int src_h, int stride)
|
||||
{
|
||||
volatile struct blit_call bc;
|
||||
|
||||
bc.dstx = dst_x;
|
||||
bc.dsty = dst_y;
|
||||
bc.w = w;
|
||||
bc.h = h;
|
||||
bc.srcx = src_x;
|
||||
bc.srcy = src_y;
|
||||
bc.srcw = src_w;
|
||||
bc.srch = src_h;
|
||||
bc.stride = stride;
|
||||
bc.bitmap = bitmap;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(73),"b"(0),"c"(&bc.dstx));
|
||||
};
|
||||
|
||||
#define TLS_KEY_PID 0
|
||||
#define TLS_KEY_TID 4
|
||||
#define TLS_KEY_LOW_STACK 8
|
||||
#define TLS_KEY_HIGH_STACK 12
|
||||
#define TLS_KEY_LIBC 16
|
||||
|
||||
unsigned int tls_alloc(void);
|
||||
int tls_free(unsigned int key);
|
||||
|
||||
static inline int tls_set(unsigned int key, void *val)
|
||||
{
|
||||
int ret = -1;
|
||||
if(key < 4096)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"movl %0, %%fs:(%1)"
|
||||
::"r"(val),"r"(key));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
static inline void *tls_get(unsigned int key)
|
||||
{
|
||||
void *val = (void*)-1;
|
||||
if(key < 4096)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"movl %%fs:(%1), %0"
|
||||
:"=r"(val)
|
||||
:"r"(key));
|
||||
};
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
int create_thread(int (*proc)(void *param), void *param, int stack_size);
|
||||
|
||||
void* load_library(const char *name);
|
||||
|
||||
void* get_proc_address(void *handle, const char *proc_name);
|
||||
|
||||
void enumerate_libraries(int (*callback)(void *handle, const char* name,
|
||||
uint32_t base, uint32_t size, void *user_data),
|
||||
void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
/* BSD predecessor of POSIX.1 <dirent.h> and struct dirent */
|
||||
|
||||
#ifndef _SYS_DIR_H_
|
||||
#define _SYS_DIR_H_
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#define direct dirent
|
||||
|
||||
extern int chdir(char* dir);
|
||||
extern int rmdir(const char* dir);
|
||||
extern int mkdir(const char* dir, unsigned fake_mode);
|
||||
|
||||
#endif /*_SYS_DIR_H_*/
|
@ -1,41 +0,0 @@
|
||||
/* <dirent.h> includes <sys/dirent.h>, which is this file. On a
|
||||
system which supports <dirent.h>, this file is overridden by
|
||||
dirent.h in the libc/sys/.../sys directory. On a system which does
|
||||
not support <dirent.h>, we will get this file which uses #error to force
|
||||
an error. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DT_DIR 16
|
||||
#define DT_REG 0
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct dirent{
|
||||
ino_t d_ino;
|
||||
unsigned d_type;
|
||||
char d_name[256];
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
struct dirent* objs;
|
||||
ino_t pos;
|
||||
ino_t num_objs;
|
||||
}DIR;
|
||||
|
||||
extern int closedir(DIR *dir);
|
||||
extern DIR* opendir(const char *path);
|
||||
extern struct dirent* readdir(DIR *);
|
||||
extern void rewinddir(DIR *dir);
|
||||
extern void seekdir(DIR *dir, unsigned pos);
|
||||
extern unsigned telldir(DIR *dir);
|
||||
|
||||
extern int scandir(const char *path, struct dirent ***res, int (*sel)(const struct dirent *), int (*cmp)(const struct dirent **, const struct dirent **));
|
||||
extern int alphasort(const struct dirent **a, const struct dirent **b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,147 +0,0 @@
|
||||
// Console.obj loading for kos32-gcc
|
||||
// Writed by rgimad and maxcodehack
|
||||
//
|
||||
// Usage:
|
||||
// #include <sys/kos_LoadConsole.h>
|
||||
// load_console();
|
||||
//
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef CONSOLE_OBJ_H
|
||||
#define CONSOLE_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef cdecl
|
||||
#define cdecl __attribute__ ((cdecl))
|
||||
#endif
|
||||
|
||||
#ifndef stdcall
|
||||
#define stdcall __attribute__ ((stdcall))
|
||||
#endif
|
||||
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned short word;
|
||||
|
||||
const char* imports[] = {
|
||||
"START", "version", "con_init", "con_write_asciiz", "con_write_string",
|
||||
"con_printf", "con_exit", "con_get_flags", "con_set_flags", "con_kbhit",
|
||||
"con_getch", "con_getch2", "con_gets", "con_gets2", "con_get_font_height",
|
||||
"con_get_cursor_height", "con_set_cursor_height", "con_cls",
|
||||
"con_get_cursor_pos", "con_set_cursor_pos", "con_set_title",
|
||||
(char*)0
|
||||
};
|
||||
|
||||
dword *version;
|
||||
|
||||
typedef int (stdcall * con_gets2_callback)(int keycode, char** pstr, int* pn,
|
||||
int* ppos);
|
||||
|
||||
void stdcall (*con_init)(dword wnd_width, dword wnd_height, dword scr_width, dword scr_height, const char* title) = 0;
|
||||
void stdcall (*con_exit)(int bCloseWindow) = 0;
|
||||
void stdcall (*con_set_title)(const char* title) = 0;
|
||||
void stdcall (*con_write_asciiz)(const char* str) = 0;
|
||||
void stdcall (*con_write_string)(const char* str, dword length) = 0;
|
||||
int cdecl (*con_printf)(const char* format, ...) = 0;
|
||||
dword stdcall (*con_get_flags)(void) = 0;
|
||||
dword stdcall (*con_set_flags)(dword new_flags) = 0;
|
||||
int stdcall (*con_get_font_height)(void) = 0;
|
||||
int stdcall (*con_get_cursor_height)(void) = 0;
|
||||
int stdcall (*con_set_cursor_height)(int new_height) = 0;
|
||||
int stdcall (*con_getch)(void) = 0;
|
||||
word stdcall (*con_getch2)(void) = 0;
|
||||
int stdcall (*con_kbhit)(void) = 0;
|
||||
char* stdcall (*con_gets)(char* str, int n) = 0;
|
||||
char* stdcall (*con_gets2)(con_gets2_callback callback, char* str, int n) = 0;
|
||||
void stdcall (*con_cls)() = 0;
|
||||
void stdcall (*con_get_cursor_pos)(int* px, int* py) = 0;
|
||||
void stdcall (*con_set_cursor_pos)(int x, int y) = 0;
|
||||
|
||||
const char lib_path[] = "/sys/lib/console.obj";
|
||||
|
||||
void* load_library(const char *name)
|
||||
{
|
||||
void *table;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(table)
|
||||
:"a"(68), "b"(19), "c"(name));
|
||||
return table;
|
||||
}
|
||||
|
||||
void *load_library_procedure(void *exports, const char *name)
|
||||
{
|
||||
if (exports == NULL) { return 0; }
|
||||
while (*(dword*)exports != 0)
|
||||
{
|
||||
char *str1 = (char*)(*(dword*)exports);
|
||||
if (strcmp(str1, name) == 0)
|
||||
{
|
||||
void *ptr = (void*)*(dword*)(exports + 4);
|
||||
return ptr;
|
||||
}
|
||||
exports += 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void output_debug_string(const char *s)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while(*(s + i))
|
||||
{
|
||||
__asm__ __volatile__ ("int $0x40"::"a"(63), "b"(1), "c"(*(s + i)));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void load_console()
|
||||
{
|
||||
void *lib = load_library(lib_path);
|
||||
|
||||
if (!lib)
|
||||
{
|
||||
output_debug_string("Console.obj loading error\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dword (*start_lib)(dword) = (dword(*)(dword))load_library_procedure(lib, imports[0]);
|
||||
|
||||
version = (dword*)load_library_procedure(lib, imports[1]);
|
||||
|
||||
con_init = (void stdcall(*)(dword,dword,dword,dword,const char*))load_library_procedure(lib, imports[2]);
|
||||
con_write_asciiz = (void stdcall(*)(const char*))load_library_procedure(lib, imports[3]);
|
||||
con_write_string = (void stdcall(*)(const char*,dword))load_library_procedure(lib, imports[4]);
|
||||
con_printf = (int cdecl(*)(const char*,...))load_library_procedure(lib, imports[5]);
|
||||
con_exit = (void stdcall(*)(int))load_library_procedure(lib, imports[6]);
|
||||
con_get_flags = (dword stdcall(*)(void))load_library_procedure(lib, imports[7]);
|
||||
con_set_flags = (dword stdcall(*)(dword))load_library_procedure(lib, imports[8]);
|
||||
con_kbhit = (int stdcall(*)(void))load_library_procedure(lib, imports[9]);
|
||||
con_getch = (int stdcall(*)(void))load_library_procedure(lib, imports[10]);
|
||||
con_getch2 = (word stdcall(*)(void))load_library_procedure(lib, imports[11]);
|
||||
con_gets = (char* stdcall(*)(char*,int))load_library_procedure(lib, imports[12]);
|
||||
con_gets2 = (char* stdcall(*)(con_gets2_callback,char*,int))load_library_procedure(lib, imports[13]);
|
||||
con_get_font_height = (int stdcall(*)(void))load_library_procedure(lib, imports[14]);
|
||||
con_get_cursor_height = (int stdcall(*)(void))load_library_procedure(lib, imports[15]);
|
||||
con_set_cursor_height = (int stdcall(*)(int))load_library_procedure(lib, imports[16]);
|
||||
con_cls = (void stdcall(*)(void))load_library_procedure(lib, imports[17]);
|
||||
con_get_cursor_pos = (void stdcall(*)(int*,int*))load_library_procedure(lib, imports[18]);
|
||||
con_set_cursor_pos = (void stdcall(*)(int,int))load_library_procedure(lib, imports[19]);
|
||||
con_set_title = (void stdcall(*)(const char*))load_library_procedure(lib, imports[20]);
|
||||
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,85 +0,0 @@
|
||||
|
||||
#ifndef __KOS_IO_H__
|
||||
#define __KOS_IO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
char sec;
|
||||
char min;
|
||||
char hour;
|
||||
char rsv;
|
||||
}detime_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char day;
|
||||
char month;
|
||||
short year;
|
||||
}dedate_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned attr;
|
||||
unsigned flags;
|
||||
union
|
||||
{
|
||||
detime_t ctime;
|
||||
unsigned cr_time;
|
||||
};
|
||||
union
|
||||
{
|
||||
dedate_t cdate;
|
||||
unsigned cr_date;
|
||||
};
|
||||
union
|
||||
{
|
||||
detime_t atime;
|
||||
unsigned acc_time;
|
||||
};
|
||||
union
|
||||
{
|
||||
dedate_t adate;
|
||||
unsigned acc_date;
|
||||
};
|
||||
union
|
||||
{
|
||||
detime_t mtime;
|
||||
unsigned mod_time;
|
||||
};
|
||||
union
|
||||
{
|
||||
dedate_t mdate;
|
||||
unsigned mod_date;
|
||||
};
|
||||
unsigned size;
|
||||
unsigned size_high;
|
||||
} fileinfo_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
int create_file(const char *path);
|
||||
int get_fileinfo(const char *path, fileinfo_t *info);
|
||||
int set_fileinfo(const char *path, fileinfo_t *info);
|
||||
int read_file(const char *path, void *buff,
|
||||
size_t offset, size_t count, size_t *reads);
|
||||
int write_file(const char *path,const void *buff,
|
||||
size_t offset, size_t count, size_t *writes);
|
||||
int set_file_size(const char *path, unsigned size);
|
||||
void unpack(void* packed_data, void* unpacked_data) __attribute__((stdcall)) ;
|
||||
|
||||
static inline void set_cwd(const char* cwd)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(30),"b"(1),"c"(cwd));
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -82,43 +83,48 @@ typedef struct {
|
||||
} ksys_ufile_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t p00;
|
||||
uint32_t func_num;
|
||||
union {
|
||||
uint64_t p04;
|
||||
uint64_t offset64;
|
||||
struct {
|
||||
uint32_t p04dw;
|
||||
uint32_t p08dw;
|
||||
union {
|
||||
uint32_t debug;
|
||||
uint32_t offset;
|
||||
};
|
||||
union {
|
||||
uint32_t flags;
|
||||
char* args;
|
||||
};
|
||||
};
|
||||
};
|
||||
uint32_t p12;
|
||||
uint32_t data_size;
|
||||
void* data;
|
||||
union {
|
||||
uint32_t p16;
|
||||
const char* new_name;
|
||||
void* bdfe;
|
||||
void* buf16;
|
||||
const void* cbuf16;
|
||||
struct {
|
||||
uint8_t zero;
|
||||
char* path_ptr;
|
||||
};
|
||||
char path[0];
|
||||
};
|
||||
char p20;
|
||||
const char* p21;
|
||||
} ksys70_t;
|
||||
} ksys_file_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t status;
|
||||
uint32_t rw_bytes;
|
||||
} ksys70_status_t;
|
||||
} ksys_file_status_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t attributes;
|
||||
uint32_t name_cp;
|
||||
ksys_time_t creation_time;
|
||||
ksys_date_t creation_date;
|
||||
ksys_time_t last_access_time;
|
||||
ksys_date_t last_access_date;
|
||||
ksys_time_t last_modification_time;
|
||||
ksys_date_t last_modification_date;
|
||||
uint32_t attr;
|
||||
uint32_t name_enc;
|
||||
ksys_time_t ctime;
|
||||
ksys_date_t cdate;
|
||||
ksys_time_t atime;
|
||||
ksys_date_t adate;
|
||||
ksys_time_t mtime;
|
||||
ksys_date_t mdate;
|
||||
uint64_t size;
|
||||
char name[0];
|
||||
} ksys_bdfe_t;
|
||||
} ksys_file_info_t;
|
||||
|
||||
#define KSYS_THREAD_INFO_SIZE 1024
|
||||
|
||||
@ -1483,125 +1489,166 @@ KOSAPI ksys_ufile_t _ksys_load_file_enc(const char* path, unsigned file_encoding
|
||||
|
||||
/*==== Function 70 - work with file system with long names support. ====*/
|
||||
|
||||
KOSAPI ksys70_status_t _ksys70(const ksys70_t* k)
|
||||
enum KSYS_FILE_FUNC {
|
||||
KSYS_FILE_READ = 0,
|
||||
KSYS_FILE_READ_DIR,
|
||||
KSYS_FILE_CREATE,
|
||||
KSYS_FILE_WRITE,
|
||||
KSYS_FILE_SET_SIZE,
|
||||
KSYS_FILE_GET_INFO,
|
||||
KSYS_FILE_SET_ATTR,
|
||||
KSYS_FILE_EXEC,
|
||||
KSYS_FILE_REMOVE,
|
||||
KSYS_FILE_CREATE_DIR,
|
||||
KSYS_FILE_RENAME,
|
||||
};
|
||||
|
||||
KOSAPI ksys_file_status_t _ksys_file(const ksys_file_t* info)
|
||||
{
|
||||
ksys70_status_t status;
|
||||
ksys_file_status_t st;
|
||||
asm_inline(
|
||||
"int $0x40"
|
||||
: "=a"(status.status), "=b"(status.rw_bytes)
|
||||
: "a"(70), "b"(k)
|
||||
: "=a"(st.status), "=b"(st.rw_bytes)
|
||||
: "a"(70), "b"(info)
|
||||
: "memory");
|
||||
return status;
|
||||
return st;
|
||||
}
|
||||
|
||||
/*====== Function 70, subfunction 0 - read file with long names support. ======*/
|
||||
|
||||
KOSAPI ksys70_status_t _ksys_file_read(const char* name, uint64_t offset, uint32_t size, void* buf)
|
||||
KOSAPI ksys_file_status_t _ksys_file_read(const char* name, uint64_t offset, uint32_t size, void* buf)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 0;
|
||||
k.p04 = offset;
|
||||
k.p12 = size;
|
||||
k.buf16 = buf;
|
||||
k.p20 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys70(&k);
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_READ;
|
||||
f.offset64 = offset;
|
||||
f.data_size = size;
|
||||
f.data = buf;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)name;
|
||||
return _ksys_file(&f);
|
||||
}
|
||||
|
||||
/*===================== Function 70, subfunction 2 =====================*/
|
||||
/*============ Create/rewrite file with long names support. ============*/
|
||||
|
||||
KOSAPI int _ksys_file_create(const char* name)
|
||||
KOSAPI ksys_file_status_t _ksys_file_create(const char* name)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 2;
|
||||
k.p04dw = 0;
|
||||
k.p08dw = 0;
|
||||
k.p12 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys70(&k).status;
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_CREATE;
|
||||
f.offset64 = 0;
|
||||
f.data_size = 0;
|
||||
f.data = NULL;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)name;
|
||||
return _ksys_file(&f);
|
||||
}
|
||||
|
||||
/*===================== Function 70, subfunction 3 =====================*/
|
||||
/*=========== Write to existing file with long names support. ==========*/
|
||||
|
||||
KOSAPI ksys70_status_t _ksys_file_write(const char* name, uint64_t offset, uint32_t size, const void* buf)
|
||||
KOSAPI ksys_file_status_t _ksys_file_write(const char* name, uint64_t offset, uint32_t size, const void* buf)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 3;
|
||||
k.p04 = offset;
|
||||
k.p12 = size;
|
||||
k.cbuf16 = buf;
|
||||
k.p20 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys70(&k);
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_WRITE;
|
||||
f.offset64 = offset;
|
||||
f.data_size = size;
|
||||
f.data = (void*)buf;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)name;
|
||||
return _ksys_file(&f);
|
||||
}
|
||||
|
||||
/*========== Function 70, subfunction 4 - set file size. =====*/
|
||||
|
||||
KOSAPI int _ksys_file_set_size(const char* name, uint64_t size)
|
||||
{
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_SET_SIZE;
|
||||
f.offset64 = size;
|
||||
f.data_size = 0;
|
||||
f.data = NULL;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)name;
|
||||
return _ksys_file(&f).status;
|
||||
}
|
||||
|
||||
/*========== Function 70, subfunction 5 - get information on file/folder. =====*/
|
||||
|
||||
KOSAPI int _ksys_file_info(const char* name, ksys_bdfe_t* bdfe)
|
||||
KOSAPI int _ksys_file_info(const char* name, ksys_file_info_t* info)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 5;
|
||||
k.p04dw = 0;
|
||||
k.p08dw = 0;
|
||||
k.p12 = 0;
|
||||
k.bdfe = bdfe;
|
||||
k.p20 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys70(&k).status;
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_GET_INFO;
|
||||
f.offset64 = 0;
|
||||
f.data_size = 0;
|
||||
f.data = (void*)info;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)name;
|
||||
return _ksys_file(&f).status;
|
||||
}
|
||||
|
||||
#define _ksys_dir_info _ksys_file_info
|
||||
|
||||
KOSAPI uint64_t _ksys_file_get_size(const char* name, int* err)
|
||||
{
|
||||
ksys_file_info_t info;
|
||||
*err = _ksys_file_info(name, &info);
|
||||
return info.size;
|
||||
}
|
||||
|
||||
#define _ksys_dir_info _ksys_file_info
|
||||
|
||||
/*=========== Function 70, subfunction 7 - start application. ===========*/
|
||||
|
||||
KOSAPI int _ksys_exec(const char* app_name, char* args)
|
||||
KOSAPI int _ksys_exec(const char* path, char* args, bool debug)
|
||||
{
|
||||
ksys70_t file_opt;
|
||||
file_opt.p00 = 7;
|
||||
file_opt.p04dw = 0;
|
||||
file_opt.p08dw = (uint32_t)args;
|
||||
|
||||
file_opt.p12 = 0;
|
||||
file_opt.p16 = 0;
|
||||
file_opt.p20 = 0;
|
||||
|
||||
file_opt.p21 = app_name;
|
||||
return _ksys70(&file_opt).status;
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_EXEC;
|
||||
f.debug = debug;
|
||||
f.args = args;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)path;
|
||||
return _ksys_file(&f).status;
|
||||
}
|
||||
|
||||
/*========== Function 70, subfunction 8 - delete file/folder. ==========*/
|
||||
|
||||
KOSAPI int _ksys_file_delete(const char* name)
|
||||
KOSAPI int _ksys_file_delete(const char* path)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 8;
|
||||
k.p20 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys70(&k).status;
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_REMOVE;
|
||||
f.offset64 = 0;
|
||||
f.data_size = 0;
|
||||
f.data = NULL;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)path;
|
||||
return _ksys_file(&f).status;
|
||||
}
|
||||
|
||||
/*============= Function 70, subfunction 9 - create folder. =============*/
|
||||
|
||||
KOSAPI int _ksys_mkdir(const char* path)
|
||||
{
|
||||
ksys70_t dir_opt;
|
||||
dir_opt.p00 = 9;
|
||||
dir_opt.p21 = path;
|
||||
return _ksys70(&dir_opt).status;
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_CREATE_DIR;
|
||||
f.offset64 = 0;
|
||||
f.data_size = 0;
|
||||
f.data = NULL;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)path;
|
||||
return _ksys_file(&f).status;
|
||||
}
|
||||
|
||||
/*============= Function 70, subfunction 10 - rename/move. =============*/
|
||||
|
||||
KOSAPI int _ksys_file_rename(const char* name, const char* new_name)
|
||||
{
|
||||
ksys70_t k;
|
||||
k.p00 = 10;
|
||||
k.new_name = new_name;
|
||||
k.p20 = 0;
|
||||
k.p21 = name;
|
||||
return _ksys70(&k).status;
|
||||
ksys_file_t f;
|
||||
f.func_num = KSYS_FILE_REMOVE;
|
||||
f.data = (void*)new_name;
|
||||
f.data_size = 0;
|
||||
f.zero = 0;
|
||||
f.path_ptr = (char*)name;
|
||||
return _ksys_file(&f).status;
|
||||
}
|
||||
|
||||
#define _ksys_dir_rename _ksys_file_rename
|
||||
@ -1707,25 +1754,6 @@ KOSAPI int _ksys_posix_pipe2(int pipefd[2], int flags)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ######### Old names of functions and structures. Do not use again! ##########*/
|
||||
|
||||
#define _ksys_get_event _ksys_wait_event
|
||||
#define _ksys_file_get_info _ksys_file_info
|
||||
|
||||
static inline int _ksys_file_read_file(const char* name, unsigned long long offset, unsigned size, void* buff, unsigned* bytes_read)
|
||||
{
|
||||
ksys70_status_t res = _ksys_file_read(name, offset, size, buff);
|
||||
*bytes_read = res.rw_bytes;
|
||||
return res.status;
|
||||
}
|
||||
|
||||
static inline int _ksys_file_write_file(const char* name, unsigned long long offset, unsigned size, const void* buff, unsigned* bytes_write)
|
||||
{
|
||||
ksys70_status_t res = _ksys_file_write(name, offset, size, buff);
|
||||
*bytes_write = res.rw_bytes;
|
||||
return res.status;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,216 +0,0 @@
|
||||
#ifndef __SOCKET_H__
|
||||
#define __SOCKET_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// Socket Types
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define SOCK_RAW 3
|
||||
|
||||
// IP protocols
|
||||
#define IPPROTO_IP 0
|
||||
#define IPPROTO_ICMP 1
|
||||
#define IPPROTO_TCP 6
|
||||
#define IPPROTO_UDP 17
|
||||
#define IPPROTO_RAW 255
|
||||
|
||||
// IP options
|
||||
#define IP_TTL 2
|
||||
|
||||
// Address families
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_LOCAL 1
|
||||
#define AF_INET 2 // Default INET=IPv4
|
||||
#define AF_INET4 2 // IPv4
|
||||
#define AF_INET6 10 // IPv6
|
||||
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
#define PF_LOCAL AF_LOCAL
|
||||
#define PF_INET4 AF_INET4
|
||||
#define PF_INET6 AF_INET6
|
||||
|
||||
// internal definition
|
||||
#define AI_SUPPORTED 0x40F
|
||||
|
||||
// for system function 76
|
||||
#define API_ETH (0<<16)
|
||||
#define API_IPv4 (1<<16)
|
||||
#define API_ICMP (2<<16)
|
||||
#define API_UDP (3<<16)
|
||||
#define API_TCP (4<<16)
|
||||
#define API_ARP (5<<16)
|
||||
#define API_PPPOE (6<<16)
|
||||
|
||||
// Socket flags for user calls
|
||||
#define MSG_NOFLAG 0
|
||||
#define MSG_PEEK 0x02
|
||||
#define MSG_DONTWAIT 0x40
|
||||
|
||||
// Socket levels
|
||||
#define SOL_SOCKET 0xffff
|
||||
|
||||
//Socket options
|
||||
#define SO_BINDTODEVICE (1<<9)
|
||||
#define SO_NONBLOCK (1<<31)
|
||||
|
||||
// Error Codes
|
||||
#define ENOBUFS 1
|
||||
#define EINPROGRESS 2
|
||||
#define EOPNOTSUPP 4
|
||||
#define EWOULDBLOCK 6
|
||||
#define ENOTCONN 9
|
||||
#define EALREADY 10
|
||||
#define EINVALUE 11
|
||||
#define EMSGSIZE 12
|
||||
#define ENOMEM 18
|
||||
#define EADDRINUSE 20
|
||||
#define ECONNREFUSED 61
|
||||
#define ECONNRESET 52
|
||||
#define EISCONN 56
|
||||
#define ETIMEDOUT 60
|
||||
#define ECONNABORTED 53
|
||||
|
||||
|
||||
#define PORT(X) (X<<8)
|
||||
int err_code;
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct sockaddr{
|
||||
unsigned short sin_family;
|
||||
unsigned short sin_port;
|
||||
unsigned int sin_addr;
|
||||
unsigned long long sin_zero;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct{
|
||||
unsigned int level;
|
||||
unsigned int optionname;
|
||||
unsigned int optlenght;
|
||||
unsigned char options;
|
||||
}optstruct;
|
||||
#pragma pack(pop)
|
||||
|
||||
static inline int socket(int domain, int type, int protocol)
|
||||
{
|
||||
int socket;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(socket)
|
||||
:"a"(75), "b"(0), "c"(domain), "d"(type), "S"(protocol)
|
||||
);
|
||||
return socket;
|
||||
}
|
||||
|
||||
static inline int close(int socket)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(1), "c"(socket)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int bind(int socket, const struct sockaddr *addres, int addres_len)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(2), "c"(socket), "d"(addres), "S"(addres_len)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int listen(int socket, int backlog)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(3), "c"(socket), "d"(backlog)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int connect(int socket, const struct sockaddr* address, int socket_len)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(4), "c"(socket), "d"(address), "S"(socket_len)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int accept(int socket, const struct sockaddr *address, int address_len)
|
||||
{
|
||||
int new_socket;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(new_socket)
|
||||
:"a"(75), "b"(5), "c"(socket), "d"(address), "S"(address_len)
|
||||
);
|
||||
return new_socket;
|
||||
}
|
||||
|
||||
static inline int send(int socket, const void *message, size_t msg_len, int flag)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(6), "c"(socket), "d"(message), "S"(msg_len), "D"(flag)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int recv(int socket, void *buffer, size_t buff_len, int flag)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(7), "c"(socket), "d"(buffer), "S"(buff_len), "D"(flag)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int setsockopt(int socket,const optstruct* opt)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(8), "c"(socket),"d"(opt)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int getsockopt(int socket, optstruct* opt)
|
||||
{
|
||||
int status;
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(err_code), "=a"(status)
|
||||
:"a"(75), "b"(9), "c"(socket),"d"(opt)
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int socketpair(int *socket1, int *socket2)
|
||||
{
|
||||
asm volatile(
|
||||
"int $0x40"
|
||||
:"=b"(*socket2), "=a"(*socket1)
|
||||
:"a"(75), "b"(10)
|
||||
);
|
||||
err_code=*socket2;
|
||||
return *socket1;
|
||||
}
|
||||
#endif
|
@ -10,6 +10,7 @@ extern "C" {
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/_timespec.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
/* dj's stat defines _STAT_H_ */
|
||||
#ifndef _STAT_H_
|
||||
@ -147,11 +148,12 @@ struct stat
|
||||
int _EXFUN(chmod,( const char *__path, mode_t __mode ));
|
||||
int _EXFUN(fchmod,(int __fd, mode_t __mode));
|
||||
int _EXFUN(fstat,( int __fd, struct stat *__sbuf ));
|
||||
int _EXFUN(mkdir,( const char *_path, mode_t __mode ));
|
||||
int _EXFUN(mkfifo,( const char *__path, mode_t __mode ));
|
||||
int _EXFUN(stat,( const char *__restrict __path, struct stat *__restrict __sbuf ));
|
||||
mode_t _EXFUN(umask,( mode_t __mask ));
|
||||
|
||||
#define mkdir(path, mode) _ksys_mkdir(path)
|
||||
|
||||
#if defined (__SPU__) || defined(__rtems__) || defined(__CYGWIN__) && !defined(__INSIDE_CYGWIN__)
|
||||
int _EXFUN(lstat,( const char *__restrict __path, struct stat *__restrict __buf ));
|
||||
int _EXFUN(mknod,( const char *__path, mode_t __mode, dev_t __dev ));
|
||||
|
@ -1,522 +0,0 @@
|
||||
EXPORTS
|
||||
_Balloc
|
||||
_Bfree
|
||||
_Exit DATA
|
||||
__assert
|
||||
__assert_func
|
||||
__ctype_ptr__ DATA
|
||||
__emutls_get_address
|
||||
__errno
|
||||
__fpclassifyd
|
||||
__fpclassifyf
|
||||
__mutex_lock
|
||||
__signbitd
|
||||
__signbitf
|
||||
__srget_r
|
||||
__swbuf_r
|
||||
_atoi_r
|
||||
_atol_r
|
||||
_buf_findstr
|
||||
_calloc_r
|
||||
_cleanup
|
||||
_cleanup_r
|
||||
_close_r
|
||||
_ctype_ DATA
|
||||
_daylight DATA
|
||||
_diprintf_r
|
||||
_dprintf_r
|
||||
_dtoa_r
|
||||
_exit DATA
|
||||
_f_atan2 DATA
|
||||
_f_atan2f DATA
|
||||
_f_exp
|
||||
_f_expf
|
||||
_f_frexp DATA
|
||||
_f_frexpf DATA
|
||||
_f_ldexp DATA
|
||||
_f_ldexpf DATA
|
||||
_f_llrint
|
||||
_f_llrintf
|
||||
_f_llrintl
|
||||
_f_log DATA
|
||||
_f_log10 DATA
|
||||
_f_log10f DATA
|
||||
_f_logf DATA
|
||||
_f_lrint
|
||||
_f_lrintf
|
||||
_f_lrintl
|
||||
_f_pow
|
||||
_f_powf
|
||||
_f_rint
|
||||
_f_rintf
|
||||
_f_rintl
|
||||
_f_tan DATA
|
||||
_f_tanf DATA
|
||||
_fclose_r
|
||||
_fdopen_r
|
||||
_fflush_r
|
||||
_fgetc_r
|
||||
_fgets_r
|
||||
_findenv
|
||||
_fiprintf_r
|
||||
_fiscanf_r
|
||||
_fopen_r
|
||||
_fprintf_r
|
||||
_fputc_r
|
||||
_fputs_r
|
||||
_fputwc_r
|
||||
_fread_r
|
||||
_free_r
|
||||
_freopen_r
|
||||
_fscanf_r
|
||||
_fseek_r
|
||||
_fseeko_r
|
||||
_fstat_r
|
||||
_ftell_r
|
||||
_ftello_r
|
||||
_fwalk
|
||||
_fwalk_reent
|
||||
_fwrite_r
|
||||
_gettimeofday
|
||||
_gettimeofday_r
|
||||
_global_impure_ptr DATA
|
||||
_grow_handles
|
||||
_init_signal
|
||||
_init_signal_r
|
||||
_isatty
|
||||
_isatty_r
|
||||
_kill_r
|
||||
_localeconv_r
|
||||
_lseek_r
|
||||
_malloc_r
|
||||
_mbrtowc_r
|
||||
_mbtowc_r
|
||||
_mktm_r
|
||||
_mprec_log10
|
||||
_open_r
|
||||
_printf_r
|
||||
_putc_r
|
||||
_putchar_r
|
||||
_puts_r
|
||||
_raise_r
|
||||
_read
|
||||
_read_r
|
||||
_realloc_r
|
||||
_remove_r
|
||||
_rename_r
|
||||
_seed48_r
|
||||
_setlocale_r
|
||||
_sfread_r
|
||||
_signal_r
|
||||
_siprintf_r
|
||||
_sniprintf_r
|
||||
_snprintf_r
|
||||
_sprintf_r
|
||||
_srand48_r
|
||||
_sscanf_r
|
||||
_strdup_r
|
||||
_strerror_r
|
||||
_strndup_r
|
||||
_strtod_r
|
||||
_strtol_r
|
||||
_strtoll_r
|
||||
_strtoul_r
|
||||
_strtoull_r
|
||||
_sungetc_r
|
||||
_svfiprintf_r
|
||||
_svfprintf_r
|
||||
_system_r
|
||||
_tempnam_r
|
||||
_times_r
|
||||
_timezone DATA
|
||||
_tls_map DATA
|
||||
_tmpfile_r
|
||||
_tmpnam_r
|
||||
_towctrans_r
|
||||
_tzname DATA
|
||||
_ungetc_r
|
||||
_user_strerror
|
||||
_vasniprintf_r
|
||||
_vasnprintf_r
|
||||
_vdiprintf_r
|
||||
_vdprintf_r
|
||||
_vfiprintf_r
|
||||
_vfiscanf_r
|
||||
_vfprintf_r
|
||||
_vfscanf_r
|
||||
_vscanf_r
|
||||
_vsnprintf_r
|
||||
_vsprintf_r
|
||||
_vsscanf_r
|
||||
_wcrtomb_r
|
||||
_wctomb_r
|
||||
_wctrans_r
|
||||
_wctype_r
|
||||
_write_r
|
||||
abort
|
||||
abs
|
||||
acos
|
||||
acosf
|
||||
acosh
|
||||
acoshf
|
||||
asctime
|
||||
asctime_r
|
||||
asin
|
||||
asinf
|
||||
asinh
|
||||
asinhf
|
||||
atan
|
||||
atan2
|
||||
atan2f
|
||||
atanf
|
||||
atanh
|
||||
atanhf
|
||||
atexit
|
||||
atof
|
||||
atoi
|
||||
atol
|
||||
bsearch
|
||||
calloc
|
||||
cbrt
|
||||
cbrtf
|
||||
ceil
|
||||
ceilf
|
||||
clearerr
|
||||
clock
|
||||
close
|
||||
copysign
|
||||
copysignf
|
||||
cos
|
||||
cosf
|
||||
cosh
|
||||
coshf
|
||||
create_file
|
||||
create_image
|
||||
create_thread
|
||||
ctime
|
||||
ctime_r
|
||||
debugwrite
|
||||
delete_file
|
||||
difftime
|
||||
diprintf
|
||||
div
|
||||
dprintf
|
||||
drem
|
||||
dremf
|
||||
entry DATA
|
||||
envz_get
|
||||
erf
|
||||
erfc
|
||||
erfcf
|
||||
erff
|
||||
exit
|
||||
exp
|
||||
exp10
|
||||
exp10f
|
||||
exp2
|
||||
exp2f
|
||||
expf
|
||||
expm1
|
||||
expm1f
|
||||
fabs
|
||||
fabsf
|
||||
fclose
|
||||
fdim
|
||||
fdimf
|
||||
fdopen
|
||||
fflush
|
||||
fgetc
|
||||
fgets
|
||||
fileno
|
||||
finite
|
||||
finitef
|
||||
fiprintf
|
||||
fiscanf
|
||||
floor
|
||||
floorf
|
||||
fma
|
||||
fmaf
|
||||
fmax
|
||||
fmaxf
|
||||
fmin
|
||||
fminf
|
||||
fmod
|
||||
fmodf
|
||||
fopen
|
||||
fprintf
|
||||
fputc
|
||||
fputs
|
||||
fputwc
|
||||
fread
|
||||
free
|
||||
freopen
|
||||
frexp
|
||||
frexpf
|
||||
fscanf
|
||||
fseek
|
||||
fseeko
|
||||
fstat
|
||||
ftell
|
||||
ftello
|
||||
fwrite
|
||||
gamma
|
||||
gamma_r
|
||||
gammaf
|
||||
gammaf_r
|
||||
get_entry_point
|
||||
get_fileinfo
|
||||
get_proc_address
|
||||
getenv
|
||||
gettimeofday
|
||||
gmtime
|
||||
gmtime_r
|
||||
hypot
|
||||
hypotf
|
||||
ilogb
|
||||
ilogbf
|
||||
infinity
|
||||
infinityf
|
||||
init_global_reent
|
||||
init_loader
|
||||
init_reent
|
||||
isalnum
|
||||
isalpha
|
||||
isascii
|
||||
isblank
|
||||
iscntrl
|
||||
isdigit
|
||||
isgraph
|
||||
isinf
|
||||
isinff
|
||||
islower
|
||||
isnan
|
||||
isnanf
|
||||
isprint
|
||||
ispunct
|
||||
isspace
|
||||
isupper
|
||||
iswalnum
|
||||
iswalpha
|
||||
iswblank
|
||||
iswcntrl
|
||||
iswctype
|
||||
iswdigit
|
||||
iswgraph
|
||||
iswlower
|
||||
iswprint
|
||||
iswpunct
|
||||
iswspace
|
||||
iswupper
|
||||
iswxdigit
|
||||
isxdigit
|
||||
j0
|
||||
j0f
|
||||
j1
|
||||
j1f
|
||||
jn
|
||||
jnf
|
||||
ldexp
|
||||
ldexpf
|
||||
lgamma
|
||||
lgamma_r
|
||||
lgammaf
|
||||
lgammaf_r
|
||||
libc_crt_startup
|
||||
link_app
|
||||
link_image
|
||||
llrint
|
||||
llrintf
|
||||
llrintl
|
||||
llround
|
||||
llroundf
|
||||
load_library
|
||||
loader_env DATA
|
||||
localeconv
|
||||
localtime
|
||||
localtime_r
|
||||
log
|
||||
log10
|
||||
log10f
|
||||
log1p
|
||||
log1pf
|
||||
log2
|
||||
log2f
|
||||
logb
|
||||
logbf
|
||||
logf
|
||||
longjmp
|
||||
lrint
|
||||
lrintf
|
||||
lrintl
|
||||
lround
|
||||
lroundf
|
||||
lseek
|
||||
malloc
|
||||
matherr
|
||||
mbrtowc
|
||||
mbtowc
|
||||
memalign
|
||||
memchr
|
||||
memcmp
|
||||
memcpy
|
||||
memmove
|
||||
memset
|
||||
mktime
|
||||
modf
|
||||
modff
|
||||
nan
|
||||
nanf
|
||||
nearbyint
|
||||
nearbyintf
|
||||
nextafter
|
||||
nextafterf
|
||||
open
|
||||
path_list DATA
|
||||
pow
|
||||
pow10
|
||||
pow10f
|
||||
powf
|
||||
printf
|
||||
putc
|
||||
putchar
|
||||
puts
|
||||
qsort
|
||||
raise
|
||||
rand
|
||||
rand_r
|
||||
read
|
||||
read_file
|
||||
realloc
|
||||
remainder
|
||||
remainderf
|
||||
remove
|
||||
remquo
|
||||
remquof
|
||||
rename
|
||||
rint
|
||||
rintf
|
||||
rintl
|
||||
round
|
||||
roundf
|
||||
scalb
|
||||
scalbf
|
||||
scalbln
|
||||
scalblnf
|
||||
scalbn
|
||||
scalbnf
|
||||
seed48
|
||||
set_file_size
|
||||
setjmp
|
||||
setlocale
|
||||
setvbuf
|
||||
signal
|
||||
significand
|
||||
significandf
|
||||
sin
|
||||
sincos
|
||||
sincosf
|
||||
sinf
|
||||
sinh
|
||||
sinhf
|
||||
siprintf
|
||||
sniprintf
|
||||
snprintf
|
||||
sprintf
|
||||
sqrt
|
||||
sqrtf
|
||||
srand
|
||||
srand48
|
||||
sscanf
|
||||
stpcpy
|
||||
stpncpy
|
||||
strcasecmp
|
||||
strcasestr
|
||||
strcat
|
||||
strchr
|
||||
strcmp
|
||||
strcoll
|
||||
strcpy
|
||||
strcspn
|
||||
strdup
|
||||
strerror
|
||||
strftime
|
||||
strlen
|
||||
strncasecmp
|
||||
strncat
|
||||
strncmp
|
||||
strncpy
|
||||
strndup
|
||||
strnlen
|
||||
strpbrk
|
||||
strrchr
|
||||
strsep
|
||||
strspn
|
||||
strstr
|
||||
strtod
|
||||
strtof
|
||||
strtok
|
||||
strtok_r
|
||||
strtol
|
||||
strtoll
|
||||
strtoul
|
||||
strtoull
|
||||
strupr
|
||||
system
|
||||
tan
|
||||
tanf
|
||||
tanh
|
||||
tanhf
|
||||
tempnam
|
||||
tgamma
|
||||
tgammaf
|
||||
time
|
||||
tls_alloc DATA
|
||||
tmpfile
|
||||
tmpnam
|
||||
toascii
|
||||
tolower
|
||||
toupper
|
||||
towctrans
|
||||
towlower
|
||||
towupper
|
||||
trunc
|
||||
truncf
|
||||
ungetc
|
||||
user_alloc
|
||||
validate_pe
|
||||
vasniprintf
|
||||
vasnprintf
|
||||
vdiprintf
|
||||
vdprintf
|
||||
vfiprintf
|
||||
vfiscanf
|
||||
vfprintf
|
||||
vfscanf
|
||||
vscanf
|
||||
vsnprintf
|
||||
vsprintf
|
||||
vsscanf
|
||||
wcrtomb
|
||||
wctrans
|
||||
wctype
|
||||
write
|
||||
write_file
|
||||
y0
|
||||
y0f
|
||||
y1
|
||||
y1f
|
||||
yn
|
||||
ynf
|
||||
alphasort
|
||||
opendir
|
||||
closedir
|
||||
readdir
|
||||
rewinddir
|
||||
seekdir
|
||||
telldir
|
||||
scandir
|
||||
mkdir
|
||||
rmdir
|
||||
chdir
|
||||
dirname
|
||||
getcwd
|
@ -1,509 +0,0 @@
|
||||
EXPORTS
|
||||
_Balloc @1
|
||||
_Bfree @2
|
||||
_Exit @3 DATA
|
||||
__assert @4
|
||||
__assert_func @5
|
||||
__ctype_ptr__ @6 DATA
|
||||
__emutls_get_address @7
|
||||
__errno @8
|
||||
__fpclassifyd @9
|
||||
__fpclassifyf @10
|
||||
__mutex_lock @11
|
||||
__signbitd @12
|
||||
__signbitf @13
|
||||
__srget_r @14
|
||||
__swbuf_r @15
|
||||
_atoi_r @16
|
||||
_atol_r @17
|
||||
_buf_findstr @18
|
||||
_calloc_r @19
|
||||
_cleanup @20
|
||||
_cleanup_r @21
|
||||
_close_r @22
|
||||
_ctype_ @23 DATA
|
||||
_daylight @24 DATA
|
||||
_diprintf_r @25
|
||||
_dprintf_r @26
|
||||
_dtoa_r @27
|
||||
_exit @28 DATA
|
||||
_f_atan2 @29 DATA
|
||||
_f_atan2f @30 DATA
|
||||
_f_exp @31
|
||||
_f_expf @32
|
||||
_f_frexp @33 DATA
|
||||
_f_frexpf @34 DATA
|
||||
_f_ldexp @35 DATA
|
||||
_f_ldexpf @36 DATA
|
||||
_f_llrint @37
|
||||
_f_llrintf @38
|
||||
_f_llrintl @39
|
||||
_f_log @40 DATA
|
||||
_f_log10 @41 DATA
|
||||
_f_log10f @42 DATA
|
||||
_f_logf @43 DATA
|
||||
_f_lrint @44
|
||||
_f_lrintf @45
|
||||
_f_lrintl @46
|
||||
_f_pow @47
|
||||
_f_powf @48
|
||||
_f_rint @49
|
||||
_f_rintf @50
|
||||
_f_rintl @51
|
||||
_f_tan @52 DATA
|
||||
_f_tanf @53 DATA
|
||||
_fclose_r @54
|
||||
_fdopen_r @55
|
||||
_fflush_r @56
|
||||
_fgetc_r @57
|
||||
_fgets_r @58
|
||||
_findenv @59
|
||||
_fiprintf_r @60
|
||||
_fiscanf_r @61
|
||||
_fopen_r @62
|
||||
_fprintf_r @63
|
||||
_fputc_r @64
|
||||
_fputs_r @65
|
||||
_fputwc_r @66
|
||||
_fread_r @67
|
||||
_free_r @68
|
||||
_freopen_r @69
|
||||
_fscanf_r @70
|
||||
_fseek_r @71
|
||||
_fseeko_r @72
|
||||
_fstat_r @73
|
||||
_ftell_r @74
|
||||
_ftello_r @75
|
||||
_fwalk @76
|
||||
_fwalk_reent @77
|
||||
_fwrite_r @78
|
||||
_gettimeofday @79
|
||||
_gettimeofday_r @80
|
||||
_global_impure_ptr @81 DATA
|
||||
_grow_handles @82
|
||||
_init_signal @83
|
||||
_init_signal_r @84
|
||||
_isatty @85
|
||||
_isatty_r @86
|
||||
_kill_r @87
|
||||
_localeconv_r @88
|
||||
_lseek_r @89
|
||||
_malloc_r @90
|
||||
_mbrtowc_r @91
|
||||
_mbtowc_r @92
|
||||
_mktm_r @93
|
||||
_mprec_log10 @94
|
||||
_open_r @95
|
||||
_printf_r @96
|
||||
_putc_r @97
|
||||
_putchar_r @98
|
||||
_puts_r @99
|
||||
_raise_r @100
|
||||
_read @101
|
||||
_read_r @102
|
||||
_realloc_r @103
|
||||
_remove_r @104
|
||||
_rename_r @105
|
||||
_seed48_r @106
|
||||
_setlocale_r @107
|
||||
_sfread_r @108
|
||||
_signal_r @109
|
||||
_siprintf_r @110
|
||||
_sniprintf_r @111
|
||||
_snprintf_r @112
|
||||
_sprintf_r @113
|
||||
_srand48_r @114
|
||||
_sscanf_r @115
|
||||
_strdup_r @116
|
||||
_strerror_r @117
|
||||
_strndup_r @118
|
||||
_strtod_r @119
|
||||
_strtol_r @120
|
||||
_strtoll_r @121
|
||||
_strtoul_r @122
|
||||
_strtoull_r @123
|
||||
_sungetc_r @124
|
||||
_svfiprintf_r @125
|
||||
_svfprintf_r @126
|
||||
_system_r @127
|
||||
_tempnam_r @128
|
||||
_times_r @129
|
||||
_timezone @130 DATA
|
||||
_tls_map @131 DATA
|
||||
_tmpfile_r @132
|
||||
_tmpnam_r @133
|
||||
_towctrans_r @134
|
||||
_tzname @135 DATA
|
||||
_ungetc_r @136
|
||||
_user_strerror @137
|
||||
_vasniprintf_r @138
|
||||
_vasnprintf_r @139
|
||||
_vdiprintf_r @140
|
||||
_vdprintf_r @141
|
||||
_vfiprintf_r @142
|
||||
_vfiscanf_r @143
|
||||
_vfprintf_r @144
|
||||
_vfscanf_r @145
|
||||
_vscanf_r @146
|
||||
_vsnprintf_r @147
|
||||
_vsprintf_r @148
|
||||
_vsscanf_r @149
|
||||
_wcrtomb_r @150
|
||||
_wctomb_r @151
|
||||
_wctrans_r @152
|
||||
_wctype_r @153
|
||||
_write_r @154
|
||||
abort @155
|
||||
abs @156
|
||||
acos @157
|
||||
acosf @158
|
||||
acosh @159
|
||||
acoshf @160
|
||||
asctime @161
|
||||
asctime_r @162
|
||||
asin @163
|
||||
asinf @164
|
||||
asinh @165
|
||||
asinhf @166
|
||||
atan @167
|
||||
atan2 @168
|
||||
atan2f @169
|
||||
atanf @170
|
||||
atanh @171
|
||||
atanhf @172
|
||||
atexit @173
|
||||
atof @174
|
||||
atoi @175
|
||||
atol @176
|
||||
bsearch @177
|
||||
calloc @178
|
||||
cbrt @179
|
||||
cbrtf @180
|
||||
ceil @181
|
||||
ceilf @182
|
||||
clearerr @183
|
||||
clock @184
|
||||
close @185
|
||||
copysign @186
|
||||
copysignf @187
|
||||
cos @188
|
||||
cosf @189
|
||||
cosh @190
|
||||
coshf @191
|
||||
create_file @192
|
||||
create_image @193
|
||||
create_thread @194
|
||||
ctime @195
|
||||
ctime_r @196
|
||||
debugwrite @197
|
||||
delete_file @198
|
||||
difftime @199
|
||||
diprintf @200
|
||||
div @201
|
||||
dprintf @202
|
||||
drem @203
|
||||
dremf @204
|
||||
entry @205 DATA
|
||||
envz_get @206
|
||||
erf @207
|
||||
erfc @208
|
||||
erfcf @209
|
||||
erff @210
|
||||
exit @211
|
||||
exp @212
|
||||
exp10 @213
|
||||
exp10f @214
|
||||
exp2 @215
|
||||
exp2f @216
|
||||
expf @217
|
||||
expm1 @218
|
||||
expm1f @219
|
||||
fabs @220
|
||||
fabsf @221
|
||||
fclose @222
|
||||
fdim @223
|
||||
fdimf @224
|
||||
fdopen @225
|
||||
fflush @226
|
||||
fgetc @227
|
||||
fgets @228
|
||||
fileno @229
|
||||
finite @230
|
||||
finitef @231
|
||||
fiprintf @232
|
||||
fiscanf @233
|
||||
floor @234
|
||||
floorf @235
|
||||
fma @236
|
||||
fmaf @237
|
||||
fmax @238
|
||||
fmaxf @239
|
||||
fmin @240
|
||||
fminf @241
|
||||
fmod @242
|
||||
fmodf @243
|
||||
fopen @244
|
||||
fprintf @245
|
||||
fputc @246
|
||||
fputs @247
|
||||
fputwc @248
|
||||
fread @249
|
||||
free @250
|
||||
freopen @251
|
||||
frexp @252
|
||||
frexpf @253
|
||||
fscanf @254
|
||||
fseek @255
|
||||
fseeko @256
|
||||
fstat @257
|
||||
ftell @258
|
||||
ftello @259
|
||||
fwrite @260
|
||||
gamma @261
|
||||
gamma_r @262
|
||||
gammaf @263
|
||||
gammaf_r @264
|
||||
get_entry_point @265
|
||||
get_fileinfo @266
|
||||
get_proc_address @267
|
||||
getenv @268
|
||||
gettimeofday @269
|
||||
gmtime @270
|
||||
gmtime_r @271
|
||||
hypot @272
|
||||
hypotf @273
|
||||
ilogb @274
|
||||
ilogbf @275
|
||||
infinity @276
|
||||
infinityf @277
|
||||
init_global_reent @278
|
||||
init_loader @279
|
||||
init_reent @280
|
||||
isalnum @281
|
||||
isalpha @282
|
||||
isascii @283
|
||||
isblank @284
|
||||
iscntrl @285
|
||||
isdigit @286
|
||||
isgraph @287
|
||||
isinf @288
|
||||
isinff @289
|
||||
islower @290
|
||||
isnan @291
|
||||
isnanf @292
|
||||
isprint @293
|
||||
ispunct @294
|
||||
isspace @295
|
||||
isupper @296
|
||||
iswalnum @297
|
||||
iswalpha @298
|
||||
iswblank @299
|
||||
iswcntrl @300
|
||||
iswctype @301
|
||||
iswdigit @302
|
||||
iswgraph @303
|
||||
iswlower @304
|
||||
iswprint @305
|
||||
iswpunct @306
|
||||
iswspace @307
|
||||
iswupper @308
|
||||
iswxdigit @309
|
||||
isxdigit @310
|
||||
j0 @311
|
||||
j0f @312
|
||||
j1 @313
|
||||
j1f @314
|
||||
jn @315
|
||||
jnf @316
|
||||
ldexp @317
|
||||
ldexpf @318
|
||||
lgamma @319
|
||||
lgamma_r @320
|
||||
lgammaf @321
|
||||
lgammaf_r @322
|
||||
libc_crt_startup @323
|
||||
link_app @324
|
||||
link_image @325
|
||||
llrint @326
|
||||
llrintf @327
|
||||
llrintl @328
|
||||
llround @329
|
||||
llroundf @330
|
||||
load_library @331
|
||||
loader_env @332 DATA
|
||||
localeconv @333
|
||||
localtime @334
|
||||
localtime_r @335
|
||||
log @336
|
||||
log10 @337
|
||||
log10f @338
|
||||
log1p @339
|
||||
log1pf @340
|
||||
log2 @341
|
||||
log2f @342
|
||||
logb @343
|
||||
logbf @344
|
||||
logf @345
|
||||
longjmp @346
|
||||
lrint @347
|
||||
lrintf @348
|
||||
lrintl @349
|
||||
lround @350
|
||||
lroundf @351
|
||||
lseek @352
|
||||
malloc @353
|
||||
matherr @354
|
||||
mbrtowc @355
|
||||
mbtowc @356
|
||||
memalign @357
|
||||
memchr @358
|
||||
memcmp @359
|
||||
memcpy @360
|
||||
memmove @361
|
||||
memset @362
|
||||
mktime @363
|
||||
modf @364
|
||||
modff @365
|
||||
nan @366
|
||||
nanf @367
|
||||
nearbyint @368
|
||||
nearbyintf @369
|
||||
nextafter @370
|
||||
nextafterf @371
|
||||
open @372
|
||||
path_list @373 DATA
|
||||
pow @374
|
||||
pow10 @375
|
||||
pow10f @376
|
||||
powf @377
|
||||
printf @378
|
||||
putc @379
|
||||
putchar @380
|
||||
puts @381
|
||||
qsort @382
|
||||
raise @383
|
||||
rand @384
|
||||
rand_r @385
|
||||
read @386
|
||||
read_file @387
|
||||
realloc @388
|
||||
remainder @389
|
||||
remainderf @390
|
||||
remove @391
|
||||
remquo @392
|
||||
remquof @393
|
||||
rename @394
|
||||
rint @395
|
||||
rintf @396
|
||||
rintl @397
|
||||
round @398
|
||||
roundf @399
|
||||
scalb @400
|
||||
scalbf @401
|
||||
scalbln @402
|
||||
scalblnf @403
|
||||
scalbn @404
|
||||
scalbnf @405
|
||||
seed48 @406
|
||||
set_file_size @407
|
||||
setjmp @408
|
||||
setlocale @409
|
||||
setvbuf @410
|
||||
signal @411
|
||||
significand @412
|
||||
significandf @413
|
||||
sin @414
|
||||
sincos @415
|
||||
sincosf @416
|
||||
sinf @417
|
||||
sinh @418
|
||||
sinhf @419
|
||||
siprintf @420
|
||||
sniprintf @421
|
||||
snprintf @422
|
||||
sprintf @423
|
||||
sqrt @424
|
||||
sqrtf @425
|
||||
srand @426
|
||||
srand48 @427
|
||||
sscanf @428
|
||||
stpcpy @429
|
||||
stpncpy @430
|
||||
strcasecmp @431
|
||||
strcasestr @432
|
||||
strcat @433
|
||||
strchr @434
|
||||
strcmp @435
|
||||
strcoll @436
|
||||
strcpy @437
|
||||
strcspn @438
|
||||
strdup @439
|
||||
strerror @440
|
||||
strftime @441
|
||||
strlen @442
|
||||
strncasecmp @443
|
||||
strncat @444
|
||||
strncmp @445
|
||||
strncpy @446
|
||||
strndup @447
|
||||
strnlen @448
|
||||
strpbrk @449
|
||||
strrchr @450
|
||||
strsep @451
|
||||
strspn @452
|
||||
strstr @453
|
||||
strtod @454
|
||||
strtof @455
|
||||
strtok @456
|
||||
strtok_r @457
|
||||
strtol @458
|
||||
strtoll @459
|
||||
strtoul @460
|
||||
strtoull @461
|
||||
strupr @462
|
||||
system @463
|
||||
tan @464
|
||||
tanf @465
|
||||
tanh @466
|
||||
tanhf @467
|
||||
tempnam @468
|
||||
tgamma @469
|
||||
tgammaf @470
|
||||
time @471
|
||||
tls_alloc @472 DATA
|
||||
tmpfile @473
|
||||
tmpnam @474
|
||||
toascii @475
|
||||
tolower @476
|
||||
toupper @477
|
||||
towctrans @478
|
||||
towlower @479
|
||||
towupper @480
|
||||
trunc @481
|
||||
truncf @482
|
||||
ungetc @483
|
||||
user_alloc @484
|
||||
validate_pe @485
|
||||
vasniprintf @486
|
||||
vasnprintf @487
|
||||
vdiprintf @488
|
||||
vdprintf @489
|
||||
vfiprintf @490
|
||||
vfiscanf @491
|
||||
vfprintf @492
|
||||
vfscanf @493
|
||||
vscanf @494
|
||||
vsnprintf @495
|
||||
vsprintf @496
|
||||
vsscanf @497
|
||||
wcrtomb @498
|
||||
wctrans @499
|
||||
wctype @500
|
||||
write @501
|
||||
write_file @502
|
||||
y0 @503
|
||||
y0f @504
|
||||
y1 @505
|
||||
y1f @506
|
||||
yn @507
|
||||
ynf @508
|
@ -355,7 +355,6 @@ import libc,\
|
||||
_cosf,'cosf',\
|
||||
_cosh,'cosh',\
|
||||
_coshf,'coshf',\
|
||||
_create_file,'create_file',\
|
||||
_create_image,'create_image',\
|
||||
_create_thread,'create_thread',\
|
||||
_ctime,'ctime',\
|
||||
@ -429,7 +428,6 @@ import libc,\
|
||||
_gammaf,'gammaf',\
|
||||
_gammaf_r,'gammaf_r',\
|
||||
_get_entry_point,'get_entry_point',\
|
||||
_get_fileinfo,'get_fileinfo',\
|
||||
_get_proc_address,'get_proc_address',\
|
||||
_getenv,'getenv',\
|
||||
_gettimeofday,'gettimeofday',\
|
||||
@ -550,7 +548,6 @@ import libc,\
|
||||
_rand,'rand',\
|
||||
_rand_r,'rand_r',\
|
||||
_read,'read',\
|
||||
_read_file,'read_file',\
|
||||
_realloc,'realloc',\
|
||||
_remainder,'remainder',\
|
||||
_remainderf,'remainderf',\
|
||||
@ -570,7 +567,6 @@ import libc,\
|
||||
_scalbn,'scalbn',\
|
||||
_scalbnf,'scalbnf',\
|
||||
_seed48,'seed48',\
|
||||
_set_file_size,'set_file_size',\
|
||||
_setjmp,'setjmp',\
|
||||
_setlocale,'setlocale',\
|
||||
_setvbuf,'setvbuf',\
|
||||
@ -665,7 +661,6 @@ import libc,\
|
||||
_wctrans,'wctrans',\
|
||||
_wctype,'wctype',\
|
||||
_write,'write',\
|
||||
_write_file,'write_file',\
|
||||
_y0,'y0',\
|
||||
_y0f,'y0f',\
|
||||
_y1,'y1',\
|
||||
|
11
contrib/sdk/sources/newlib/libc/sys/chdir.c
Normal file
11
contrib/sdk/sources/newlib/libc/sys/chdir.c
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) KolibriOS team 2004-2024. All rights reserved.
|
||||
* Distributed under terms of the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/ksys.h>
|
||||
|
||||
int chdir(char* dir){
|
||||
_ksys_setcwd(dir);
|
||||
return 0;
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
#include "glue.h"
|
||||
#include "io.h"
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) KolibriOS team 2004-2024. All rights reserved.
|
||||
* Distributed under terms of the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <_ansi.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/unistd.h>
|
||||
@ -16,28 +21,8 @@ static int console_read(const char *path, void *buff,
|
||||
size_t offset, size_t count, size_t *done)
|
||||
{
|
||||
char *p = buff;
|
||||
/*int cnt = 0;
|
||||
short c;
|
||||
char ch;*/
|
||||
con_gets(p, count+1);
|
||||
*done = strlen(p);
|
||||
|
||||
// __asm__ volatile("int3");
|
||||
/*
|
||||
do
|
||||
{
|
||||
c = con_getch2();
|
||||
printf("%d\n",(char)c);
|
||||
ch = (char)c;
|
||||
if(ch != 0)
|
||||
{
|
||||
p[cnt] = ch != 0x0D ? ch : 0x0A;
|
||||
con_write_string(p+cnt, 1);
|
||||
cnt++;
|
||||
}
|
||||
}while(ch != 0x0D);
|
||||
*done = cnt;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -48,7 +33,7 @@ static int console_write(const char *path, const void *buff,
|
||||
|
||||
*writes = count;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
void __init_conio()
|
||||
{
|
||||
|
@ -1,25 +0,0 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kos_io.h>
|
||||
|
||||
int create_file(const char *path)
|
||||
{
|
||||
int retval;
|
||||
__asm__ __volatile__ (
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %1, 1(%%esp) \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $2 \n\t"
|
||||
"movl %%esp, %%ebx \n\t"
|
||||
"movl $70, %%eax \n\t"
|
||||
"int $0x40 \n\t"
|
||||
"addl $28, %%esp \n\t"
|
||||
:"=a" (retval)
|
||||
:"r" (path)
|
||||
:"ebx");
|
||||
return retval;
|
||||
};
|
@ -1,48 +0,0 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kos_io.h>
|
||||
|
||||
int get_fileinfo(const char *path, fileinfo_t *info)
|
||||
{
|
||||
int retval;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %1, 1(%%esp) \n\t"
|
||||
"pushl %%ebx \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $5 \n\t"
|
||||
"movl %%esp, %%ebx \n\t"
|
||||
"movl $70, %%eax \n\t"
|
||||
"int $0x40 \n\t"
|
||||
"addl $28, %%esp \n\t"
|
||||
:"=a" (retval)
|
||||
:"r" (path), "b" (info));
|
||||
return retval;
|
||||
};
|
||||
|
||||
|
||||
int set_fileinfo(const char *path, fileinfo_t *info)
|
||||
{
|
||||
int retval;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %1, 1(%%esp) \n\t"
|
||||
"pushl %%ebx \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $6 \n\t"
|
||||
"movl %%esp, %%ebx \n\t"
|
||||
"movl $70, %%eax \n\t"
|
||||
"int $0x40 \n\t"
|
||||
"addl $28, %%esp \n\t"
|
||||
:"=a" (retval)
|
||||
:"r" (path), "b" (info));
|
||||
return retval;
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kos_io.h>
|
||||
|
||||
|
||||
int set_file_size(const char *path, unsigned size)
|
||||
{
|
||||
int retval;
|
||||
__asm__ __volatile__(
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %%eax, 1(%%esp) \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl %%ebx \n\t"
|
||||
"push $4 \n\t"
|
||||
"movl %%esp, %%ebx \n\t"
|
||||
"movl $70, %%eax \n\t"
|
||||
"int $0x40 \n\t"
|
||||
"addl $28, %%esp \n\t"
|
||||
:"=a" (retval)
|
||||
:"a" (path), "b" (size));
|
||||
return retval;
|
||||
};
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
#include <sys/stat.h>
|
||||
#include "glue.h"
|
||||
#include "io.h"
|
||||
@ -25,7 +25,7 @@ _DEFUN (fstat, (fd, buf),
|
||||
int fd _AND
|
||||
struct stat *buf)
|
||||
{
|
||||
fileinfo_t info;
|
||||
ksys_file_info_t info;
|
||||
struct tm time;
|
||||
|
||||
__io_handle *ioh;
|
||||
@ -33,8 +33,8 @@ _DEFUN (fstat, (fd, buf),
|
||||
if( (fd < 0) || (fd >=64) )
|
||||
{
|
||||
errno = EBADF;
|
||||
return (-1);
|
||||
};
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (buf, 0, sizeof (* buf));
|
||||
|
||||
@ -47,7 +47,7 @@ _DEFUN (fstat, (fd, buf),
|
||||
{
|
||||
|
||||
ioh = &__io_tab[fd];
|
||||
get_fileinfo(ioh->name, &info);
|
||||
_ksys_file_info(ioh->name, &info);
|
||||
|
||||
if (info.attr & 0x10)
|
||||
buf->st_mode = S_IFDIR;
|
||||
|
17
contrib/sdk/sources/newlib/libc/sys/getcwd.c
Normal file
17
contrib/sdk/sources/newlib/libc/sys/getcwd.c
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) KolibriOS team 2004-2024. All rights reserved.
|
||||
* Distributed under terms of the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
char *getcwd(char *buf, unsigned size){
|
||||
if(!buf){
|
||||
if((buf = malloc(size))==NULL){
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
_ksys_getcwd(buf, size);
|
||||
return(buf);
|
||||
}
|
@ -1,31 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) KolibriOS team 2004-2024. All rights reserved.
|
||||
* Distributed under terms of the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
int read_file(const char *path, void *buff,
|
||||
size_t offset, size_t count, size_t *reads)
|
||||
{
|
||||
int retval;
|
||||
int d0;
|
||||
__asm__ __volatile__(
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %%eax, 1(%%esp) \n\t"
|
||||
"pushl %%ebx \n\t"
|
||||
"pushl %%edx \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl %%ecx \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %%esp, %%ebx \n\t"
|
||||
"mov $70, %%eax \n\t"
|
||||
"int $0x40 \n\t"
|
||||
"testl %%esi, %%esi \n\t"
|
||||
"jz 1f \n\t"
|
||||
"movl %%ebx, (%%esi) \n\t"
|
||||
"1:"
|
||||
"addl $28, %%esp \n\t"
|
||||
:"=a" (retval)
|
||||
:"a"(path),"b"(buff),"c"(offset),"d"(count),"S"(reads));
|
||||
return retval == 6 ? 0 : retval;
|
||||
};
|
||||
|
||||
ksys_file_status_t st = _ksys_file_read(path, offset, count, buff);
|
||||
*reads = st.rw_bytes;
|
||||
return st.status == KSYS_FS_ERR_EOF ? 0 : st.status;
|
||||
}
|
||||
|
@ -1,33 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) KolibriOS team 2004-2024. All rights reserved.
|
||||
* Distributed under terms of the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
int write_file(const char *path,const void *buff,
|
||||
int write_file(const char *path, const void *buff,
|
||||
size_t offset, size_t count, size_t *writes)
|
||||
{
|
||||
int retval;
|
||||
__asm__ __volatile__(
|
||||
"pushl $0 \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"movl %%eax, 1(%%esp) \n\t"
|
||||
"pushl %%ebx \n\t"
|
||||
"pushl %%edx \n\t"
|
||||
"pushl $0 \n\t"
|
||||
"pushl %%ecx \n\t"
|
||||
"pushl $3 \n\t"
|
||||
"movl %%esp, %%ebx \n\t"
|
||||
"mov $70, %%eax \n\t"
|
||||
"int $0x40 \n\t"
|
||||
"testl %%esi, %%esi \n\t"
|
||||
"jz 1f \n\t"
|
||||
"movl %%ebx, (%%esi) \n\t"
|
||||
"1:"
|
||||
"addl $28, %%esp \n\t"
|
||||
:"=a" (retval)
|
||||
:"a"(path),"b"(buff),"c"(offset),"d"(count),"S"(writes));
|
||||
if(retval == 0)
|
||||
ksys_file_status_t st = _ksys_file_write(path, offset, count, buff);
|
||||
*writes = st.rw_bytes;
|
||||
if(!st.status)
|
||||
return 0;
|
||||
else if (retval == 8)
|
||||
else if (st.status == KSYS_FS_ERR_8)
|
||||
return ENOSPC;
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
|
@ -1,28 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) KolibriOS team 2004-2024. All rights reserved.
|
||||
* Distributed under terms of the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
#include "glue.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
_off_t
|
||||
_DEFUN (lseek, (fd, pos, whence),
|
||||
int fd _AND
|
||||
_off_t pos _AND
|
||||
int whence)
|
||||
|
||||
{
|
||||
fileinfo_t info;
|
||||
ksys_file_info_t info;
|
||||
__io_handle *ioh;
|
||||
_off_t ret;
|
||||
|
||||
if( (fd < 0) || (fd >=64) )
|
||||
if ((fd < 0) || (fd >=64))
|
||||
{
|
||||
errno = EBADF;
|
||||
return (-1);
|
||||
};
|
||||
}
|
||||
|
||||
ioh = &__io_tab[fd];
|
||||
|
||||
@ -36,16 +38,16 @@ _DEFUN (lseek, (fd, pos, whence),
|
||||
break;
|
||||
case SEEK_END:
|
||||
{
|
||||
get_fileinfo(ioh->name, &info);
|
||||
_ksys_file_info(ioh->name, &info);
|
||||
ret = pos + info.size;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
};
|
||||
return -1;
|
||||
}
|
||||
|
||||
ioh->offset = ret;
|
||||
|
||||
return( ret );
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
@ -15,13 +15,20 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
#include "glue.h"
|
||||
#include "io.h"
|
||||
|
||||
#undef erro
|
||||
#undef errno
|
||||
extern int errno;
|
||||
|
||||
extern int write_file(const char *path,const void *buff,
|
||||
size_t offset, size_t count, size_t *writes);
|
||||
|
||||
extern int read_file(const char *path, void *buff,
|
||||
size_t offset, size_t count, size_t *reads);
|
||||
|
||||
static inline int is_slash(char c)
|
||||
{
|
||||
return c=='/' || c=='\\';
|
||||
@ -49,7 +56,7 @@ void fix_slashes(char * in,char * out)
|
||||
}
|
||||
}
|
||||
*out='\0';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void buildpath(char *buf, const char* file)
|
||||
@ -89,26 +96,14 @@ __do_until_slash:
|
||||
*ptr++ = *file++;
|
||||
}
|
||||
*ptr = 0;
|
||||
};
|
||||
|
||||
static char *getccwd(char *buf, size_t size)
|
||||
{
|
||||
int bsize;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(bsize)
|
||||
:"a"(30),"b"(2),"c"(buf), "d"(size)
|
||||
:"memory");
|
||||
|
||||
return buf;
|
||||
};
|
||||
}
|
||||
|
||||
int open (const char * filename, int flags, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
__io_handle *ioh;
|
||||
fileinfo_t info;
|
||||
ksys_file_info_t info;
|
||||
int iomode, rwmode, offset;
|
||||
int hid;
|
||||
int err;
|
||||
@ -127,28 +122,28 @@ int open (const char * filename, int flags, ...)
|
||||
}
|
||||
else
|
||||
{
|
||||
getccwd(buf, 1024);
|
||||
_ksys_getcwd(buf, 1024);
|
||||
buildpath(buf, filename);
|
||||
}
|
||||
|
||||
err = get_fileinfo(buf, &info);
|
||||
err = _ksys_file_info(buf, &info);
|
||||
|
||||
if( flags & O_EXCL &&
|
||||
if (flags & O_EXCL &&
|
||||
flags & O_CREAT )
|
||||
{
|
||||
if( !err )
|
||||
if (!err)
|
||||
{
|
||||
errno = EEXIST;
|
||||
__io_free(hid);
|
||||
return (-1);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if( err )
|
||||
if (err)
|
||||
{
|
||||
if(flags & O_CREAT)
|
||||
err=create_file(buf);
|
||||
if( err )
|
||||
err = _ksys_file_create(buf).status;
|
||||
if(err)
|
||||
{
|
||||
errno = EACCES;
|
||||
__io_free(hid);
|
||||
@ -156,8 +151,8 @@ int open (const char * filename, int flags, ...)
|
||||
};
|
||||
};
|
||||
|
||||
if( flags & O_TRUNC )
|
||||
set_file_size(buf, 0);
|
||||
if (flags & O_TRUNC)
|
||||
_ksys_file_set_size(buf, 0);
|
||||
|
||||
ioh = &__io_tab[hid];
|
||||
|
||||
@ -166,25 +161,28 @@ int open (const char * filename, int flags, ...)
|
||||
iomode = 0;
|
||||
offset = 0;
|
||||
|
||||
if( rwmode == O_RDWR )
|
||||
if (rwmode == O_RDWR)
|
||||
iomode |= _READ | _WRITE;
|
||||
else if( rwmode == O_RDONLY)
|
||||
else if (rwmode == O_RDONLY)
|
||||
iomode |= _READ;
|
||||
else if( rwmode == O_WRONLY)
|
||||
else if (rwmode == O_WRONLY)
|
||||
iomode |= _WRITE;
|
||||
|
||||
if( flags & O_APPEND )
|
||||
if (flags & O_APPEND)
|
||||
{
|
||||
iomode |= _APPEND;
|
||||
offset = info.size;
|
||||
};
|
||||
}
|
||||
|
||||
if( flags & (O_BINARY|O_TEXT) )
|
||||
if (flags & (O_BINARY|O_TEXT))
|
||||
{
|
||||
if( flags & O_BINARY )
|
||||
if (flags & O_BINARY)
|
||||
iomode |= _BINARY;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
iomode |= _BINARY;
|
||||
}
|
||||
|
||||
ioh->name = strdup(buf);
|
||||
ioh->offset = offset;
|
||||
@ -193,6 +191,4 @@ int open (const char * filename, int flags, ...)
|
||||
ioh->write = write_file;
|
||||
|
||||
return hid;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ ssize_t read(int fd, void *buf, size_t cnt)
|
||||
char *buffer = buf;
|
||||
int rc;
|
||||
int h;
|
||||
unsigned amount_read;
|
||||
size_t amount_read;
|
||||
int err;
|
||||
|
||||
__io_handle *ioh;
|
||||
|
@ -13,7 +13,7 @@
|
||||
* they apply.
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include <sys/ksys.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
@ -28,16 +28,16 @@ _DEFUN (stat, (path, buf),
|
||||
struct stat *buf)
|
||||
{
|
||||
|
||||
fileinfo_t info;
|
||||
ksys_file_info_t info;
|
||||
struct tm time;
|
||||
|
||||
if( get_fileinfo(path, &info))
|
||||
if (_ksys_file_info(path, &info))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
};
|
||||
}
|
||||
|
||||
memset (buf, 0, sizeof (* buf));
|
||||
memset(buf, 0, sizeof (*buf));
|
||||
|
||||
buf->st_size = info.size;
|
||||
|
||||
@ -91,4 +91,3 @@ _DEFUN (lstat, (path, buf),
|
||||
{
|
||||
return stat(path, buf);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <alloca.h>
|
||||
#include <sys/kos_io.h>
|
||||
#include "io.h"
|
||||
|
||||
#undef erro
|
||||
|
@ -7,7 +7,7 @@ STRIP = kos32-strip
|
||||
|
||||
INSTALLDIR ?= /home/autobuild/tools/win32/lib
|
||||
|
||||
CFLAGS = -U__MINGW32__ -UWIN32 -UWindows -U_WINDOWS -U_WIN32 -U__WIN32__ -U_WIN32 -DPACKAGE_NAME=\"sqlite\" -DPACKAGE_TARNAME=\"sqlite\" -DPACKAGE_VERSION=\"3.36.0\" -DPACKAGE_STRING=\"sqlite\ 3.36.0\" -DPACKAGE_BUGREPORT=\"http://www.sqlite.org\" -DPACKAGE_URL=\"\" -DPACKAGE=\"sqlite\" -DVERSION=\"3.36.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=0 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_FDATASYNC=0 -DHAVE_USLEEP=0 -DHAVE_LOCALTIME_R=1 -DHAVE_GMTIME_R=1 -DHAVE_DECL_STRERROR_R=1 -DHAVE_STRERROR_R=1 -DHAVE_EDITLINE_READLINE_H=1 -DHAVE_EDITLINE=1 -DHAVE_ZLIB_H=1 -I. -D_REENTRANT=1 -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY -DSQLITE_HAVE_ZLIB=1 -DSQLITE_OS_OTHER=1 -USQLITE_OS_WIN_H -DSQLITE_TEMP_STORE=3 -D_NO_STDERR -c -O2 -fomit-frame-pointer -D_KOLIBRI
|
||||
CFLAGS = -U__MINGW32__ -UWIN32 -UWindows -U_WINDOWS -U_WIN32 -U__WIN32__ -U_WIN32 -DPACKAGE_NAME=\"sqlite\" -DPACKAGE_TARNAME=\"sqlite\" -DPACKAGE_VERSION=\"3.36.0\" -DPACKAGE_STRING=\"sqlite\ 3.36.0\" -DPACKAGE_BUGREPORT=\"http://www.sqlite.org\" -DPACKAGE_URL=\"\" -DPACKAGE=\"sqlite\" -DVERSION=\"3.36.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=0 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_FDATASYNC=0 -DHAVE_USLEEP=0 -DHAVE_LOCALTIME_R=1 -DHAVE_GMTIME_R=1 -DHAVE_DECL_STRERROR_R=1 -DHAVE_STRERROR_R=1 -DHAVE_EDITLINE_READLINE_H=1 -DHAVE_EDITLINE=1 -DHAVE_ZLIB_H=1 -I. -D_REENTRANT=1 -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY -DSQLITE_HAVE_ZLIB=1 -DSQLITE_OS_OTHER=1 -USQLITE_OS_WIN_H -DSQLITE_TEMP_STORE=3 -D_NO_STDERR -DSQLITE_OMIT_VIRTUALTABLE -c -O2 -fomit-frame-pointer -D_KOLIBRI
|
||||
|
||||
LDFLAGS=$(LDFLAGS_CMD)
|
||||
LDFLAGS+= -shared -s -T dll.lds --entry _DllStartup --image-base=0
|
||||
|
@ -8,7 +8,7 @@ tup.include(HELPERDIR .. "/use_newlib.lua")
|
||||
|
||||
INCLUDES= INCLUDES .. " -I .. "
|
||||
|
||||
CFLAGS = CFLAGS .. " -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -DSQLITE_OS_OTHER=1 -DHAVE_UNISTD_H=0 -D_NO_STDERR -DSQLITE_OMIT_POPEN -DSQLITE_THREADSAFE=0 -D_KOLIBRI -U__linux__ -DPACKAGE_NAME=\"sqlite\" -DPACKAGE_TARNAME=\"sqlite\" -DPACKAGE_VERSION=\"3.36.0\" -DPACKAGE_STRING=\"sqlite-3.36.0\" -DPACKAGE=\"sqlite\" -DVERSION=\"3.36.0\""
|
||||
CFLAGS = CFLAGS .. " -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -DSQLITE_OS_OTHER=1 -DHAVE_UNISTD_H=0 -D_NO_STDERR -DSQLITE_OMIT_POPEN -DSQLITE_THREADSAFE=0 -D_KOLIBRI -DSQLITE_OMIT_VIRTUALTABLE -U__linux__ -DPACKAGE_NAME=\"sqlite\" -DPACKAGE_TARNAME=\"sqlite\" -DPACKAGE_VERSION=\"3.36.0\" -DPACKAGE_STRING=\"sqlite-3.36.0\" -DPACKAGE=\"sqlite\" -DVERSION=\"3.36.0\""
|
||||
|
||||
LDFLAGS = LDFLAGS .. " --subsystem console "
|
||||
|
||||
|
@ -102,7 +102,7 @@ typedef unsigned char u8;
|
||||
# include <pwd.h>
|
||||
# endif
|
||||
#endif
|
||||
#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
|
||||
#if (!defined(_WIN32) && !defined(WIN32) && !defined (_KOLIBRI)) || defined(__MINGW32__)
|
||||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
# define GETPID getpid
|
||||
@ -2209,7 +2209,9 @@ SQLITE_EXTENSION_INIT1
|
||||
#include <fcntl.h>
|
||||
#if !defined(_WIN32) && !defined(WIN32)
|
||||
# include <unistd.h>
|
||||
#ifndef _KOLIBRI
|
||||
# include <dirent.h>
|
||||
#endif
|
||||
# include <utime.h>
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
|
@ -1,188 +0,0 @@
|
||||
#ifndef __cplusplus
|
||||
|
||||
//"inline" ôóíêöèè äëÿ âûçîâà ñèñòåìíûõ ôóíêöèé Kolibri â C - â èìåíè ôóíêöèè êîë-âî ïàðàìåòðîâ
|
||||
//SysCall# (íîìåð_ñèñòåìíîé_ôóíêöèè, ïàðàìåòðû,...)
|
||||
|
||||
static inline int SysCall1 (int EAX__) __attribute__((always_inline));
|
||||
static inline int SysCall2 (int EAX__, int EBX__) __attribute__((always_inline));
|
||||
static inline int SysCall3 (int EAX__, int EBX__, int ECX__) __attribute__((always_inline));
|
||||
static inline int SysCall4 (int EAX__, int EBX__, int ECX__, int EDX__) __attribute__((always_inline));
|
||||
static inline int SysCall5 (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__) __attribute__((always_inline));
|
||||
static inline int SysCall6 (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__, int EDI__) __attribute__((always_inline));
|
||||
|
||||
|
||||
static inline int SysCall1 (int EAX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall2 (int EAX__, int EBX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall3 (int EAX__, int EBX__, int ECX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall4 (int EAX__, int EBX__, int ECX__, int EDX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile(""::"d"(EDX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall5 (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile(""::"d"(EDX__));
|
||||
asm volatile(""::"S"(ESI__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall6 (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__, int EDI__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile(""::"d"(EDX__));
|
||||
asm volatile(""::"S"(ESI__));
|
||||
asm volatile(""::"D"(EDI__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//"inline" ôóíêöèè äëÿ âûçîâà ñèñòåìíûõ ôóíêöèé Kolibri â C++
|
||||
//SysCall(íîìåð_ñèñòåìíîé_ôóíêöèè, ïàðàìåòðû,...)
|
||||
|
||||
static inline int SysCall (int EAX__) __attribute__((always_inline));
|
||||
static inline int SysCall (int EAX__, int EBX__) __attribute__((always_inline));
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__) __attribute__((always_inline));
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__, int EDX__) __attribute__((always_inline));
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__) __attribute__((always_inline));
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__, int EDI__) __attribute__((always_inline));
|
||||
|
||||
|
||||
|
||||
static inline int SysCall (int EAX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall (int EAX__, int EBX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__, int EDX__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile(""::"d"(EDX__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile(""::"d"(EDX__));
|
||||
asm volatile(""::"S"(ESI__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline int SysCall (int EAX__, int EBX__, int ECX__, int EDX__, int ESI__, int EDI__)
|
||||
{
|
||||
asm volatile(""::"a"(EAX__));
|
||||
asm volatile(""::"b"(EBX__));
|
||||
asm volatile(""::"c"(ECX__));
|
||||
asm volatile(""::"d"(EDX__));
|
||||
asm volatile(""::"S"(ESI__));
|
||||
asm volatile(""::"D"(EDI__));
|
||||
asm volatile("int $0x40");
|
||||
|
||||
register int res;
|
||||
asm volatile("":"=a"(res):);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
if tup.getconfig("NO_GCC") ~= "" then return end
|
||||
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../.." or tup.getconfig("HELPERDIR")
|
||||
tup.include(HELPERDIR .. "/use_gcc.lua")
|
||||
tup.include(HELPERDIR .. "/use_newlib.lua")
|
||||
tup.include(HELPERDIR .. "/use_tinygl.lua")
|
||||
|
||||
LIBS = "-lstdc++ -lsupc++ " .. LIBS
|
||||
LDFLAGS = LDFLAGS .. " --subsystem native"
|
||||
|
||||
compile_gcc{"fps.cpp", "main.cpp"}
|
||||
link_gcc("gears")
|
@ -1,46 +0,0 @@
|
||||
#include "SysCall.h"
|
||||
|
||||
/*******************************************************************************
|
||||
ФУНКЦИЯ ОПРЕДЕЛЕНИЯ FPS
|
||||
x,y - координаты вывода FPS на окно
|
||||
возвращает время в сотых долях секунды затрачиваемое на 1 цикл
|
||||
|
||||
*/
|
||||
|
||||
int time1=0;
|
||||
int time2=0;
|
||||
int fps1=0;
|
||||
int timerend=0;
|
||||
|
||||
int Fps (long x, long y)//функция определения FPS
|
||||
{
|
||||
int tr;
|
||||
|
||||
time1 = SysCall(26,9);//определяем время прошедшее момента запуска системы
|
||||
|
||||
if (timerend==0)
|
||||
{
|
||||
time2=time1;
|
||||
timerend=time1;
|
||||
}
|
||||
|
||||
tr = time1 - timerend;
|
||||
|
||||
if ((time1 - time2) < 100)//если прошло менее 1 секунды
|
||||
{ //увеличиваем счетчик fps
|
||||
fps1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//выводим число fps
|
||||
SysCall(13,(x<<16)+23,(y<<16)+7,0x00555555); //НАРИСОВАТЬ ПОЛОСУ
|
||||
SysCall(47,4<<16,fps1,(x<<16)+y,0xfafafa);//ВЫВЕСТИ В ОКНО ПРИЛОЖЕНИЯ ЧИСЛО
|
||||
fps1=0;
|
||||
time2=time1;
|
||||
}
|
||||
|
||||
timerend=time1;
|
||||
|
||||
return tr;
|
||||
}
|
||||
//******************************************************************************
|
@ -1,351 +0,0 @@
|
||||
/*
|
||||
Ïðèìåð âçÿò èç íàáîðà ïðèìåðîâ áèáëèîòåêè Mesa
|
||||
|
||||
iadn
|
||||
http://www.iadn.narod.ru
|
||||
iadn@bk.ru
|
||||
*/
|
||||
|
||||
/*
|
||||
* 3-D gear wheels. This program is in the public domain.
|
||||
*
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
/*
|
||||
* Newlib port by maxcodehack
|
||||
*/
|
||||
|
||||
#include <kos32sys.h>
|
||||
#include <kosgl.h> // TinyGL
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "SysCall.h"
|
||||
|
||||
int Fps (long x, long y);
|
||||
|
||||
struct {
|
||||
int x,y;
|
||||
int dx,dy;
|
||||
} win;
|
||||
|
||||
#define KEY_ESC 1
|
||||
#define KEY_F 33
|
||||
|
||||
char *title = "Gears (F - full screen, ESC - exit)";
|
||||
char *fps = "FPS:";
|
||||
|
||||
unsigned char FullScreen = 0;
|
||||
unsigned char skin = 0x34;
|
||||
|
||||
oskey_t key;
|
||||
|
||||
proc_info* pri;
|
||||
KOSGLContext cgl;
|
||||
|
||||
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
|
||||
static GLint gear1, gear2, gear3;
|
||||
static GLfloat angle = 0.0;
|
||||
|
||||
static GLuint limit;
|
||||
static GLuint count = 1;
|
||||
|
||||
/*
|
||||
* Draw a gear wheel. You'll probably want to call this function when
|
||||
* building a display list since we do a lot of trig here.
|
||||
*
|
||||
* Input: inner_radius - radius of hole at center
|
||||
* outer_radius - radius at center of teeth
|
||||
* width - width of gear
|
||||
* teeth - number of teeth
|
||||
* tooth_depth - depth of tooth
|
||||
*/
|
||||
static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
|
||||
GLint teeth, GLfloat tooth_depth )
|
||||
{
|
||||
GLint i;
|
||||
GLfloat r0, r1, r2;
|
||||
GLfloat angle, da;
|
||||
GLfloat u, v, len;
|
||||
|
||||
r0 = inner_radius;
|
||||
r1 = outer_radius - tooth_depth/2.0;
|
||||
r2 = outer_radius + tooth_depth/2.0;
|
||||
|
||||
da = 2.0*M_PI / teeth / 4.0;
|
||||
|
||||
glShadeModel( GL_FLAT );
|
||||
|
||||
glNormal3f( 0.0, 0.0, 1.0 );
|
||||
|
||||
/* draw front face */
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = i * 2.0*M_PI / teeth;
|
||||
glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
|
||||
glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
|
||||
glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
|
||||
glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw front sides of teeth */
|
||||
glBegin( GL_QUADS );
|
||||
da = 2.0*M_PI / teeth / 4.0;
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = i * 2.0*M_PI / teeth;
|
||||
|
||||
glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
|
||||
glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
|
||||
glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
|
||||
glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glNormal3f( 0.0, 0.0, -1.0 );
|
||||
|
||||
/* draw back face */
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = i * 2.0*M_PI / teeth;
|
||||
glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
|
||||
glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
|
||||
glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
|
||||
glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw back sides of teeth */
|
||||
glBegin( GL_QUADS );
|
||||
da = 2.0*M_PI / teeth / 4.0;
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = i * 2.0*M_PI / teeth;
|
||||
|
||||
glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
|
||||
glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
|
||||
glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
|
||||
glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw outward faces of teeth */
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = i * 2.0*M_PI / teeth;
|
||||
|
||||
glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
|
||||
glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
|
||||
u = r2*cos(angle+da) - r1*cos(angle);
|
||||
v = r2*sin(angle+da) - r1*sin(angle);
|
||||
len = sqrt( u*u + v*v );
|
||||
u /= len;
|
||||
v /= len;
|
||||
glNormal3f( v, -u, 0.0 );
|
||||
glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
|
||||
glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
|
||||
glNormal3f( cos(angle), sin(angle), 0.0 );
|
||||
glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
|
||||
glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
|
||||
u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
|
||||
v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
|
||||
glNormal3f( v, -u, 0.0 );
|
||||
glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
|
||||
glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
|
||||
glNormal3f( cos(angle), sin(angle), 0.0 );
|
||||
}
|
||||
|
||||
glVertex3f( r1*cos(0.0), r1*sin(0.0), width*0.5 );
|
||||
glVertex3f( r1*cos(0.0), r1*sin(0.0), -width*0.5 );
|
||||
|
||||
glEnd();
|
||||
|
||||
glShadeModel( GL_SMOOTH );
|
||||
|
||||
/* draw inside radius cylinder */
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = i * 2.0*M_PI / teeth;
|
||||
glNormal3f( -cos(angle), -sin(angle), 0.0 );
|
||||
glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
|
||||
glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0 };
|
||||
static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0 };
|
||||
static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0 };
|
||||
static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0 };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, pos );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
|
||||
/* make the gears */
|
||||
gear1 = glGenLists(1);
|
||||
glNewList(gear1, GL_COMPILE);
|
||||
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red );
|
||||
gear( 1.0, 4.0, 1.0, 20, 0.7 );
|
||||
glEndList();
|
||||
|
||||
gear2 = glGenLists(1);
|
||||
glNewList(gear2, GL_COMPILE);
|
||||
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
|
||||
gear( 0.5, 2.0, 2.0, 10, 0.7 );
|
||||
glEndList();
|
||||
|
||||
gear3 = glGenLists(1);
|
||||
glNewList(gear3, GL_COMPILE);
|
||||
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue );
|
||||
gear( 1.3, 2.0, 0.5, 10, 0.7 );
|
||||
glEndList();
|
||||
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
glViewport(0, 0, (GLint)500, (GLint)480);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum( -1.0, 1.0, -1, 1, 5.0, 60.0 );
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef( 0.0, 0.0, -40.0 );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
}
|
||||
|
||||
void reshape()
|
||||
{
|
||||
get_proc_info((char*)pri);
|
||||
glViewport(0, 0, pri->width, pri->height-20);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, (GLfloat)pri->width/pri->height, 1.0, 60.0);
|
||||
glTranslatef( 0.0, 0.0, 20.0 );
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
}
|
||||
|
||||
void disabletgl()
|
||||
{
|
||||
kosglDestroyContext(cgl);
|
||||
delete pri;
|
||||
}
|
||||
|
||||
void kos_text(int x, int y, int color, const char* text, int len)
|
||||
{
|
||||
asm volatile ("int $0x40"::"a"(4),"b"((x<<16) | y),"c"(color),"d"((unsigned long)text),"S"(len));
|
||||
};
|
||||
|
||||
void Title()
|
||||
{
|
||||
kos_text(300,8,0x10ffffff,fps,strlen(fps));
|
||||
/*kos_text(180,8,0x90ffffff,title2,strlen(title2));
|
||||
kos_text(600,8,0x90ffffff,title3,strlen(title3));*/
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
// start redraw
|
||||
begin_draw();
|
||||
// define&draw window
|
||||
sys_create_window(win.x, win.y, win.dx, win.dy, title, 0, /*TYPEWIN(0,0,0,1,skin,0,0,0)*/skin);
|
||||
// end redraw
|
||||
end_draw();
|
||||
// display string
|
||||
Title();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
win.x = 100;
|
||||
win.y = 100;
|
||||
win.dx = 400;
|
||||
win.dy = 400;
|
||||
|
||||
draw_window();
|
||||
|
||||
cgl = kosglCreateContext( 0, 0);
|
||||
kosglMakeCurrent( 0, 0, win.dx, win.dy, cgl);
|
||||
|
||||
init();
|
||||
|
||||
pri = new proc_info;
|
||||
SysCall(66,1,1);
|
||||
|
||||
reshape();
|
||||
|
||||
do {
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef( view_rotx, 1.0, 0.0, 0.0 );
|
||||
glRotatef( view_roty, 0.0, 1.0, 0.0 );
|
||||
glRotatef( view_rotz, 0.0, 0.0, 1.0 );
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef( -2.0, -2.0, 0.0 );
|
||||
glRotatef( angle, 0.0, 0.0, 1.0 );
|
||||
glCallList(gear1);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef( 4.1, -2.0, 0.0 );
|
||||
glRotatef( -2.0*angle-9.0, 0.0, 0.0, 1.0 );
|
||||
glCallList(gear2);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef( -2.1, 4.2, 0.0 );
|
||||
glRotatef( -2.0*angle-25.0, 0.0, 0.0, 1.0 );
|
||||
glCallList(gear3);
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
angle += 0.01 + 0.3 * Fps (330, 8);
|
||||
|
||||
switch(check_os_event())
|
||||
{
|
||||
case 1:
|
||||
draw_window();
|
||||
reshape();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
key = get_key();
|
||||
switch(key.code) {
|
||||
case KEY_F:
|
||||
if(!FullScreen){
|
||||
skin=0x01;
|
||||
SysCall(67,0,0,SysCall(14)>>16,SysCall(14)&0xffff);
|
||||
draw_window();
|
||||
reshape();
|
||||
FullScreen = 1;
|
||||
}
|
||||
else{
|
||||
skin=0x34;
|
||||
draw_window();
|
||||
SysCall(67,win.x,win.y,win.dx,win.dy);
|
||||
reshape();
|
||||
FullScreen = 0;
|
||||
};
|
||||
break;
|
||||
|
||||
case KEY_ESC:
|
||||
disabletgl();
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
disabletgl();
|
||||
return 0;
|
||||
}
|
||||
} while(1);
|
||||
}
|
@ -1,396 +0,0 @@
|
||||
/*
|
||||
* Programme name: Backy
|
||||
* Description: The programme for backing up a file.
|
||||
*
|
||||
* Backy.c
|
||||
* Author: JohnXenox aka Aleksandr Igorevich.
|
||||
* Port to GCC: maxcodehack
|
||||
*
|
||||
* Works from command line, only!
|
||||
*/
|
||||
|
||||
#define CREATION_DATE "2020.05.27"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/kos_LoadConsole.h>
|
||||
|
||||
#include "Backy_lib.h"
|
||||
|
||||
int date = 0;
|
||||
int time = 0;
|
||||
|
||||
char years = 0;
|
||||
char months = 0;
|
||||
char days = 0;
|
||||
|
||||
char hours = 0;
|
||||
char minutes = 0;
|
||||
char seconds = 0;
|
||||
|
||||
char *data = 0;
|
||||
int length = 0;
|
||||
|
||||
char path_in[4096] = {0};
|
||||
char path_out[4096] = {0};
|
||||
|
||||
char num[3] = {0};
|
||||
|
||||
char full_date[25] = {0};
|
||||
char ext[] = ".bak";
|
||||
|
||||
char flag = 0;
|
||||
|
||||
char state;
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
// ============================================================ //
|
||||
// preprocessing arguments from the command line. ============= //
|
||||
//
|
||||
// 0 argument - name of the programme.
|
||||
// 1 argument - path to the file with name that need to be backup.
|
||||
// 2 argument - the key (-o).
|
||||
// 3 argument - path to the output directory without the name of the file.
|
||||
|
||||
// printf("Number of args: %d\n", argc);
|
||||
// printf("Argv 0: %s\n", argv[0]);
|
||||
// sprintf("Argv 1: %s\n\n", argv[1]);
|
||||
|
||||
|
||||
// ============================================================ //
|
||||
// process the command line arguments. ======================== //
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
// if found the key "-o", then copy output path into the array "path_out".
|
||||
if (*argv[i] == '-') // && (*(argv[i] + 1) == 'o'))
|
||||
{
|
||||
// printf("Key -o is found!\n");
|
||||
|
||||
i++;
|
||||
|
||||
flag = 1;
|
||||
|
||||
if (i <= argc)
|
||||
{
|
||||
// copying of a current path into the array "path_out".
|
||||
strcpy(path_out, argv[i]);
|
||||
|
||||
// printf("Path output is copyed!\n");
|
||||
|
||||
i++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if input path is found, then copy it into the array "path_in".
|
||||
if (*argv[i] == '/')
|
||||
{
|
||||
flag = 2;
|
||||
|
||||
// copying of a current path into the buffer.
|
||||
strcpy(path_in, argv[i]);
|
||||
|
||||
if (flag != 1)
|
||||
{
|
||||
int idx = strlen(path_in);
|
||||
while (path_in[idx] != '/')
|
||||
{
|
||||
idx--;
|
||||
}
|
||||
|
||||
strncpy(path_out, path_in, idx);
|
||||
}
|
||||
|
||||
// printf("Path input is copyed!\n");
|
||||
}
|
||||
|
||||
// if found characters.
|
||||
if ( (*argv[i] > '0') && (*argv[i] < '9') || \
|
||||
(*argv[i] > 'A') && (*argv[i] < 'Z') || \
|
||||
(*argv[i] > 'a') && (*argv[i] < 'z') )
|
||||
{
|
||||
flag = 3;
|
||||
|
||||
strcpy(path_in, argv[0]);
|
||||
// printf("Arg 0 is copyed!\n");
|
||||
|
||||
int idx = strlen(path_in);
|
||||
|
||||
while (path_in[idx] != '/')
|
||||
{
|
||||
path_in[idx] = 0;
|
||||
idx--;
|
||||
}
|
||||
|
||||
idx++;
|
||||
strcpy(path_out, path_in);
|
||||
strcpy(&path_in[idx], argv[1]);
|
||||
// printf("Arg 1 is added!\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if not found the flag, then copy path from "path_in" into "path_out".
|
||||
if ((flag == 0) && (flag != 2) && (flag != 3))
|
||||
{
|
||||
// copying the input path into the output path,
|
||||
strcpy(path_out, path_in);
|
||||
//printf("Path input is copyed into the path output!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
load_console();
|
||||
|
||||
con_set_title("Useful info!");
|
||||
|
||||
#if defined (lang_en)
|
||||
|
||||
con_printf("\n Name: Backy");
|
||||
con_printf("\n Date: %s", CREATION_DATE);
|
||||
con_printf("\n Description: The programme for backing up a file.\n");
|
||||
|
||||
con_printf("\n Author: JohnXenox\n");
|
||||
|
||||
con_printf("\n Usage: backy <path1> <-o path2>\n");
|
||||
con_printf(" path1 - path to a file to be backuped.\n");
|
||||
con_printf(" -o path2 - path to the output directory without the name of a file.\n\n");
|
||||
|
||||
con_printf(" Examples:\n");
|
||||
con_printf(" backy test.c\n");
|
||||
con_printf(" backy test.c -o /tmp0/1/\n");
|
||||
con_printf(" backy /hd0/1/test.c\n");
|
||||
con_printf(" backy /hd0/1/test.c -o /tmp0/1/\n");
|
||||
|
||||
#elif defined (lang_ru)
|
||||
|
||||
con_printf("\n ˆ¬ï: Backy");
|
||||
con_printf("\n „ â : %s", CREATION_DATE);
|
||||
con_printf("\n Ž¯¨á ¨¥: <20>à®£à ¬¬ ¤«ï ᮧ¤ ¨ï १¥à¢®© ª®¯¨¨ ä ©« .\n");
|
||||
|
||||
con_printf("\n €¢â®à: JohnXenox\n");
|
||||
|
||||
con_printf("\n ˆá¯®«ì§®¢ ¨¥: backy <path1> <-o path2>\n");
|
||||
con_printf(" path1 - ¯ãâì ª ä ©«ã, ª®â®àë© ¤® ᪮¯¨à®¢ âì.\n");
|
||||
con_printf(" -o path2 - ¯ãâì ª ¤¨à¥ªâ®à¨¨, ¢ ª®â®àãî ¡ã¤¥â ᪮¯¨à®¢ १¥à¢ ï ª®¯¨ï ä ©« .\n\n");
|
||||
|
||||
con_printf(" <20>ਬ¥àë:\n");
|
||||
con_printf(" backy test.c\n");
|
||||
con_printf(" backy test.c -o /tmp0/1/\n");
|
||||
con_printf(" backy /hd0/1/test.c\n");
|
||||
con_printf(" backy /hd0/1/test.c -o /tmp0/1/\n");
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//printf("Path_in: %s\n", path_in);
|
||||
//printf("Path_out: %s\n", path_out);
|
||||
|
||||
|
||||
// ============================================================ //
|
||||
// getting the time in BCD. =================================== //
|
||||
|
||||
time = getTime(); // time = 0x00SSMMHH.
|
||||
|
||||
hours = (char)time;
|
||||
minutes = (char)(time >> 8);
|
||||
seconds = (char)(time >> 16);
|
||||
|
||||
// ============================================================ //
|
||||
// getting the date in BCD. =================================== //
|
||||
|
||||
date = getDate(); // date = 0x00DDMMYY.
|
||||
|
||||
years = (char)date;
|
||||
months = (char)(date >> 8);
|
||||
days = (char)(date >> 16);
|
||||
|
||||
// ============================================================ //
|
||||
// fills the array with the date in ASCII. ==================== //
|
||||
|
||||
char ofs = 0;
|
||||
char *dta = 0;
|
||||
|
||||
for (char i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
dta = &years;
|
||||
full_date[ofs] = '2';
|
||||
ofs++;
|
||||
full_date[ofs] = '0';
|
||||
ofs++;
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
dta = &months;
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
dta = &days;
|
||||
}
|
||||
|
||||
|
||||
itoab(*dta, num, 16);
|
||||
|
||||
if (num[1] == 0)
|
||||
{
|
||||
full_date[ofs] = '0';
|
||||
ofs++;
|
||||
full_date[ofs] = num[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
full_date[ofs] = num[0];
|
||||
ofs++;
|
||||
full_date[ofs] = num[1];
|
||||
}
|
||||
|
||||
ofs++;
|
||||
|
||||
if (i != 2)
|
||||
{
|
||||
full_date[ofs] = '.';
|
||||
ofs++;
|
||||
}
|
||||
}
|
||||
|
||||
full_date[ofs] = '_';
|
||||
ofs++;
|
||||
|
||||
// ============================================================ //
|
||||
// fills the array with the time in ASCII. ==================== //
|
||||
|
||||
ofs = 11;
|
||||
dta = 0;
|
||||
|
||||
for (char i = 0; i < 3; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
dta = &hours;
|
||||
if (i == 1)
|
||||
dta = &minutes;
|
||||
if (i == 2)
|
||||
dta = &seconds;
|
||||
|
||||
itoab(*dta, num, 16);
|
||||
|
||||
if (num[1] == 0)
|
||||
{
|
||||
full_date[ofs] = '0';
|
||||
ofs++;
|
||||
full_date[ofs] = num[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
full_date[ofs] = num[0];
|
||||
ofs++;
|
||||
full_date[ofs] = num[1];
|
||||
}
|
||||
|
||||
ofs++;
|
||||
|
||||
if (i < 2)
|
||||
{
|
||||
full_date[ofs] = '.';
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// full_date[ofs] = '_';
|
||||
//}
|
||||
|
||||
ofs++;
|
||||
}
|
||||
|
||||
// ============================================================ //
|
||||
// adding the name of the input file to the output path. ====== //
|
||||
|
||||
int i = 0;
|
||||
int y = 0;
|
||||
|
||||
// searching for a zero terminator in the input path.
|
||||
while (path_in[i] != 0)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// searching for a slash in the input path.
|
||||
while (path_in[i] != '/')
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
// searching for a zero terminator in the output path.
|
||||
while (path_out[y] != 0)
|
||||
{
|
||||
y++;
|
||||
}
|
||||
|
||||
// searching for a slash in the output path.
|
||||
if (path_out[y - 1] == '/')
|
||||
{
|
||||
y--;
|
||||
}
|
||||
|
||||
// copying the input name of the file into the output path,
|
||||
strcpy(&path_out[y], &path_in[i]);
|
||||
|
||||
// ============================================================ //
|
||||
// adding the extension and full date to the path. ============ //
|
||||
|
||||
i = 0;
|
||||
|
||||
// searching for a zero terminator in the output path.
|
||||
while (path_out[i] != 0)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
path_out[i] = '_';
|
||||
i++;
|
||||
|
||||
// adding full date.
|
||||
strcpy(&path_out[i], full_date);
|
||||
|
||||
i += strlen(full_date);
|
||||
|
||||
// adding the extension to a path.
|
||||
strncpy(&path_out[i], ext, 4);
|
||||
|
||||
//printf("Path_in: %s\n", path_in);
|
||||
//printf("Path_out: %s\n", path_out);
|
||||
|
||||
data = openFile(&length, path_in);
|
||||
|
||||
if(data == 0)
|
||||
{
|
||||
load_console();
|
||||
con_set_title("Backy");
|
||||
|
||||
#if defined (lang_en)
|
||||
|
||||
con_printf("\nThe file isn't found!\n");
|
||||
|
||||
#elif defined (lang_ru)
|
||||
|
||||
con_printf("\n” ©« ¥ ©¤¥!\n");
|
||||
|
||||
#endif
|
||||
|
||||
return 13;
|
||||
}
|
||||
|
||||
|
||||
saveFile(length, data, 0, path_out);//return checkStateOnSave(saveFile(length, data, 0, path_out));
|
||||
}
|
||||
|
@ -1,189 +0,0 @@
|
||||
|
||||
/*
|
||||
* Backy_lib.h
|
||||
* Author: JohnXenox aka Aleksandr Igorevich.
|
||||
*/
|
||||
|
||||
#ifndef __Backy_lib_h__
|
||||
#define __Backy_lib_h__
|
||||
|
||||
// Copied from TCC
|
||||
char* strrev(char *p)
|
||||
{
|
||||
char *q = p, *res = p, z;
|
||||
while(q && *q) ++q; /* find eos */
|
||||
for(--q; p < q; ++p, --q)
|
||||
{
|
||||
z = *p;
|
||||
*p = *q;
|
||||
*q = z;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
char* itoab(unsigned int n, char* s, int b)
|
||||
{
|
||||
char *ptr;
|
||||
int lowbit;
|
||||
ptr = s;
|
||||
b >>= 1;
|
||||
do {
|
||||
lowbit = n & 1;
|
||||
n = (n >> 1) & 0x7FFFFFFF;
|
||||
*ptr = ((n % b) << 1) + lowbit;
|
||||
if(*ptr < 10) *ptr += '0'; else *ptr += 55;
|
||||
++ptr;
|
||||
} while(n /= b);
|
||||
*ptr = 0;
|
||||
return strrev(s);
|
||||
}
|
||||
|
||||
/*
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef char int8_t;
|
||||
typedef short int int16_t;
|
||||
typedef int int32_t;
|
||||
typedef long long int64_t;
|
||||
*/
|
||||
static inline uint32_t getDate(void)
|
||||
{
|
||||
uint32_t date;
|
||||
__asm__ __volatile__("int $0x40":"=a"(date):"a"(29));
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline uint32_t getTime(void)
|
||||
{
|
||||
uint32_t time;
|
||||
__asm__ __volatile__("int $0x40":"=a"(time):"a"(3));
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void *openFile(uint32_t *length, const uint8_t *path)
|
||||
{
|
||||
uint8_t *fd;
|
||||
|
||||
__asm__ __volatile__ ("int $0x40":"=a"(fd), "=d"(*length):"a" (68), "b"(27),"c"(path));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
struct saveFileStruct
|
||||
{
|
||||
int p1;
|
||||
int p2;
|
||||
int p3;
|
||||
int p4;
|
||||
|
||||
char* p5;
|
||||
int p6;
|
||||
char* p7;
|
||||
};
|
||||
|
||||
static inline int32_t saveFile(uint32_t nbytes, uint8_t *data, uint32_t enc, uint8_t *path)
|
||||
{
|
||||
int32_t val;
|
||||
|
||||
struct saveFileStruct dt; // basic information structure.
|
||||
|
||||
dt.p1 = 2; // subfunction number.
|
||||
dt.p2= 0; // reserved.
|
||||
dt.p3 = 0; // reserved.
|
||||
dt.p4 = nbytes; // number of bytes to write.
|
||||
dt.p5 = data; // pointer to data.
|
||||
dt.p6 = enc; // string encoding (0 = default, 1 = cp866, 2 = UTF-16LE, 3 = UTF-8).
|
||||
dt.p7 = path; // pointer to path.
|
||||
|
||||
__asm__ __volatile__("int $0x40":"=a"(val):"a"(80), "b"(&dt):"memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int checkStateOnSave(int state)
|
||||
{
|
||||
#if defined (lang_en)
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case 2: con_printf("\nThe function isn't supported for the given file system!\n");
|
||||
return 2;
|
||||
|
||||
case 3: con_printf("\nUnknown file system!\n");
|
||||
return 3;
|
||||
|
||||
case 5: con_printf("\nFile isn't found!\n");
|
||||
return 5;
|
||||
|
||||
case 6: con_printf("\nEnd of a file, EOF!\n");
|
||||
return 6;
|
||||
|
||||
case 7: con_printf("\nPointer lies outside of application memory!\n");
|
||||
return 7;
|
||||
|
||||
case 8: con_printf("\nDisk is full!\n");
|
||||
return 8;
|
||||
|
||||
case 9: con_printf("\nFile system error!\n");
|
||||
return 9;
|
||||
|
||||
case 10: con_printf("\nAccess denied!\n");
|
||||
return 10;
|
||||
|
||||
case 11: con_printf("\nDevice error!\n");
|
||||
return 11;
|
||||
|
||||
case 12: con_printf("\nFile system requires more memory!\n");
|
||||
return 12;
|
||||
}
|
||||
|
||||
#elif defined (lang_ru)
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case 2: con_printf("\n”ãªæ¨ï ¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ¤ ®© ä ©«®¢®© á¨á⥬ë!\n");
|
||||
return 2;
|
||||
|
||||
case 3: con_printf("\n<EFBFBD>¥¨§¢¥áâ ï ä ©«®¢ ï á¨á⥬ !\n");
|
||||
return 3;
|
||||
|
||||
case 5: con_printf("\n” ©« ¥ ©¤¥!\n");
|
||||
return 5;
|
||||
|
||||
case 6: con_printf("\n” ©« § ª®ç¨«áï!\n");
|
||||
return 6;
|
||||
|
||||
case 7: con_printf("\n“ª § â¥«ì ¢¥ ¯ ¬ï⨠¯à¨«®¦¥¨ï!\n");
|
||||
return 7;
|
||||
|
||||
case 8: con_printf("\n„¨áª § ¯®«¥!\n");
|
||||
return 8;
|
||||
|
||||
case 9: con_printf("\nŽè¨¡ª ä ©«®¢®© á¨á⥬ë!\n");
|
||||
return 9;
|
||||
|
||||
case 10: con_printf("\n„®áâ㯠§ ¯à¥éñ!\n");
|
||||
return 10;
|
||||
|
||||
case 11: con_printf("\nŽè¨¡ª ãáâனá⢠!\n");
|
||||
return 11;
|
||||
|
||||
case 12: con_printf("\n” ©«®¢®© á¨á⥬¥ ¥¤®áâ â®ç® ®¯¥à ⨢®© ¯ ¬ïâ¨!\n");
|
||||
return 12;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -1,25 +0,0 @@
|
||||
CC = kos32-gcc
|
||||
LD = kos32-ld
|
||||
|
||||
SDK_DIR = $(abspath ../../../../contrib/sdk)
|
||||
LDFLAGS = -call_shared -nostdlib -T $(SDK_DIR)/sources/newlib/app-dynamic.lds --image-base 0
|
||||
|
||||
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32
|
||||
|
||||
INCLUDES = -I $(SDK_DIR)/sources/newlib/libc/include
|
||||
LIBPATH = -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib
|
||||
|
||||
ifndef LANG_
|
||||
LANG_ = lang_en
|
||||
endif
|
||||
|
||||
default: backy
|
||||
|
||||
backy: $(OBJECTS) Makefile
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -D$(LANG_) -o Backy.o Backy.c
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) --subsystem console -o Backy Backy.o -lgcc -lc.dll
|
||||
kos32-strip -s Backy -o Backy
|
||||
objcopy Backy -O binary
|
||||
rm Backy.o
|
||||
clean:
|
||||
rm Backy
|
@ -1,14 +0,0 @@
|
||||
if tup.getconfig("NO_GCC") ~= "" then return end
|
||||
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../.." or tup.getconfig("HELPERDIR")
|
||||
tup.include(HELPERDIR .. "/use_gcc.lua")
|
||||
tup.include(HELPERDIR .. "/use_newlib.lua")
|
||||
|
||||
if tup.getconfig("LANG") == "ru"
|
||||
then CFLAGS = CFLAGS .. " -Dlang_ru"
|
||||
else CFLAGS = CFLAGS .. " -Dlang_en"
|
||||
end
|
||||
|
||||
CFLAGS = CFLAGS .. " -std=c99"
|
||||
|
||||
compile_gcc{"Backy.c"}
|
||||
link_gcc("Backy")
|
@ -1,6 +0,0 @@
|
||||
Port backy to gcc
|
||||
Languages:
|
||||
Eng:
|
||||
make
|
||||
Rus:
|
||||
env LANG_=lang_ru make
|
@ -1,23 +0,0 @@
|
||||
CC = kos32-gcc
|
||||
LD = kos32-ld
|
||||
OBJCOPY = objcopy
|
||||
STRIP = strip
|
||||
|
||||
NAME = kosjs
|
||||
|
||||
SDK_DIR = ../../../contrib/sdk
|
||||
|
||||
LDFLAGS = -call_shared -nostdlib -T $(SDK_DIR)/sources/newlib/app-dynamic.lds --image-base 0
|
||||
LIBPATH = -L$(SDK_DIR)/lib -L/home/autobuild/tools/win32/mingw32/lib -L libmujs
|
||||
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32
|
||||
INCLUDES = -I $(SDK_DIR)/sources/newlib/libc/include -I libmujs
|
||||
|
||||
all:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) kosjs.c import.c
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) --subsystem native -o $(NAME) $(NAME).o import.o -lmujs -lgcc -lc.dll
|
||||
$(STRIP) -s $(NAME) -o $(NAME)
|
||||
$(OBJCOPY) $(NAME) -O binary
|
||||
|
||||
clean:
|
||||
rm -f $(NAME) *.o
|
||||
|
@ -1,13 +0,0 @@
|
||||
if tup.getconfig("NO_GCC") ~= "" then return end
|
||||
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../.." or tup.getconfig("HELPERDIR")
|
||||
tup.include(HELPERDIR .. "/use_gcc.lua")
|
||||
tup.include(HELPERDIR .. "/use_newlib.lua")
|
||||
|
||||
LDFLAGS = LDFLAGS .. " -Llibmujs --subsystem native"
|
||||
LIBS = "-lmujs " .. LIBS
|
||||
table.insert(LIBDEPS, "libmujs/<libmujs>")
|
||||
INCLUDES = INCLUDES .. " -Ilibmujs"
|
||||
|
||||
compile_gcc{"kosjs.c", "import.c"}
|
||||
link_gcc("kosjs")
|
||||
|
@ -1,64 +0,0 @@
|
||||
var button_text = 0
|
||||
var button = 2
|
||||
|
||||
// Dynamic functions! //
|
||||
//////////////////////////////////////////////////
|
||||
function Delay(long)
|
||||
{
|
||||
KolibriSyscall(5, long, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
function StartDraw()
|
||||
{
|
||||
KolibriSyscall(12, 1, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
function EndDraw()
|
||||
{
|
||||
KolibriSyscall(12, 2, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
function GetEvent()
|
||||
{
|
||||
return KolibriSyscallReturnEAX(10, 0, 0, 0, 0, 0)
|
||||
}
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
function Redraw()
|
||||
{
|
||||
StartDraw()
|
||||
WindowCreate(10, 40, 400, 200, "My window", 0xFFFFFF, 0x14)
|
||||
WriteText("KolibriOS JS example", 15, 34, 0, 0x90000000, 0xFFFFFF)
|
||||
ButtonCreate((150 << 16) + 100, (100 << 16) + 50, button, 0x177245)
|
||||
// Delay(100)
|
||||
WriteText("Click!", 155,115, 0, 0x91000000 | 0xFFFFFF)
|
||||
WriteText(button_text, 15,100, 0, 0x92000000)
|
||||
EndDraw()
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
var gui_event = GetEvent()
|
||||
switch(gui_event)
|
||||
{
|
||||
case 0:
|
||||
break
|
||||
case 1:
|
||||
Redraw()
|
||||
break
|
||||
case 3:
|
||||
var pressed_button = GetButtonEvent()
|
||||
switch (pressed_button)
|
||||
{
|
||||
case 1:
|
||||
Exit()
|
||||
break
|
||||
case button:
|
||||
button_text++;
|
||||
Redraw()
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -1,91 +0,0 @@
|
||||
#include <kos32sys.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <import.h>
|
||||
|
||||
static void _ButtonCreate()
|
||||
{
|
||||
define_button(js_touint32(J, 1),js_touint32(J,2), js_touint32(J,3), js_touint32(J,4));
|
||||
}
|
||||
|
||||
static void _WindowCreate()
|
||||
{
|
||||
sys_create_window(js_toint(J, 1), js_toint(J, 2), js_toint(J, 3), js_toint(J, 4), js_tostring(J,5), js_touint32(J,6), js_touint32(J,7));
|
||||
}
|
||||
|
||||
static void _DebugPrintS()
|
||||
{
|
||||
puts(js_tostring(J,1));
|
||||
|
||||
}
|
||||
|
||||
static void _GetButtonEvent()
|
||||
{
|
||||
js_pushnumber(J,get_os_button());
|
||||
}
|
||||
|
||||
static void _WriteText()
|
||||
{
|
||||
draw_text_sys(js_tostring(J,1), js_toint32(J,2), js_toint32(J,3), js_toint32(J,4), js_touint32(J,5));
|
||||
}
|
||||
|
||||
// KolibriSyscall(EAX, EBX, ECX, EDX, EDI, ESI)
|
||||
static void _KolibriSyscall()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(js_toint32(J,1)),
|
||||
"b"(js_toint32(J,2)),
|
||||
"c"(js_toint32(J,3)),
|
||||
"d"(js_toint32(J,4)),
|
||||
"D"(js_toint32(J,5)),
|
||||
"S"(js_toint32(J,6)) : "memory");
|
||||
}
|
||||
|
||||
static void _KolibriSyscallReturnEAX()
|
||||
{
|
||||
int _eax_;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(_eax_)
|
||||
:"a"(js_toint32(J,1)),
|
||||
"b"(js_toint32(J,2)),
|
||||
"c"(js_toint32(J,3)),
|
||||
"d"(js_toint32(J,4)),
|
||||
"D"(js_toint32(J,5)),
|
||||
"S"(js_toint32(J,6)) : "memory");
|
||||
|
||||
js_pushnumber(J, _eax_);
|
||||
}
|
||||
|
||||
void import_functions()
|
||||
{
|
||||
J = js_newstate(NULL, NULL, JS_STRICT);
|
||||
|
||||
js_newcfunction(J, _WindowCreate, "WindowCreate", 7);
|
||||
js_setglobal(J, "WindowCreate");
|
||||
|
||||
js_newcfunction(J, _DebugPrintS, "DebugPrintS", 0);
|
||||
js_setglobal(J, "DebugPrintS");
|
||||
|
||||
js_newcfunction(J, _ButtonCreate, "ButtonCreate", 4);
|
||||
js_setglobal(J, "ButtonCreate");
|
||||
|
||||
js_newcfunction(J, _GetButtonEvent, "GetButtonEvent", 0);
|
||||
js_setglobal(J, "GetButtonEvent");
|
||||
|
||||
js_newcfunction(J, (void*)exit, "Exit", 0);
|
||||
js_setglobal(J, "Exit");
|
||||
|
||||
js_newcfunction(J, _WriteText, "WriteText", 5);
|
||||
js_setglobal(J, "WriteText");
|
||||
|
||||
js_newcfunction(J, _KolibriSyscall, "KolibriSyscall", 6);
|
||||
js_setglobal(J, "KolibriSyscall");
|
||||
|
||||
js_newcfunction(J, _KolibriSyscallReturnEAX, "KolibriSyscallReturnEAX", 6);
|
||||
js_setglobal(J, "KolibriSyscallReturnEAX");
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mujs.h>
|
||||
#include <import.h>
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
printf("usage: %s [program.js]\n", argv[0]);
|
||||
} else {
|
||||
import_functions();
|
||||
js_dofile(J, argv[1]);
|
||||
js_freestate (J);
|
||||
}
|
||||
exit(0);
|
||||
}
|
@ -1 +0,0 @@
|
||||
Tor Andersson <tor.andersson@artifex.com>
|
@ -1,16 +0,0 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2013-2020 Artifex Software, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
@ -1,16 +0,0 @@
|
||||
CC = kos32-gcc
|
||||
|
||||
SDK_DIR = ../../../../contrib/sdk
|
||||
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32
|
||||
|
||||
INCLUDES = -I $(SDK_DIR)/sources/newlib/libc/include -I .
|
||||
|
||||
SRC := $(notdir $(wildcard *.c))
|
||||
OBJECTS = $(patsubst %.c, %.o, $(SRC))
|
||||
|
||||
default: $(patsubst %.c,%.o,$(SRC))
|
||||
ar rcs libmujs.a *.o
|
||||
rm *.o
|
||||
|
||||
%.o : %.c Makefile $(SRC)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
|
@ -1,52 +0,0 @@
|
||||
MuJS: an embeddable Javascript interpreter in C.
|
||||
|
||||
ABOUT
|
||||
|
||||
MuJS is a lightweight Javascript interpreter designed for embedding in
|
||||
other software to extend them with scripting capabilities.
|
||||
|
||||
LICENSE
|
||||
|
||||
MuJS is Copyright 2013-2017 Artifex Software, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
The software is provided "as is" and the author disclaims all warranties with
|
||||
regard to this software including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any special, direct,
|
||||
indirect, or consequential damages or any damages whatsoever resulting from
|
||||
loss of use, data or profits, whether in an action of contract, negligence
|
||||
or other tortious action, arising out of or in connection with the use or
|
||||
performance of this software.
|
||||
|
||||
COMPILING
|
||||
|
||||
If you are building from source you can either use the provided Unix Makefile:
|
||||
|
||||
make release
|
||||
|
||||
Or compile the source with your preferred compiler:
|
||||
|
||||
cc -O2 -c one.c -o libmujs.o
|
||||
|
||||
INSTALLING
|
||||
|
||||
To install the MuJS command line interpreter, static library and header file:
|
||||
|
||||
make prefix=/usr/local install
|
||||
|
||||
DOWNLOAD
|
||||
|
||||
The latest development source is available directly from the git repository:
|
||||
|
||||
git clone http://git.ghostscript.com/mujs.git
|
||||
|
||||
REPORTING BUGS AND PROBLEMS
|
||||
|
||||
Report bugs on the ghostscript bugzilla, with MuJS as the selected component.
|
||||
|
||||
http://bugs.ghostscript.com/
|
||||
|
||||
The MuJS developers hang out on IRC in the #mupdf channel on irc.freenode.net.
|
@ -1,10 +0,0 @@
|
||||
if tup.getconfig("NO_GCC") ~= "" then return end
|
||||
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../.." or tup.getconfig("HELPERDIR")
|
||||
tup.include(HELPERDIR .. "/use_gcc.lua")
|
||||
tup.include(HELPERDIR .. "/use_newlib.lua")
|
||||
|
||||
CFLAGS = CFLAGS .. " -std=c99 -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32"
|
||||
INCLUDES = INCLUDES .. " -I ."
|
||||
|
||||
compile_gcc{"utftype.c", "jsproperty.c", "jsobject.c", "jsdtoa.c", "jsbuiltin.c", "jsvalue.c", "jsnumber.c", "jsparse.c", "jsstate.c", "jsgc.c", "jsrepr.c", "pp.c", "utf.c", "jsfunction.c", "jsdump.c", "regexp.c", "jsstring.c", "jsarray.c", "jsrun.c", "jsdate.c", "jscompile.c", "jslex.c", "jsboolean.c", "jserror.c", "jsintern.c", "jsmath.c", "jsregexp.c", "json.c"}
|
||||
tup.rule(OBJS, "kos32-ar rcs %o %f", {"libmujs.a", "<libmujs>"})
|
@ -1,92 +0,0 @@
|
||||
"list",
|
||||
"fundec",
|
||||
"identifier",
|
||||
"exp_identifier",
|
||||
"exp_number",
|
||||
"exp_string",
|
||||
"exp_regexp",
|
||||
"exp_undef",
|
||||
"exp_null",
|
||||
"exp_true",
|
||||
"exp_false",
|
||||
"exp_this",
|
||||
"exp_array",
|
||||
"exp_object",
|
||||
"exp_prop_val",
|
||||
"exp_prop_get",
|
||||
"exp_prop_set",
|
||||
"exp_fun",
|
||||
"exp_index",
|
||||
"exp_member",
|
||||
"exp_call",
|
||||
"exp_new",
|
||||
"exp_postinc",
|
||||
"exp_postdec",
|
||||
"exp_delete",
|
||||
"exp_void",
|
||||
"exp_typeof",
|
||||
"exp_preinc",
|
||||
"exp_predec",
|
||||
"exp_pos",
|
||||
"exp_neg",
|
||||
"exp_bitnot",
|
||||
"exp_lognot",
|
||||
"exp_mod",
|
||||
"exp_div",
|
||||
"exp_mul",
|
||||
"exp_sub",
|
||||
"exp_add",
|
||||
"exp_ushr",
|
||||
"exp_shr",
|
||||
"exp_shl",
|
||||
"exp_in",
|
||||
"exp_instanceof",
|
||||
"exp_ge",
|
||||
"exp_le",
|
||||
"exp_gt",
|
||||
"exp_lt",
|
||||
"exp_strictne",
|
||||
"exp_stricteq",
|
||||
"exp_ne",
|
||||
"exp_eq",
|
||||
"exp_bitand",
|
||||
"exp_bitxor",
|
||||
"exp_bitor",
|
||||
"exp_logand",
|
||||
"exp_logor",
|
||||
"exp_cond",
|
||||
"exp_ass",
|
||||
"exp_ass_mul",
|
||||
"exp_ass_div",
|
||||
"exp_ass_mod",
|
||||
"exp_ass_add",
|
||||
"exp_ass_sub",
|
||||
"exp_ass_shl",
|
||||
"exp_ass_shr",
|
||||
"exp_ass_ushr",
|
||||
"exp_ass_bitand",
|
||||
"exp_ass_bitxor",
|
||||
"exp_ass_bitor",
|
||||
"exp_comma",
|
||||
"exp_var",
|
||||
"stm_block",
|
||||
"stm_empty",
|
||||
"stm_var",
|
||||
"stm_if",
|
||||
"stm_do",
|
||||
"stm_while",
|
||||
"stm_for",
|
||||
"stm_for_var",
|
||||
"stm_for_in",
|
||||
"stm_for_in_var",
|
||||
"stm_continue",
|
||||
"stm_break",
|
||||
"stm_return",
|
||||
"stm_with",
|
||||
"stm_switch",
|
||||
"stm_throw",
|
||||
"stm_try",
|
||||
"stm_debugger",
|
||||
"stm_label",
|
||||
"stm_case",
|
||||
"stm_default",
|
@ -1,6 +0,0 @@
|
||||
#include "mujs.h"
|
||||
#define js_toint(J, idx) js_tointeger(J, idx)
|
||||
|
||||
js_State *J;
|
||||
|
||||
void import_functions();
|
@ -1,748 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
int js_getlength(js_State *J, int idx)
|
||||
{
|
||||
int len;
|
||||
js_getproperty(J, idx, "length");
|
||||
len = js_tointeger(J, -1);
|
||||
js_pop(J, 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
void js_setlength(js_State *J, int idx, int len)
|
||||
{
|
||||
js_pushnumber(J, len);
|
||||
js_setproperty(J, idx < 0 ? idx - 1 : idx, "length");
|
||||
}
|
||||
|
||||
int js_hasindex(js_State *J, int idx, int i)
|
||||
{
|
||||
char buf[32];
|
||||
return js_hasproperty(J, idx, js_itoa(buf, i));
|
||||
}
|
||||
|
||||
void js_getindex(js_State *J, int idx, int i)
|
||||
{
|
||||
char buf[32];
|
||||
js_getproperty(J, idx, js_itoa(buf, i));
|
||||
}
|
||||
|
||||
void js_setindex(js_State *J, int idx, int i)
|
||||
{
|
||||
char buf[32];
|
||||
js_setproperty(J, idx, js_itoa(buf, i));
|
||||
}
|
||||
|
||||
void js_delindex(js_State *J, int idx, int i)
|
||||
{
|
||||
char buf[32];
|
||||
js_delproperty(J, idx, js_itoa(buf, i));
|
||||
}
|
||||
|
||||
static void jsB_new_Array(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
if (top == 2) {
|
||||
if (js_isnumber(J, 1)) {
|
||||
js_copy(J, 1);
|
||||
js_setproperty(J, -2, "length");
|
||||
} else {
|
||||
js_copy(J, 1);
|
||||
js_setindex(J, -2, 0);
|
||||
}
|
||||
} else {
|
||||
for (i = 1; i < top; ++i) {
|
||||
js_copy(J, i);
|
||||
js_setindex(J, -2, i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ap_concat(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
int n, k, len;
|
||||
|
||||
js_newarray(J);
|
||||
n = 0;
|
||||
|
||||
for (i = 0; i < top; ++i) {
|
||||
js_copy(J, i);
|
||||
if (js_isarray(J, -1)) {
|
||||
len = js_getlength(J, -1);
|
||||
for (k = 0; k < len; ++k)
|
||||
if (js_hasindex(J, -1, k))
|
||||
js_setindex(J, -3, n++);
|
||||
js_pop(J, 1);
|
||||
} else {
|
||||
js_setindex(J, -2, n++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ap_join(js_State *J)
|
||||
{
|
||||
char * volatile out = NULL;
|
||||
const char *sep;
|
||||
const char *r;
|
||||
int seplen;
|
||||
int k, n, len;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
|
||||
if (js_isdefined(J, 1)) {
|
||||
sep = js_tostring(J, 1);
|
||||
seplen = strlen(sep);
|
||||
} else {
|
||||
sep = ",";
|
||||
seplen = 1;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
js_pushliteral(J, "");
|
||||
return;
|
||||
}
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, out);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
n = 1;
|
||||
for (k = 0; k < len; ++k) {
|
||||
js_getindex(J, 0, k);
|
||||
if (js_isundefined(J, -1) || js_isnull(J, -1))
|
||||
r = "";
|
||||
else
|
||||
r = js_tostring(J, -1);
|
||||
n += strlen(r);
|
||||
|
||||
if (k == 0) {
|
||||
out = js_malloc(J, n);
|
||||
strcpy(out, r);
|
||||
} else {
|
||||
n += seplen;
|
||||
out = js_realloc(J, out, n);
|
||||
strcat(out, sep);
|
||||
strcat(out, r);
|
||||
}
|
||||
|
||||
js_pop(J, 1);
|
||||
}
|
||||
|
||||
js_pushstring(J, out);
|
||||
js_endtry(J);
|
||||
js_free(J, out);
|
||||
}
|
||||
|
||||
static void Ap_pop(js_State *J)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = js_getlength(J, 0);
|
||||
|
||||
if (n > 0) {
|
||||
js_getindex(J, 0, n - 1);
|
||||
js_delindex(J, 0, n - 1);
|
||||
js_setlength(J, 0, n - 1);
|
||||
} else {
|
||||
js_setlength(J, 0, 0);
|
||||
js_pushundefined(J);
|
||||
}
|
||||
}
|
||||
|
||||
static void Ap_push(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
int n;
|
||||
|
||||
n = js_getlength(J, 0);
|
||||
|
||||
for (i = 1; i < top; ++i, ++n) {
|
||||
js_copy(J, i);
|
||||
js_setindex(J, 0, n);
|
||||
}
|
||||
|
||||
js_setlength(J, 0, n);
|
||||
|
||||
js_pushnumber(J, n);
|
||||
}
|
||||
|
||||
static void Ap_reverse(js_State *J)
|
||||
{
|
||||
int len, middle, lower;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
middle = len / 2;
|
||||
lower = 0;
|
||||
|
||||
while (lower != middle) {
|
||||
int upper = len - lower - 1;
|
||||
int haslower = js_hasindex(J, 0, lower);
|
||||
int hasupper = js_hasindex(J, 0, upper);
|
||||
if (haslower && hasupper) {
|
||||
js_setindex(J, 0, lower);
|
||||
js_setindex(J, 0, upper);
|
||||
} else if (hasupper) {
|
||||
js_setindex(J, 0, lower);
|
||||
js_delindex(J, 0, upper);
|
||||
} else if (haslower) {
|
||||
js_setindex(J, 0, upper);
|
||||
js_delindex(J, 0, lower);
|
||||
}
|
||||
++lower;
|
||||
}
|
||||
|
||||
js_copy(J, 0);
|
||||
}
|
||||
|
||||
static void Ap_shift(js_State *J)
|
||||
{
|
||||
int k, len;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
|
||||
if (len == 0) {
|
||||
js_setlength(J, 0, 0);
|
||||
js_pushundefined(J);
|
||||
return;
|
||||
}
|
||||
|
||||
js_getindex(J, 0, 0);
|
||||
|
||||
for (k = 1; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k))
|
||||
js_setindex(J, 0, k - 1);
|
||||
else
|
||||
js_delindex(J, 0, k - 1);
|
||||
}
|
||||
|
||||
js_delindex(J, 0, len - 1);
|
||||
js_setlength(J, 0, len - 1);
|
||||
}
|
||||
|
||||
static void Ap_slice(js_State *J)
|
||||
{
|
||||
int len, s, e, n;
|
||||
double sv, ev;
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
sv = js_tointeger(J, 1);
|
||||
ev = js_isdefined(J, 2) ? js_tointeger(J, 2) : len;
|
||||
|
||||
if (sv < 0) sv = sv + len;
|
||||
if (ev < 0) ev = ev + len;
|
||||
|
||||
s = sv < 0 ? 0 : sv > len ? len : sv;
|
||||
e = ev < 0 ? 0 : ev > len ? len : ev;
|
||||
|
||||
for (n = 0; s < e; ++s, ++n)
|
||||
if (js_hasindex(J, 0, s))
|
||||
js_setindex(J, -2, n);
|
||||
}
|
||||
|
||||
struct sortslot {
|
||||
js_Value v;
|
||||
js_State *J;
|
||||
};
|
||||
|
||||
static int sortcmp(const void *avoid, const void *bvoid)
|
||||
{
|
||||
const struct sortslot *aslot = avoid, *bslot = bvoid;
|
||||
const js_Value *a = &aslot->v, *b = &bslot->v;
|
||||
js_State *J = aslot->J;
|
||||
const char *sx, *sy;
|
||||
double v;
|
||||
int c;
|
||||
|
||||
int unx = (a->type == JS_TUNDEFINED);
|
||||
int uny = (b->type == JS_TUNDEFINED);
|
||||
if (unx) return !uny;
|
||||
if (uny) return -1;
|
||||
|
||||
if (js_iscallable(J, 1)) {
|
||||
js_copy(J, 1); /* copy function */
|
||||
js_pushundefined(J);
|
||||
js_pushvalue(J, *a);
|
||||
js_pushvalue(J, *b);
|
||||
js_call(J, 2);
|
||||
v = js_tonumber(J, -1);
|
||||
c = (v == 0) ? 0 : (v < 0) ? -1 : 1;
|
||||
js_pop(J, 1);
|
||||
} else {
|
||||
js_pushvalue(J, *a);
|
||||
js_pushvalue(J, *b);
|
||||
sx = js_tostring(J, -2);
|
||||
sy = js_tostring(J, -1);
|
||||
c = strcmp(sx, sy);
|
||||
js_pop(J, 2);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static void Ap_sort(js_State *J)
|
||||
{
|
||||
struct sortslot *array = NULL;
|
||||
int i, n, len;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
if (len <= 0) {
|
||||
js_copy(J, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= INT_MAX / (int)sizeof(*array))
|
||||
js_rangeerror(J, "array is too large to sort");
|
||||
|
||||
array = js_malloc(J, len * sizeof *array);
|
||||
|
||||
/* Holding objects where the GC cannot see them is illegal, but if we
|
||||
* don't allow the GC to run we can use qsort() on a temporary array of
|
||||
* js_Values for fast sorting.
|
||||
*/
|
||||
++J->gcpause;
|
||||
|
||||
if (js_try(J)) {
|
||||
--J->gcpause;
|
||||
js_free(J, array);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (js_hasindex(J, 0, i)) {
|
||||
array[n].v = *js_tovalue(J, -1);
|
||||
array[n].J = J;
|
||||
js_pop(J, 1);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(array, n, sizeof *array, sortcmp);
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
js_pushvalue(J, array[i].v);
|
||||
js_setindex(J, 0, i);
|
||||
}
|
||||
for (i = n; i < len; ++i) {
|
||||
js_delindex(J, 0, i);
|
||||
}
|
||||
|
||||
--J->gcpause;
|
||||
|
||||
js_endtry(J);
|
||||
js_free(J, array);
|
||||
|
||||
js_copy(J, 0);
|
||||
}
|
||||
|
||||
static void Ap_splice(js_State *J)
|
||||
{
|
||||
int top = js_gettop(J);
|
||||
int len, start, del, add, k;
|
||||
double f;
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
|
||||
f = js_tointeger(J, 1);
|
||||
if (f < 0) f = f + len;
|
||||
start = f < 0 ? 0 : f > len ? len : f;
|
||||
|
||||
f = js_tointeger(J, 2);
|
||||
del = f < 0 ? 0 : f > len - start ? len - start : f;
|
||||
|
||||
/* copy deleted items to return array */
|
||||
for (k = 0; k < del; ++k)
|
||||
if (js_hasindex(J, 0, start + k))
|
||||
js_setindex(J, -2, k);
|
||||
js_setlength(J, -1, del);
|
||||
|
||||
/* shift the tail to resize the hole left by deleted items */
|
||||
add = top - 3;
|
||||
if (add < del) {
|
||||
for (k = start; k < len - del; ++k) {
|
||||
if (js_hasindex(J, 0, k + del))
|
||||
js_setindex(J, 0, k + add);
|
||||
else
|
||||
js_delindex(J, 0, k + add);
|
||||
}
|
||||
for (k = len; k > len - del + add; --k)
|
||||
js_delindex(J, 0, k - 1);
|
||||
} else if (add > del) {
|
||||
for (k = len - del; k > start; --k) {
|
||||
if (js_hasindex(J, 0, k + del - 1))
|
||||
js_setindex(J, 0, k + add - 1);
|
||||
else
|
||||
js_delindex(J, 0, k + add - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy new items into the hole */
|
||||
for (k = 0; k < add; ++k) {
|
||||
js_copy(J, 3 + k);
|
||||
js_setindex(J, 0, start + k);
|
||||
}
|
||||
|
||||
js_setlength(J, 0, len - del + add);
|
||||
}
|
||||
|
||||
static void Ap_unshift(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
int k, len;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
|
||||
for (k = len; k > 0; --k) {
|
||||
int from = k - 1;
|
||||
int to = k + top - 2;
|
||||
if (js_hasindex(J, 0, from))
|
||||
js_setindex(J, 0, to);
|
||||
else
|
||||
js_delindex(J, 0, to);
|
||||
}
|
||||
|
||||
for (i = 1; i < top; ++i) {
|
||||
js_copy(J, i);
|
||||
js_setindex(J, 0, i - 1);
|
||||
}
|
||||
|
||||
js_setlength(J, 0, len + top - 1);
|
||||
|
||||
js_pushnumber(J, len + top - 1);
|
||||
}
|
||||
|
||||
static void Ap_toString(js_State *J)
|
||||
{
|
||||
int top = js_gettop(J);
|
||||
js_pop(J, top - 1);
|
||||
Ap_join(J);
|
||||
}
|
||||
|
||||
static void Ap_indexOf(js_State *J)
|
||||
{
|
||||
int k, len, from;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
from = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
|
||||
if (from < 0) from = len + from;
|
||||
if (from < 0) from = 0;
|
||||
|
||||
js_copy(J, 1);
|
||||
for (k = from; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
if (js_strictequal(J)) {
|
||||
js_pushnumber(J, k);
|
||||
return;
|
||||
}
|
||||
js_pop(J, 1);
|
||||
}
|
||||
}
|
||||
|
||||
js_pushnumber(J, -1);
|
||||
}
|
||||
|
||||
static void Ap_lastIndexOf(js_State *J)
|
||||
{
|
||||
int k, len, from;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
from = js_isdefined(J, 2) ? js_tointeger(J, 2) : len - 1;
|
||||
if (from > len - 1) from = len - 1;
|
||||
if (from < 0) from = len + from;
|
||||
|
||||
js_copy(J, 1);
|
||||
for (k = from; k >= 0; --k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
if (js_strictequal(J)) {
|
||||
js_pushnumber(J, k);
|
||||
return;
|
||||
}
|
||||
js_pop(J, 1);
|
||||
}
|
||||
}
|
||||
|
||||
js_pushnumber(J, -1);
|
||||
}
|
||||
|
||||
static void Ap_every(js_State *J)
|
||||
{
|
||||
int hasthis = js_gettop(J) >= 3;
|
||||
int k, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
for (k = 0; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
if (hasthis)
|
||||
js_copy(J, 2);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_copy(J, -3);
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 3);
|
||||
if (!js_toboolean(J, -1))
|
||||
return;
|
||||
js_pop(J, 2);
|
||||
}
|
||||
}
|
||||
|
||||
js_pushboolean(J, 1);
|
||||
}
|
||||
|
||||
static void Ap_some(js_State *J)
|
||||
{
|
||||
int hasthis = js_gettop(J) >= 3;
|
||||
int k, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
for (k = 0; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
if (hasthis)
|
||||
js_copy(J, 2);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_copy(J, -3);
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 3);
|
||||
if (js_toboolean(J, -1))
|
||||
return;
|
||||
js_pop(J, 2);
|
||||
}
|
||||
}
|
||||
|
||||
js_pushboolean(J, 0);
|
||||
}
|
||||
|
||||
static void Ap_forEach(js_State *J)
|
||||
{
|
||||
int hasthis = js_gettop(J) >= 3;
|
||||
int k, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
for (k = 0; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
if (hasthis)
|
||||
js_copy(J, 2);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_copy(J, -3);
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 3);
|
||||
js_pop(J, 2);
|
||||
}
|
||||
}
|
||||
|
||||
js_pushundefined(J);
|
||||
}
|
||||
|
||||
static void Ap_map(js_State *J)
|
||||
{
|
||||
int hasthis = js_gettop(J) >= 3;
|
||||
int k, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
for (k = 0; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
if (hasthis)
|
||||
js_copy(J, 2);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_copy(J, -3);
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 3);
|
||||
js_setindex(J, -3, k);
|
||||
js_pop(J, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ap_filter(js_State *J)
|
||||
{
|
||||
int hasthis = js_gettop(J) >= 3;
|
||||
int k, to, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
js_newarray(J);
|
||||
to = 0;
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
for (k = 0; k < len; ++k) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
if (hasthis)
|
||||
js_copy(J, 2);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_copy(J, -3);
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 3);
|
||||
if (js_toboolean(J, -1)) {
|
||||
js_pop(J, 1);
|
||||
js_setindex(J, -2, to++);
|
||||
} else {
|
||||
js_pop(J, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ap_reduce(js_State *J)
|
||||
{
|
||||
int hasinitial = js_gettop(J) >= 3;
|
||||
int k, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
k = 0;
|
||||
|
||||
if (len == 0 && !hasinitial)
|
||||
js_typeerror(J, "no initial value");
|
||||
|
||||
/* initial value of accumulator */
|
||||
if (hasinitial)
|
||||
js_copy(J, 2);
|
||||
else {
|
||||
while (k < len)
|
||||
if (js_hasindex(J, 0, k++))
|
||||
break;
|
||||
if (k == len)
|
||||
js_typeerror(J, "no initial value");
|
||||
}
|
||||
|
||||
while (k < len) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
js_pushundefined(J);
|
||||
js_rot(J, 4); /* accumulator on top */
|
||||
js_rot(J, 4); /* property on top */
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 4); /* calculate new accumulator */
|
||||
}
|
||||
++k;
|
||||
}
|
||||
|
||||
/* return accumulator */
|
||||
}
|
||||
|
||||
static void Ap_reduceRight(js_State *J)
|
||||
{
|
||||
int hasinitial = js_gettop(J) >= 3;
|
||||
int k, len;
|
||||
|
||||
if (!js_iscallable(J, 1))
|
||||
js_typeerror(J, "callback is not a function");
|
||||
|
||||
len = js_getlength(J, 0);
|
||||
k = len - 1;
|
||||
|
||||
if (len == 0 && !hasinitial)
|
||||
js_typeerror(J, "no initial value");
|
||||
|
||||
/* initial value of accumulator */
|
||||
if (hasinitial)
|
||||
js_copy(J, 2);
|
||||
else {
|
||||
while (k >= 0)
|
||||
if (js_hasindex(J, 0, k--))
|
||||
break;
|
||||
if (k < 0)
|
||||
js_typeerror(J, "no initial value");
|
||||
}
|
||||
|
||||
while (k >= 0) {
|
||||
if (js_hasindex(J, 0, k)) {
|
||||
js_copy(J, 1);
|
||||
js_pushundefined(J);
|
||||
js_rot(J, 4); /* accumulator on top */
|
||||
js_rot(J, 4); /* property on top */
|
||||
js_pushnumber(J, k);
|
||||
js_copy(J, 0);
|
||||
js_call(J, 4); /* calculate new accumulator */
|
||||
}
|
||||
--k;
|
||||
}
|
||||
|
||||
/* return accumulator */
|
||||
}
|
||||
|
||||
static void A_isArray(js_State *J)
|
||||
{
|
||||
if (js_isobject(J, 1)) {
|
||||
js_Object *T = js_toobject(J, 1);
|
||||
js_pushboolean(J, T->type == JS_CARRAY);
|
||||
} else {
|
||||
js_pushboolean(J, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void jsB_initarray(js_State *J)
|
||||
{
|
||||
js_pushobject(J, J->Array_prototype);
|
||||
{
|
||||
jsB_propf(J, "Array.prototype.toString", Ap_toString, 0);
|
||||
jsB_propf(J, "Array.prototype.concat", Ap_concat, 0); /* 1 */
|
||||
jsB_propf(J, "Array.prototype.join", Ap_join, 1);
|
||||
jsB_propf(J, "Array.prototype.pop", Ap_pop, 0);
|
||||
jsB_propf(J, "Array.prototype.push", Ap_push, 0); /* 1 */
|
||||
jsB_propf(J, "Array.prototype.reverse", Ap_reverse, 0);
|
||||
jsB_propf(J, "Array.prototype.shift", Ap_shift, 0);
|
||||
jsB_propf(J, "Array.prototype.slice", Ap_slice, 2);
|
||||
jsB_propf(J, "Array.prototype.sort", Ap_sort, 1);
|
||||
jsB_propf(J, "Array.prototype.splice", Ap_splice, 0); /* 2 */
|
||||
jsB_propf(J, "Array.prototype.unshift", Ap_unshift, 0); /* 1 */
|
||||
|
||||
/* ES5 */
|
||||
jsB_propf(J, "Array.prototype.indexOf", Ap_indexOf, 1);
|
||||
jsB_propf(J, "Array.prototype.lastIndexOf", Ap_lastIndexOf, 1);
|
||||
jsB_propf(J, "Array.prototype.every", Ap_every, 1);
|
||||
jsB_propf(J, "Array.prototype.some", Ap_some, 1);
|
||||
jsB_propf(J, "Array.prototype.forEach", Ap_forEach, 1);
|
||||
jsB_propf(J, "Array.prototype.map", Ap_map, 1);
|
||||
jsB_propf(J, "Array.prototype.filter", Ap_filter, 1);
|
||||
jsB_propf(J, "Array.prototype.reduce", Ap_reduce, 1);
|
||||
jsB_propf(J, "Array.prototype.reduceRight", Ap_reduceRight, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_new_Array, jsB_new_Array, "Array", 0); /* 1 */
|
||||
{
|
||||
/* ES5 */
|
||||
jsB_propf(J, "Array.isArray", A_isArray, 1);
|
||||
}
|
||||
js_defglobal(J, "Array", JS_DONTENUM);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static void jsB_new_Boolean(js_State *J)
|
||||
{
|
||||
js_newboolean(J, js_toboolean(J, 1));
|
||||
}
|
||||
|
||||
static void jsB_Boolean(js_State *J)
|
||||
{
|
||||
js_pushboolean(J, js_toboolean(J, 1));
|
||||
}
|
||||
|
||||
static void Bp_toString(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
|
||||
js_pushliteral(J, self->u.boolean ? "true" : "false");
|
||||
}
|
||||
|
||||
static void Bp_valueOf(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
|
||||
js_pushboolean(J, self->u.boolean);
|
||||
}
|
||||
|
||||
void jsB_initboolean(js_State *J)
|
||||
{
|
||||
J->Boolean_prototype->u.boolean = 0;
|
||||
|
||||
js_pushobject(J, J->Boolean_prototype);
|
||||
{
|
||||
jsB_propf(J, "Boolean.prototype.toString", Bp_toString, 0);
|
||||
jsB_propf(J, "Boolean.prototype.valueOf", Bp_valueOf, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Boolean, jsB_new_Boolean, "Boolean", 1);
|
||||
js_defglobal(J, "Boolean", JS_DONTENUM);
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
|
||||
{
|
||||
js_newcfunction(J, cfun, name, n);
|
||||
js_defglobal(J, name, JS_DONTENUM);
|
||||
}
|
||||
|
||||
void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n)
|
||||
{
|
||||
const char *pname = strrchr(name, '.');
|
||||
pname = pname ? pname + 1 : name;
|
||||
js_newcfunction(J, cfun, name, n);
|
||||
js_defproperty(J, -2, pname, JS_DONTENUM);
|
||||
}
|
||||
|
||||
void jsB_propn(js_State *J, const char *name, double number)
|
||||
{
|
||||
js_pushnumber(J, number);
|
||||
js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
}
|
||||
|
||||
void jsB_props(js_State *J, const char *name, const char *string)
|
||||
{
|
||||
js_pushliteral(J, string);
|
||||
js_defproperty(J, -2, name, JS_DONTENUM);
|
||||
}
|
||||
|
||||
static void jsB_parseInt(js_State *J)
|
||||
{
|
||||
const char *s = js_tostring(J, 1);
|
||||
int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 10;
|
||||
double sign = 1;
|
||||
double n;
|
||||
char *e;
|
||||
|
||||
while (jsY_iswhite(*s) || jsY_isnewline(*s))
|
||||
++s;
|
||||
if (*s == '-') {
|
||||
++s;
|
||||
sign = -1;
|
||||
} else if (*s == '+') {
|
||||
++s;
|
||||
}
|
||||
if (radix == 0) {
|
||||
radix = 10;
|
||||
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
|
||||
s += 2;
|
||||
radix = 16;
|
||||
}
|
||||
} else if (radix < 2 || radix > 36) {
|
||||
js_pushnumber(J, NAN);
|
||||
return;
|
||||
}
|
||||
n = strtol(s, &e, radix);
|
||||
if (s == e)
|
||||
js_pushnumber(J, NAN);
|
||||
else
|
||||
js_pushnumber(J, n * sign);
|
||||
}
|
||||
|
||||
static void jsB_parseFloat(js_State *J)
|
||||
{
|
||||
const char *s = js_tostring(J, 1);
|
||||
char *e;
|
||||
double n;
|
||||
|
||||
while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
|
||||
if (!strncmp(s, "Infinity", 8))
|
||||
js_pushnumber(J, INFINITY);
|
||||
else if (!strncmp(s, "+Infinity", 9))
|
||||
js_pushnumber(J, INFINITY);
|
||||
else if (!strncmp(s, "-Infinity", 9))
|
||||
js_pushnumber(J, -INFINITY);
|
||||
else {
|
||||
n = js_stringtofloat(s, &e);
|
||||
if (e == s)
|
||||
js_pushnumber(J, NAN);
|
||||
else
|
||||
js_pushnumber(J, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void jsB_isNaN(js_State *J)
|
||||
{
|
||||
double n = js_tonumber(J, 1);
|
||||
js_pushboolean(J, isnan(n));
|
||||
}
|
||||
|
||||
static void jsB_isFinite(js_State *J)
|
||||
{
|
||||
double n = js_tonumber(J, 1);
|
||||
js_pushboolean(J, isfinite(n));
|
||||
}
|
||||
|
||||
static void Encode(js_State *J, const char *str, const char *unescaped)
|
||||
{
|
||||
js_Buffer *sb = NULL;
|
||||
|
||||
static const char *HEX = "0123456789ABCDEF";
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
while (*str) {
|
||||
int c = (unsigned char) *str++;
|
||||
if (strchr(unescaped, c))
|
||||
js_putc(J, &sb, c);
|
||||
else {
|
||||
js_putc(J, &sb, '%');
|
||||
js_putc(J, &sb, HEX[(c >> 4) & 0xf]);
|
||||
js_putc(J, &sb, HEX[c & 0xf]);
|
||||
}
|
||||
}
|
||||
js_putc(J, &sb, 0);
|
||||
|
||||
js_pushstring(J, sb ? sb->s : "");
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
|
||||
static void Decode(js_State *J, const char *str, const char *reserved)
|
||||
{
|
||||
js_Buffer *sb = NULL;
|
||||
int a, b;
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
while (*str) {
|
||||
int c = (unsigned char) *str++;
|
||||
if (c != '%')
|
||||
js_putc(J, &sb, c);
|
||||
else {
|
||||
if (!str[0] || !str[1])
|
||||
js_urierror(J, "truncated escape sequence");
|
||||
a = *str++;
|
||||
b = *str++;
|
||||
if (!jsY_ishex(a) || !jsY_ishex(b))
|
||||
js_urierror(J, "invalid escape sequence");
|
||||
c = jsY_tohex(a) << 4 | jsY_tohex(b);
|
||||
if (!strchr(reserved, c))
|
||||
js_putc(J, &sb, c);
|
||||
else {
|
||||
js_putc(J, &sb, '%');
|
||||
js_putc(J, &sb, a);
|
||||
js_putc(J, &sb, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
js_putc(J, &sb, 0);
|
||||
|
||||
js_pushstring(J, sb ? sb->s : "");
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
|
||||
#define URIRESERVED ";/?:@&=+$,"
|
||||
#define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define URIDIGIT "0123456789"
|
||||
#define URIMARK "-_.!~*`()"
|
||||
#define URIUNESCAPED URIALPHA URIDIGIT URIMARK
|
||||
|
||||
static void jsB_decodeURI(js_State *J)
|
||||
{
|
||||
Decode(J, js_tostring(J, 1), URIRESERVED "#");
|
||||
}
|
||||
|
||||
static void jsB_decodeURIComponent(js_State *J)
|
||||
{
|
||||
Decode(J, js_tostring(J, 1), "");
|
||||
}
|
||||
|
||||
static void jsB_encodeURI(js_State *J)
|
||||
{
|
||||
Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
|
||||
}
|
||||
|
||||
static void jsB_encodeURIComponent(js_State *J)
|
||||
{
|
||||
Encode(J, js_tostring(J, 1), URIUNESCAPED);
|
||||
}
|
||||
|
||||
void jsB_init(js_State *J)
|
||||
{
|
||||
/* Create the prototype objects here, before the constructors */
|
||||
J->Object_prototype = jsV_newobject(J, JS_COBJECT, NULL);
|
||||
J->Array_prototype = jsV_newobject(J, JS_CARRAY, J->Object_prototype);
|
||||
J->Function_prototype = jsV_newobject(J, JS_CCFUNCTION, J->Object_prototype);
|
||||
J->Boolean_prototype = jsV_newobject(J, JS_CBOOLEAN, J->Object_prototype);
|
||||
J->Number_prototype = jsV_newobject(J, JS_CNUMBER, J->Object_prototype);
|
||||
J->String_prototype = jsV_newobject(J, JS_CSTRING, J->Object_prototype);
|
||||
J->RegExp_prototype = jsV_newobject(J, JS_COBJECT, J->Object_prototype);
|
||||
J->Date_prototype = jsV_newobject(J, JS_CDATE, J->Object_prototype);
|
||||
|
||||
/* All the native error types */
|
||||
J->Error_prototype = jsV_newobject(J, JS_CERROR, J->Object_prototype);
|
||||
J->EvalError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
|
||||
J->RangeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
|
||||
J->ReferenceError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
|
||||
J->SyntaxError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
|
||||
J->TypeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
|
||||
J->URIError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
|
||||
|
||||
/* Create the constructors and fill out the prototype objects */
|
||||
jsB_initobject(J);
|
||||
jsB_initarray(J);
|
||||
jsB_initfunction(J);
|
||||
jsB_initboolean(J);
|
||||
jsB_initnumber(J);
|
||||
jsB_initstring(J);
|
||||
jsB_initregexp(J);
|
||||
jsB_initdate(J);
|
||||
jsB_initerror(J);
|
||||
jsB_initmath(J);
|
||||
jsB_initjson(J);
|
||||
|
||||
/* Initialize the global object */
|
||||
js_pushnumber(J, NAN);
|
||||
js_defglobal(J, "NaN", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
|
||||
js_pushnumber(J, INFINITY);
|
||||
js_defglobal(J, "Infinity", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
|
||||
js_pushundefined(J);
|
||||
js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
|
||||
jsB_globalf(J, "parseInt", jsB_parseInt, 1);
|
||||
jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
|
||||
jsB_globalf(J, "isNaN", jsB_isNaN, 1);
|
||||
jsB_globalf(J, "isFinite", jsB_isFinite, 1);
|
||||
|
||||
jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
|
||||
jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
|
||||
jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
|
||||
jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#ifndef js_builtin_h
|
||||
#define js_builtin_h
|
||||
|
||||
void jsB_init(js_State *J);
|
||||
void jsB_initobject(js_State *J);
|
||||
void jsB_initarray(js_State *J);
|
||||
void jsB_initfunction(js_State *J);
|
||||
void jsB_initboolean(js_State *J);
|
||||
void jsB_initnumber(js_State *J);
|
||||
void jsB_initstring(js_State *J);
|
||||
void jsB_initregexp(js_State *J);
|
||||
void jsB_initerror(js_State *J);
|
||||
void jsB_initmath(js_State *J);
|
||||
void jsB_initjson(js_State *J);
|
||||
void jsB_initdate(js_State *J);
|
||||
|
||||
void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n);
|
||||
void jsB_propn(js_State *J, const char *name, double number);
|
||||
void jsB_props(js_State *J, const char *name, const char *string);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,146 +0,0 @@
|
||||
#ifndef js_compile_h
|
||||
#define js_compile_h
|
||||
|
||||
enum js_OpCode
|
||||
{
|
||||
OP_POP, /* A -- */
|
||||
OP_DUP, /* A -- A A */
|
||||
OP_DUP2, /* A B -- A B A B */
|
||||
OP_ROT2, /* A B -- B A */
|
||||
OP_ROT3, /* A B C -- C A B */
|
||||
OP_ROT4, /* A B C D -- D A B C */
|
||||
|
||||
OP_INTEGER, /* -K- (number-32768) */
|
||||
OP_NUMBER, /* -N- <number> */
|
||||
OP_STRING, /* -S- <string> */
|
||||
OP_CLOSURE, /* -F- <closure> */
|
||||
|
||||
OP_NEWARRAY,
|
||||
OP_NEWOBJECT,
|
||||
OP_NEWREGEXP, /* -S,opts- <regexp> */
|
||||
|
||||
OP_UNDEF,
|
||||
OP_NULL,
|
||||
OP_TRUE,
|
||||
OP_FALSE,
|
||||
|
||||
OP_THIS,
|
||||
OP_CURRENT, /* currently executing function object */
|
||||
|
||||
OP_GETLOCAL, /* -K- <value> */
|
||||
OP_SETLOCAL, /* <value> -K- <value> */
|
||||
OP_DELLOCAL, /* -K- false */
|
||||
|
||||
OP_HASVAR, /* -S- ( <value> | undefined ) */
|
||||
OP_GETVAR, /* -S- <value> */
|
||||
OP_SETVAR, /* <value> -S- <value> */
|
||||
OP_DELVAR, /* -S- <success> */
|
||||
|
||||
OP_IN, /* <name> <obj> -- <exists?> */
|
||||
|
||||
OP_INITPROP, /* <obj> <key> <val> -- <obj> */
|
||||
OP_INITGETTER, /* <obj> <key> <closure> -- <obj> */
|
||||
OP_INITSETTER, /* <obj> <key> <closure> -- <obj> */
|
||||
|
||||
OP_GETPROP, /* <obj> <name> -- <value> */
|
||||
OP_GETPROP_S, /* <obj> -S- <value> */
|
||||
OP_SETPROP, /* <obj> <name> <value> -- <value> */
|
||||
OP_SETPROP_S, /* <obj> <value> -S- <value> */
|
||||
OP_DELPROP, /* <obj> <name> -- <success> */
|
||||
OP_DELPROP_S, /* <obj> -S- <success> */
|
||||
|
||||
OP_ITERATOR, /* <obj> -- <iobj> */
|
||||
OP_NEXTITER, /* <iobj> -- ( <iobj> <name> true | false ) */
|
||||
|
||||
OP_EVAL, /* <args...> -(numargs)- <returnvalue> */
|
||||
OP_CALL, /* <closure> <this> <args...> -(numargs)- <returnvalue> */
|
||||
OP_NEW, /* <closure> <args...> -(numargs)- <returnvalue> */
|
||||
|
||||
OP_TYPEOF,
|
||||
OP_POS,
|
||||
OP_NEG,
|
||||
OP_BITNOT,
|
||||
OP_LOGNOT,
|
||||
OP_INC, /* <x> -- ToNumber(x)+1 */
|
||||
OP_DEC, /* <x> -- ToNumber(x)-1 */
|
||||
OP_POSTINC, /* <x> -- ToNumber(x)+1 ToNumber(x) */
|
||||
OP_POSTDEC, /* <x> -- ToNumber(x)-1 ToNumber(x) */
|
||||
|
||||
OP_MUL,
|
||||
OP_DIV,
|
||||
OP_MOD,
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_SHL,
|
||||
OP_SHR,
|
||||
OP_USHR,
|
||||
OP_LT,
|
||||
OP_GT,
|
||||
OP_LE,
|
||||
OP_GE,
|
||||
OP_EQ,
|
||||
OP_NE,
|
||||
OP_STRICTEQ,
|
||||
OP_STRICTNE,
|
||||
OP_JCASE,
|
||||
OP_BITAND,
|
||||
OP_BITXOR,
|
||||
OP_BITOR,
|
||||
|
||||
OP_INSTANCEOF,
|
||||
|
||||
OP_THROW,
|
||||
|
||||
OP_TRY, /* -ADDR- /jump/ or -ADDR- <exception> */
|
||||
OP_ENDTRY,
|
||||
|
||||
OP_CATCH, /* push scope chain with exception variable */
|
||||
OP_ENDCATCH,
|
||||
|
||||
OP_WITH,
|
||||
OP_ENDWITH,
|
||||
|
||||
OP_DEBUGGER,
|
||||
OP_JUMP,
|
||||
OP_JTRUE,
|
||||
OP_JFALSE,
|
||||
OP_RETURN,
|
||||
};
|
||||
|
||||
struct js_Function
|
||||
{
|
||||
const char *name;
|
||||
int script;
|
||||
int lightweight;
|
||||
int strict;
|
||||
int arguments;
|
||||
int numparams;
|
||||
|
||||
js_Instruction *code;
|
||||
int codecap, codelen;
|
||||
|
||||
js_Function **funtab;
|
||||
int funcap, funlen;
|
||||
|
||||
double *numtab;
|
||||
int numcap, numlen;
|
||||
|
||||
const char **strtab;
|
||||
int strcap, strlen;
|
||||
|
||||
const char **vartab;
|
||||
int varcap, varlen;
|
||||
|
||||
const char *filename;
|
||||
int line, lastline;
|
||||
|
||||
js_Function *gcnext;
|
||||
int gcmark;
|
||||
};
|
||||
|
||||
js_Function *jsC_compilefunction(js_State *J, js_Ast *prog);
|
||||
js_Function *jsC_compilescript(js_State *J, js_Ast *prog, int default_strict);
|
||||
const char *jsC_opcodestring(enum js_OpCode opcode);
|
||||
void jsC_dumpfunction(js_State *J, js_Function *fun);
|
||||
|
||||
#endif
|
@ -1,812 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
#include <sys/time.h>
|
||||
#elif defined(_WIN32)
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#define js_optnumber(J,I,V) (js_isdefined(J,I) ? js_tonumber(J,I) : V)
|
||||
|
||||
static double Now(void)
|
||||
{
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return floor(tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0);
|
||||
#elif defined(_WIN32)
|
||||
struct _timeb tv;
|
||||
_ftime(&tv);
|
||||
return tv.time * 1000.0 + tv.millitm;
|
||||
#else
|
||||
return time(NULL) * 1000.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static double LocalTZA(void)
|
||||
{
|
||||
static int once = 1;
|
||||
static double tza = 0;
|
||||
if (once) {
|
||||
time_t now = time(NULL);
|
||||
time_t utc = mktime(gmtime(&now));
|
||||
time_t loc = mktime(localtime(&now));
|
||||
tza = (loc - utc) * 1000;
|
||||
once = 0;
|
||||
}
|
||||
return tza;
|
||||
}
|
||||
|
||||
static double DaylightSavingTA(double t)
|
||||
{
|
||||
return 0; /* TODO */
|
||||
}
|
||||
|
||||
/* Helpers from the ECMA 262 specification */
|
||||
|
||||
#define HoursPerDay 24.0
|
||||
#define MinutesPerDay (HoursPerDay * MinutesPerHour)
|
||||
#define MinutesPerHour 60.0
|
||||
#define SecondsPerDay (MinutesPerDay * SecondsPerMinute)
|
||||
#define SecondsPerHour (MinutesPerHour * SecondsPerMinute)
|
||||
#define SecondsPerMinute 60.0
|
||||
|
||||
#define msPerDay (SecondsPerDay * msPerSecond)
|
||||
#define msPerHour (SecondsPerHour * msPerSecond)
|
||||
#define msPerMinute (SecondsPerMinute * msPerSecond)
|
||||
#define msPerSecond 1000.0
|
||||
|
||||
static double pmod(double x, double y)
|
||||
{
|
||||
x = fmod(x, y);
|
||||
if (x < 0)
|
||||
x += y;
|
||||
return x;
|
||||
}
|
||||
|
||||
static int Day(double t)
|
||||
{
|
||||
return floor(t / msPerDay);
|
||||
}
|
||||
|
||||
static double TimeWithinDay(double t)
|
||||
{
|
||||
return pmod(t, msPerDay);
|
||||
}
|
||||
|
||||
static int DaysInYear(int y)
|
||||
{
|
||||
return y % 4 == 0 && (y % 100 || (y % 400 == 0)) ? 366 : 365;
|
||||
}
|
||||
|
||||
static int DayFromYear(int y)
|
||||
{
|
||||
return 365 * (y - 1970) +
|
||||
floor((y - 1969) / 4.0) -
|
||||
floor((y - 1901) / 100.0) +
|
||||
floor((y - 1601) / 400.0);
|
||||
}
|
||||
|
||||
static double TimeFromYear(int y)
|
||||
{
|
||||
return DayFromYear(y) * msPerDay;
|
||||
}
|
||||
|
||||
static int YearFromTime(double t)
|
||||
{
|
||||
int y = floor(t / (msPerDay * 365.2425)) + 1970;
|
||||
double t2 = TimeFromYear(y);
|
||||
if (t2 > t)
|
||||
--y;
|
||||
else if (t2 + msPerDay * DaysInYear(y) <= t)
|
||||
++y;
|
||||
return y;
|
||||
}
|
||||
|
||||
static int InLeapYear(double t)
|
||||
{
|
||||
return DaysInYear(YearFromTime(t)) == 366;
|
||||
}
|
||||
|
||||
static int DayWithinYear(double t)
|
||||
{
|
||||
return Day(t) - DayFromYear(YearFromTime(t));
|
||||
}
|
||||
|
||||
static int MonthFromTime(double t)
|
||||
{
|
||||
int day = DayWithinYear(t);
|
||||
int leap = InLeapYear(t);
|
||||
if (day < 31) return 0;
|
||||
if (day < 59 + leap) return 1;
|
||||
if (day < 90 + leap) return 2;
|
||||
if (day < 120 + leap) return 3;
|
||||
if (day < 151 + leap) return 4;
|
||||
if (day < 181 + leap) return 5;
|
||||
if (day < 212 + leap) return 6;
|
||||
if (day < 243 + leap) return 7;
|
||||
if (day < 273 + leap) return 8;
|
||||
if (day < 304 + leap) return 9;
|
||||
if (day < 334 + leap) return 10;
|
||||
return 11;
|
||||
}
|
||||
|
||||
static int DateFromTime(double t)
|
||||
{
|
||||
int day = DayWithinYear(t);
|
||||
int leap = InLeapYear(t);
|
||||
switch (MonthFromTime(t)) {
|
||||
case 0: return day + 1;
|
||||
case 1: return day - 30;
|
||||
case 2: return day - 58 - leap;
|
||||
case 3: return day - 89 - leap;
|
||||
case 4: return day - 119 - leap;
|
||||
case 5: return day - 150 - leap;
|
||||
case 6: return day - 180 - leap;
|
||||
case 7: return day - 211 - leap;
|
||||
case 8: return day - 242 - leap;
|
||||
case 9: return day - 272 - leap;
|
||||
case 10: return day - 303 - leap;
|
||||
default : return day - 333 - leap;
|
||||
}
|
||||
}
|
||||
|
||||
static int WeekDay(double t)
|
||||
{
|
||||
return pmod(Day(t) + 4, 7);
|
||||
}
|
||||
|
||||
static double LocalTime(double utc)
|
||||
{
|
||||
return utc + LocalTZA() + DaylightSavingTA(utc);
|
||||
}
|
||||
|
||||
static double UTC(double loc)
|
||||
{
|
||||
return loc - LocalTZA() - DaylightSavingTA(loc - LocalTZA());
|
||||
}
|
||||
|
||||
static int HourFromTime(double t)
|
||||
{
|
||||
return pmod(floor(t / msPerHour), HoursPerDay);
|
||||
}
|
||||
|
||||
static int MinFromTime(double t)
|
||||
{
|
||||
return pmod(floor(t / msPerMinute), MinutesPerHour);
|
||||
}
|
||||
|
||||
static int SecFromTime(double t)
|
||||
{
|
||||
return pmod(floor(t / msPerSecond), SecondsPerMinute);
|
||||
}
|
||||
|
||||
static int msFromTime(double t)
|
||||
{
|
||||
return pmod(t, msPerSecond);
|
||||
}
|
||||
|
||||
static double MakeTime(double hour, double min, double sec, double ms)
|
||||
{
|
||||
return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms;
|
||||
}
|
||||
|
||||
static double MakeDay(double y, double m, double date)
|
||||
{
|
||||
/*
|
||||
* The following array contains the day of year for the first day of
|
||||
* each month, where index 0 is January, and day 0 is January 1.
|
||||
*/
|
||||
static const double firstDayOfMonth[2][12] = {
|
||||
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
|
||||
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
|
||||
};
|
||||
|
||||
double yd, md;
|
||||
int im;
|
||||
|
||||
y += floor(m / 12);
|
||||
m = pmod(m, 12);
|
||||
|
||||
im = (int)m;
|
||||
if (im < 0 || im >= 12)
|
||||
return NAN;
|
||||
|
||||
yd = floor(TimeFromYear(y) / msPerDay);
|
||||
md = firstDayOfMonth[DaysInYear(y) == 366][im];
|
||||
|
||||
return yd + md + date - 1;
|
||||
}
|
||||
|
||||
static double MakeDate(double day, double time)
|
||||
{
|
||||
return day * msPerDay + time;
|
||||
}
|
||||
|
||||
static double TimeClip(double t)
|
||||
{
|
||||
if (!isfinite(t))
|
||||
return NAN;
|
||||
if (fabs(t) > 8.64e15)
|
||||
return NAN;
|
||||
return t < 0 ? -floor(-t) : floor(t);
|
||||
}
|
||||
|
||||
static int toint(const char **sp, int w, int *v)
|
||||
{
|
||||
const char *s = *sp;
|
||||
*v = 0;
|
||||
while (w--) {
|
||||
if (*s < '0' || *s > '9')
|
||||
return 0;
|
||||
*v = *v * 10 + (*s++ - '0');
|
||||
}
|
||||
*sp = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static double parseDateTime(const char *s)
|
||||
{
|
||||
int y = 1970, m = 1, d = 1, H = 0, M = 0, S = 0, ms = 0;
|
||||
int tza = 0;
|
||||
double t;
|
||||
|
||||
/* Parse ISO 8601 formatted date and time: */
|
||||
/* YYYY("-"MM("-"DD)?)?("T"HH":"mm(":"ss("."sss)?)?("Z"|[+-]HH(":"mm)?)?)? */
|
||||
|
||||
if (!toint(&s, 4, &y)) return NAN;
|
||||
if (*s == '-') {
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &m)) return NAN;
|
||||
if (*s == '-') {
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &d)) return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
if (*s == 'T') {
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &H)) return NAN;
|
||||
if (*s != ':') return NAN;
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &M)) return NAN;
|
||||
if (*s == ':') {
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &S)) return NAN;
|
||||
if (*s == '.') {
|
||||
s += 1;
|
||||
if (!toint(&s, 3, &ms)) return NAN;
|
||||
}
|
||||
}
|
||||
if (*s == 'Z') {
|
||||
s += 1;
|
||||
tza = 0;
|
||||
} else if (*s == '+' || *s == '-') {
|
||||
int tzh = 0, tzm = 0;
|
||||
int tzs = *s == '+' ? 1 : -1;
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &tzh)) return NAN;
|
||||
if (*s == ':') {
|
||||
s += 1;
|
||||
if (!toint(&s, 2, &tzm)) return NAN;
|
||||
}
|
||||
if (tzh > 23 || tzm > 59) return NAN;
|
||||
tza = tzs * (tzh * msPerHour + tzm * msPerMinute);
|
||||
} else {
|
||||
tza = LocalTZA();
|
||||
}
|
||||
}
|
||||
|
||||
if (*s) return NAN;
|
||||
|
||||
if (m < 1 || m > 12) return NAN;
|
||||
if (d < 1 || d > 31) return NAN;
|
||||
if (H < 0 || H > 24) return NAN;
|
||||
if (M < 0 || M > 59) return NAN;
|
||||
if (S < 0 || S > 59) return NAN;
|
||||
if (ms < 0 || ms > 999) return NAN;
|
||||
if (H == 24 && (M != 0 || S != 0 || ms != 0)) return NAN;
|
||||
|
||||
/* TODO: DaylightSavingTA on local times */
|
||||
t = MakeDate(MakeDay(y, m-1, d), MakeTime(H, M, S, ms));
|
||||
return t - tza;
|
||||
}
|
||||
|
||||
/* date formatting */
|
||||
|
||||
static char *fmtdate(char *buf, double t)
|
||||
{
|
||||
int y = YearFromTime(t);
|
||||
int m = MonthFromTime(t);
|
||||
int d = DateFromTime(t);
|
||||
if (!isfinite(t))
|
||||
return "Invalid Date";
|
||||
sprintf(buf, "%04d-%02d-%02d", y, m+1, d);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *fmttime(char *buf, double t, double tza)
|
||||
{
|
||||
int H = HourFromTime(t);
|
||||
int M = MinFromTime(t);
|
||||
int S = SecFromTime(t);
|
||||
int ms = msFromTime(t);
|
||||
int tzh = HourFromTime(fabs(tza));
|
||||
int tzm = MinFromTime(fabs(tza));
|
||||
if (!isfinite(t))
|
||||
return "Invalid Date";
|
||||
if (tza == 0)
|
||||
sprintf(buf, "%02d:%02d:%02d.%03dZ", H, M, S, ms);
|
||||
else if (tza < 0)
|
||||
sprintf(buf, "%02d:%02d:%02d.%03d-%02d:%02d", H, M, S, ms, tzh, tzm);
|
||||
else
|
||||
sprintf(buf, "%02d:%02d:%02d.%03d+%02d:%02d", H, M, S, ms, tzh, tzm);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *fmtdatetime(char *buf, double t, double tza)
|
||||
{
|
||||
char dbuf[20], tbuf[20];
|
||||
if (!isfinite(t))
|
||||
return "Invalid Date";
|
||||
fmtdate(dbuf, t);
|
||||
fmttime(tbuf, t, tza);
|
||||
sprintf(buf, "%sT%s", dbuf, tbuf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Date functions */
|
||||
|
||||
static double js_todate(js_State *J, int idx)
|
||||
{
|
||||
js_Object *self = js_toobject(J, idx);
|
||||
if (self->type != JS_CDATE)
|
||||
js_typeerror(J, "not a date");
|
||||
return self->u.number;
|
||||
}
|
||||
|
||||
static void js_setdate(js_State *J, int idx, double t)
|
||||
{
|
||||
js_Object *self = js_toobject(J, idx);
|
||||
if (self->type != JS_CDATE)
|
||||
js_typeerror(J, "not a date");
|
||||
self->u.number = TimeClip(t);
|
||||
js_pushnumber(J, self->u.number);
|
||||
}
|
||||
|
||||
static void D_parse(js_State *J)
|
||||
{
|
||||
double t = parseDateTime(js_tostring(J, 1));
|
||||
js_pushnumber(J, t);
|
||||
}
|
||||
|
||||
static void D_UTC(js_State *J)
|
||||
{
|
||||
double y, m, d, H, M, S, ms, t;
|
||||
y = js_tonumber(J, 1);
|
||||
if (y < 100) y += 1900;
|
||||
m = js_tonumber(J, 2);
|
||||
d = js_optnumber(J, 3, 1);
|
||||
H = js_optnumber(J, 4, 0);
|
||||
M = js_optnumber(J, 5, 0);
|
||||
S = js_optnumber(J, 6, 0);
|
||||
ms = js_optnumber(J, 7, 0);
|
||||
t = MakeDate(MakeDay(y, m, d), MakeTime(H, M, S, ms));
|
||||
t = TimeClip(t);
|
||||
js_pushnumber(J, t);
|
||||
}
|
||||
|
||||
static void D_now(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, Now());
|
||||
}
|
||||
|
||||
static void jsB_Date(js_State *J)
|
||||
{
|
||||
char buf[64];
|
||||
js_pushstring(J, fmtdatetime(buf, LocalTime(Now()), LocalTZA()));
|
||||
}
|
||||
|
||||
static void jsB_new_Date(js_State *J)
|
||||
{
|
||||
int top = js_gettop(J);
|
||||
js_Object *obj;
|
||||
double t;
|
||||
|
||||
if (top == 1)
|
||||
t = Now();
|
||||
else if (top == 2) {
|
||||
js_toprimitive(J, 1, JS_HNONE);
|
||||
if (js_isstring(J, 1))
|
||||
t = parseDateTime(js_tostring(J, 1));
|
||||
else
|
||||
t = TimeClip(js_tonumber(J, 1));
|
||||
} else {
|
||||
double y, m, d, H, M, S, ms;
|
||||
y = js_tonumber(J, 1);
|
||||
if (y < 100) y += 1900;
|
||||
m = js_tonumber(J, 2);
|
||||
d = js_optnumber(J, 3, 1);
|
||||
H = js_optnumber(J, 4, 0);
|
||||
M = js_optnumber(J, 5, 0);
|
||||
S = js_optnumber(J, 6, 0);
|
||||
ms = js_optnumber(J, 7, 0);
|
||||
t = MakeDate(MakeDay(y, m, d), MakeTime(H, M, S, ms));
|
||||
t = TimeClip(UTC(t));
|
||||
}
|
||||
|
||||
obj = jsV_newobject(J, JS_CDATE, J->Date_prototype);
|
||||
obj->u.number = t;
|
||||
|
||||
js_pushobject(J, obj);
|
||||
}
|
||||
|
||||
static void Dp_valueOf(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, t);
|
||||
}
|
||||
|
||||
static void Dp_toString(js_State *J)
|
||||
{
|
||||
char buf[64];
|
||||
double t = js_todate(J, 0);
|
||||
js_pushstring(J, fmtdatetime(buf, LocalTime(t), LocalTZA()));
|
||||
}
|
||||
|
||||
static void Dp_toDateString(js_State *J)
|
||||
{
|
||||
char buf[64];
|
||||
double t = js_todate(J, 0);
|
||||
js_pushstring(J, fmtdate(buf, LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_toTimeString(js_State *J)
|
||||
{
|
||||
char buf[64];
|
||||
double t = js_todate(J, 0);
|
||||
js_pushstring(J, fmttime(buf, LocalTime(t), LocalTZA()));
|
||||
}
|
||||
|
||||
static void Dp_toUTCString(js_State *J)
|
||||
{
|
||||
char buf[64];
|
||||
double t = js_todate(J, 0);
|
||||
js_pushstring(J, fmtdatetime(buf, t, 0));
|
||||
}
|
||||
|
||||
static void Dp_toISOString(js_State *J)
|
||||
{
|
||||
char buf[64];
|
||||
double t = js_todate(J, 0);
|
||||
if (!isfinite(t))
|
||||
js_rangeerror(J, "invalid date");
|
||||
js_pushstring(J, fmtdatetime(buf, t, 0));
|
||||
}
|
||||
|
||||
static void Dp_getFullYear(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, YearFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getMonth(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, MonthFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getDate(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, DateFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getDay(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, WeekDay(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getHours(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, HourFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getMinutes(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, MinFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getSeconds(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, SecFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getMilliseconds(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, msFromTime(LocalTime(t)));
|
||||
}
|
||||
|
||||
static void Dp_getUTCFullYear(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, YearFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCMonth(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, MonthFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCDate(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, DateFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCDay(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, WeekDay(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCHours(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, HourFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCMinutes(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, MinFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCSeconds(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, SecFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getUTCMilliseconds(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, msFromTime(t));
|
||||
}
|
||||
|
||||
static void Dp_getTimezoneOffset(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
js_pushnumber(J, (t - LocalTime(t)) / msPerMinute);
|
||||
}
|
||||
|
||||
static void Dp_setTime(js_State *J)
|
||||
{
|
||||
js_setdate(J, 0, js_tonumber(J, 1));
|
||||
}
|
||||
|
||||
static void Dp_setMilliseconds(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double h = HourFromTime(t);
|
||||
double m = MinFromTime(t);
|
||||
double s = SecFromTime(t);
|
||||
double ms = js_tonumber(J, 1);
|
||||
js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
|
||||
}
|
||||
|
||||
static void Dp_setSeconds(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double h = HourFromTime(t);
|
||||
double m = MinFromTime(t);
|
||||
double s = js_tonumber(J, 1);
|
||||
double ms = js_optnumber(J, 2, msFromTime(t));
|
||||
js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
|
||||
}
|
||||
|
||||
static void Dp_setMinutes(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double h = HourFromTime(t);
|
||||
double m = js_tonumber(J, 1);
|
||||
double s = js_optnumber(J, 2, SecFromTime(t));
|
||||
double ms = js_optnumber(J, 3, msFromTime(t));
|
||||
js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
|
||||
}
|
||||
|
||||
static void Dp_setHours(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double h = js_tonumber(J, 1);
|
||||
double m = js_optnumber(J, 2, MinFromTime(t));
|
||||
double s = js_optnumber(J, 3, SecFromTime(t));
|
||||
double ms = js_optnumber(J, 4, msFromTime(t));
|
||||
js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
|
||||
}
|
||||
|
||||
static void Dp_setDate(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double y = YearFromTime(t);
|
||||
double m = MonthFromTime(t);
|
||||
double d = js_tonumber(J, 1);
|
||||
js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
|
||||
}
|
||||
|
||||
static void Dp_setMonth(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double y = YearFromTime(t);
|
||||
double m = js_tonumber(J, 1);
|
||||
double d = js_optnumber(J, 2, DateFromTime(t));
|
||||
js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
|
||||
}
|
||||
|
||||
static void Dp_setFullYear(js_State *J)
|
||||
{
|
||||
double t = LocalTime(js_todate(J, 0));
|
||||
double y = js_tonumber(J, 1);
|
||||
double m = js_optnumber(J, 2, MonthFromTime(t));
|
||||
double d = js_optnumber(J, 3, DateFromTime(t));
|
||||
js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
|
||||
}
|
||||
|
||||
static void Dp_setUTCMilliseconds(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double h = HourFromTime(t);
|
||||
double m = MinFromTime(t);
|
||||
double s = SecFromTime(t);
|
||||
double ms = js_tonumber(J, 1);
|
||||
js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
|
||||
}
|
||||
|
||||
static void Dp_setUTCSeconds(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double h = HourFromTime(t);
|
||||
double m = MinFromTime(t);
|
||||
double s = js_tonumber(J, 1);
|
||||
double ms = js_optnumber(J, 2, msFromTime(t));
|
||||
js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
|
||||
}
|
||||
|
||||
static void Dp_setUTCMinutes(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double h = HourFromTime(t);
|
||||
double m = js_tonumber(J, 1);
|
||||
double s = js_optnumber(J, 2, SecFromTime(t));
|
||||
double ms = js_optnumber(J, 3, msFromTime(t));
|
||||
js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
|
||||
}
|
||||
|
||||
static void Dp_setUTCHours(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double h = js_tonumber(J, 1);
|
||||
double m = js_optnumber(J, 2, HourFromTime(t));
|
||||
double s = js_optnumber(J, 3, SecFromTime(t));
|
||||
double ms = js_optnumber(J, 4, msFromTime(t));
|
||||
js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
|
||||
}
|
||||
|
||||
static void Dp_setUTCDate(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double y = YearFromTime(t);
|
||||
double m = MonthFromTime(t);
|
||||
double d = js_tonumber(J, 1);
|
||||
js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
|
||||
}
|
||||
|
||||
static void Dp_setUTCMonth(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double y = YearFromTime(t);
|
||||
double m = js_tonumber(J, 1);
|
||||
double d = js_optnumber(J, 2, DateFromTime(t));
|
||||
js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
|
||||
}
|
||||
|
||||
static void Dp_setUTCFullYear(js_State *J)
|
||||
{
|
||||
double t = js_todate(J, 0);
|
||||
double y = js_tonumber(J, 1);
|
||||
double m = js_optnumber(J, 2, MonthFromTime(t));
|
||||
double d = js_optnumber(J, 3, DateFromTime(t));
|
||||
js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
|
||||
}
|
||||
|
||||
static void Dp_toJSON(js_State *J)
|
||||
{
|
||||
js_copy(J, 0);
|
||||
js_toprimitive(J, -1, JS_HNUMBER);
|
||||
if (js_isnumber(J, -1) && !isfinite(js_tonumber(J, -1))) {
|
||||
js_pushnull(J);
|
||||
return;
|
||||
}
|
||||
js_pop(J, 1);
|
||||
|
||||
js_getproperty(J, 0, "toISOString");
|
||||
if (!js_iscallable(J, -1))
|
||||
js_typeerror(J, "this.toISOString is not a function");
|
||||
js_copy(J, 0);
|
||||
js_call(J, 0);
|
||||
}
|
||||
|
||||
void jsB_initdate(js_State *J)
|
||||
{
|
||||
J->Date_prototype->u.number = 0;
|
||||
|
||||
js_pushobject(J, J->Date_prototype);
|
||||
{
|
||||
jsB_propf(J, "Date.prototype.valueOf", Dp_valueOf, 0);
|
||||
jsB_propf(J, "Date.prototype.toString", Dp_toString, 0);
|
||||
jsB_propf(J, "Date.prototype.toDateString", Dp_toDateString, 0);
|
||||
jsB_propf(J, "Date.prototype.toTimeString", Dp_toTimeString, 0);
|
||||
jsB_propf(J, "Date.prototype.toLocaleString", Dp_toString, 0);
|
||||
jsB_propf(J, "Date.prototype.toLocaleDateString", Dp_toDateString, 0);
|
||||
jsB_propf(J, "Date.prototype.toLocaleTimeString", Dp_toTimeString, 0);
|
||||
jsB_propf(J, "Date.prototype.toUTCString", Dp_toUTCString, 0);
|
||||
|
||||
jsB_propf(J, "Date.prototype.getTime", Dp_valueOf, 0);
|
||||
jsB_propf(J, "Date.prototype.getFullYear", Dp_getFullYear, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCFullYear", Dp_getUTCFullYear, 0);
|
||||
jsB_propf(J, "Date.prototype.getMonth", Dp_getMonth, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCMonth", Dp_getUTCMonth, 0);
|
||||
jsB_propf(J, "Date.prototype.getDate", Dp_getDate, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCDate", Dp_getUTCDate, 0);
|
||||
jsB_propf(J, "Date.prototype.getDay", Dp_getDay, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCDay", Dp_getUTCDay, 0);
|
||||
jsB_propf(J, "Date.prototype.getHours", Dp_getHours, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCHours", Dp_getUTCHours, 0);
|
||||
jsB_propf(J, "Date.prototype.getMinutes", Dp_getMinutes, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCMinutes", Dp_getUTCMinutes, 0);
|
||||
jsB_propf(J, "Date.prototype.getSeconds", Dp_getSeconds, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCSeconds", Dp_getUTCSeconds, 0);
|
||||
jsB_propf(J, "Date.prototype.getMilliseconds", Dp_getMilliseconds, 0);
|
||||
jsB_propf(J, "Date.prototype.getUTCMilliseconds", Dp_getUTCMilliseconds, 0);
|
||||
jsB_propf(J, "Date.prototype.getTimezoneOffset", Dp_getTimezoneOffset, 0);
|
||||
|
||||
jsB_propf(J, "Date.prototype.setTime", Dp_setTime, 1);
|
||||
jsB_propf(J, "Date.prototype.setMilliseconds", Dp_setMilliseconds, 1);
|
||||
jsB_propf(J, "Date.prototype.setUTCMilliseconds", Dp_setUTCMilliseconds, 1);
|
||||
jsB_propf(J, "Date.prototype.setSeconds", Dp_setSeconds, 2);
|
||||
jsB_propf(J, "Date.prototype.setUTCSeconds", Dp_setUTCSeconds, 2);
|
||||
jsB_propf(J, "Date.prototype.setMinutes", Dp_setMinutes, 3);
|
||||
jsB_propf(J, "Date.prototype.setUTCMinutes", Dp_setUTCMinutes, 3);
|
||||
jsB_propf(J, "Date.prototype.setHours", Dp_setHours, 4);
|
||||
jsB_propf(J, "Date.prototype.setUTCHours", Dp_setUTCHours, 4);
|
||||
jsB_propf(J, "Date.prototype.setDate", Dp_setDate, 1);
|
||||
jsB_propf(J, "Date.prototype.setUTCDate", Dp_setUTCDate, 1);
|
||||
jsB_propf(J, "Date.prototype.setMonth", Dp_setMonth, 2);
|
||||
jsB_propf(J, "Date.prototype.setUTCMonth", Dp_setUTCMonth, 2);
|
||||
jsB_propf(J, "Date.prototype.setFullYear", Dp_setFullYear, 3);
|
||||
jsB_propf(J, "Date.prototype.setUTCFullYear", Dp_setUTCFullYear, 3);
|
||||
|
||||
/* ES5 */
|
||||
jsB_propf(J, "Date.prototype.toISOString", Dp_toISOString, 0);
|
||||
jsB_propf(J, "Date.prototype.toJSON", Dp_toJSON, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Date, jsB_new_Date, "Date", 0); /* 1 */
|
||||
{
|
||||
jsB_propf(J, "Date.parse", D_parse, 1);
|
||||
jsB_propf(J, "Date.UTC", D_UTC, 7);
|
||||
|
||||
/* ES5 */
|
||||
jsB_propf(J, "Date.now", D_now, 0);
|
||||
}
|
||||
js_defglobal(J, "Date", JS_DONTENUM);
|
||||
}
|
@ -1,747 +0,0 @@
|
||||
/* Locale-independent implementations of string <-> double conversions. */
|
||||
|
||||
#include "jsi.h"
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1700) /* VS2012 has stdint.h */
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* format exponent like sprintf(p, "e%+d", e)
|
||||
*/
|
||||
void
|
||||
js_fmtexp(char *p, int e)
|
||||
{
|
||||
char se[9];
|
||||
int i;
|
||||
|
||||
*p++ = 'e';
|
||||
if(e < 0) {
|
||||
*p++ = '-';
|
||||
e = -e;
|
||||
} else
|
||||
*p++ = '+';
|
||||
i = 0;
|
||||
while(e) {
|
||||
se[i++] = e % 10 + '0';
|
||||
e /= 10;
|
||||
}
|
||||
while(i < 1)
|
||||
se[i++] = '0';
|
||||
while(i > 0)
|
||||
*p++ = se[--i];
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* grisu2_59_56.c
|
||||
*
|
||||
* Grisu prints the optimal decimal representation of floating-point numbers.
|
||||
*
|
||||
* Copyright (c) 2009 Florian Loitsch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
typedef struct diy_fp_t {
|
||||
uint64_t f;
|
||||
int e;
|
||||
} diy_fp_t;
|
||||
|
||||
#define DIY_SIGNIFICAND_SIZE 64
|
||||
#define D_1_LOG2_10 0.30102999566398114 /* 1 / lg(10) */
|
||||
|
||||
static const uint64_t powers_ten[] = {
|
||||
0xbf29dcaba82fdeae, 0xeef453d6923bd65a, 0x9558b4661b6565f8,
|
||||
0xbaaee17fa23ebf76, 0xe95a99df8ace6f54, 0x91d8a02bb6c10594,
|
||||
0xb64ec836a47146fa, 0xe3e27a444d8d98b8, 0x8e6d8c6ab0787f73,
|
||||
0xb208ef855c969f50, 0xde8b2b66b3bc4724, 0x8b16fb203055ac76,
|
||||
0xaddcb9e83c6b1794, 0xd953e8624b85dd79, 0x87d4713d6f33aa6c,
|
||||
0xa9c98d8ccb009506, 0xd43bf0effdc0ba48, 0x84a57695fe98746d,
|
||||
0xa5ced43b7e3e9188, 0xcf42894a5dce35ea, 0x818995ce7aa0e1b2,
|
||||
0xa1ebfb4219491a1f, 0xca66fa129f9b60a7, 0xfd00b897478238d1,
|
||||
0x9e20735e8cb16382, 0xc5a890362fddbc63, 0xf712b443bbd52b7c,
|
||||
0x9a6bb0aa55653b2d, 0xc1069cd4eabe89f9, 0xf148440a256e2c77,
|
||||
0x96cd2a865764dbca, 0xbc807527ed3e12bd, 0xeba09271e88d976c,
|
||||
0x93445b8731587ea3, 0xb8157268fdae9e4c, 0xe61acf033d1a45df,
|
||||
0x8fd0c16206306bac, 0xb3c4f1ba87bc8697, 0xe0b62e2929aba83c,
|
||||
0x8c71dcd9ba0b4926, 0xaf8e5410288e1b6f, 0xdb71e91432b1a24b,
|
||||
0x892731ac9faf056f, 0xab70fe17c79ac6ca, 0xd64d3d9db981787d,
|
||||
0x85f0468293f0eb4e, 0xa76c582338ed2622, 0xd1476e2c07286faa,
|
||||
0x82cca4db847945ca, 0xa37fce126597973d, 0xcc5fc196fefd7d0c,
|
||||
0xff77b1fcbebcdc4f, 0x9faacf3df73609b1, 0xc795830d75038c1e,
|
||||
0xf97ae3d0d2446f25, 0x9becce62836ac577, 0xc2e801fb244576d5,
|
||||
0xf3a20279ed56d48a, 0x9845418c345644d7, 0xbe5691ef416bd60c,
|
||||
0xedec366b11c6cb8f, 0x94b3a202eb1c3f39, 0xb9e08a83a5e34f08,
|
||||
0xe858ad248f5c22ca, 0x91376c36d99995be, 0xb58547448ffffb2e,
|
||||
0xe2e69915b3fff9f9, 0x8dd01fad907ffc3c, 0xb1442798f49ffb4b,
|
||||
0xdd95317f31c7fa1d, 0x8a7d3eef7f1cfc52, 0xad1c8eab5ee43b67,
|
||||
0xd863b256369d4a41, 0x873e4f75e2224e68, 0xa90de3535aaae202,
|
||||
0xd3515c2831559a83, 0x8412d9991ed58092, 0xa5178fff668ae0b6,
|
||||
0xce5d73ff402d98e4, 0x80fa687f881c7f8e, 0xa139029f6a239f72,
|
||||
0xc987434744ac874f, 0xfbe9141915d7a922, 0x9d71ac8fada6c9b5,
|
||||
0xc4ce17b399107c23, 0xf6019da07f549b2b, 0x99c102844f94e0fb,
|
||||
0xc0314325637a193a, 0xf03d93eebc589f88, 0x96267c7535b763b5,
|
||||
0xbbb01b9283253ca3, 0xea9c227723ee8bcb, 0x92a1958a7675175f,
|
||||
0xb749faed14125d37, 0xe51c79a85916f485, 0x8f31cc0937ae58d3,
|
||||
0xb2fe3f0b8599ef08, 0xdfbdcece67006ac9, 0x8bd6a141006042be,
|
||||
0xaecc49914078536d, 0xda7f5bf590966849, 0x888f99797a5e012d,
|
||||
0xaab37fd7d8f58179, 0xd5605fcdcf32e1d7, 0x855c3be0a17fcd26,
|
||||
0xa6b34ad8c9dfc070, 0xd0601d8efc57b08c, 0x823c12795db6ce57,
|
||||
0xa2cb1717b52481ed, 0xcb7ddcdda26da269, 0xfe5d54150b090b03,
|
||||
0x9efa548d26e5a6e2, 0xc6b8e9b0709f109a, 0xf867241c8cc6d4c1,
|
||||
0x9b407691d7fc44f8, 0xc21094364dfb5637, 0xf294b943e17a2bc4,
|
||||
0x979cf3ca6cec5b5b, 0xbd8430bd08277231, 0xece53cec4a314ebe,
|
||||
0x940f4613ae5ed137, 0xb913179899f68584, 0xe757dd7ec07426e5,
|
||||
0x9096ea6f3848984f, 0xb4bca50b065abe63, 0xe1ebce4dc7f16dfc,
|
||||
0x8d3360f09cf6e4bd, 0xb080392cc4349ded, 0xdca04777f541c568,
|
||||
0x89e42caaf9491b61, 0xac5d37d5b79b6239, 0xd77485cb25823ac7,
|
||||
0x86a8d39ef77164bd, 0xa8530886b54dbdec, 0xd267caa862a12d67,
|
||||
0x8380dea93da4bc60, 0xa46116538d0deb78, 0xcd795be870516656,
|
||||
0x806bd9714632dff6, 0xa086cfcd97bf97f4, 0xc8a883c0fdaf7df0,
|
||||
0xfad2a4b13d1b5d6c, 0x9cc3a6eec6311a64, 0xc3f490aa77bd60fd,
|
||||
0xf4f1b4d515acb93c, 0x991711052d8bf3c5, 0xbf5cd54678eef0b7,
|
||||
0xef340a98172aace5, 0x9580869f0e7aac0f, 0xbae0a846d2195713,
|
||||
0xe998d258869facd7, 0x91ff83775423cc06, 0xb67f6455292cbf08,
|
||||
0xe41f3d6a7377eeca, 0x8e938662882af53e, 0xb23867fb2a35b28e,
|
||||
0xdec681f9f4c31f31, 0x8b3c113c38f9f37f, 0xae0b158b4738705f,
|
||||
0xd98ddaee19068c76, 0x87f8a8d4cfa417ca, 0xa9f6d30a038d1dbc,
|
||||
0xd47487cc8470652b, 0x84c8d4dfd2c63f3b, 0xa5fb0a17c777cf0a,
|
||||
0xcf79cc9db955c2cc, 0x81ac1fe293d599c0, 0xa21727db38cb0030,
|
||||
0xca9cf1d206fdc03c, 0xfd442e4688bd304b, 0x9e4a9cec15763e2f,
|
||||
0xc5dd44271ad3cdba, 0xf7549530e188c129, 0x9a94dd3e8cf578ba,
|
||||
0xc13a148e3032d6e8, 0xf18899b1bc3f8ca2, 0x96f5600f15a7b7e5,
|
||||
0xbcb2b812db11a5de, 0xebdf661791d60f56, 0x936b9fcebb25c996,
|
||||
0xb84687c269ef3bfb, 0xe65829b3046b0afa, 0x8ff71a0fe2c2e6dc,
|
||||
0xb3f4e093db73a093, 0xe0f218b8d25088b8, 0x8c974f7383725573,
|
||||
0xafbd2350644eead0, 0xdbac6c247d62a584, 0x894bc396ce5da772,
|
||||
0xab9eb47c81f5114f, 0xd686619ba27255a3, 0x8613fd0145877586,
|
||||
0xa798fc4196e952e7, 0xd17f3b51fca3a7a1, 0x82ef85133de648c5,
|
||||
0xa3ab66580d5fdaf6, 0xcc963fee10b7d1b3, 0xffbbcfe994e5c620,
|
||||
0x9fd561f1fd0f9bd4, 0xc7caba6e7c5382c9, 0xf9bd690a1b68637b,
|
||||
0x9c1661a651213e2d, 0xc31bfa0fe5698db8, 0xf3e2f893dec3f126,
|
||||
0x986ddb5c6b3a76b8, 0xbe89523386091466, 0xee2ba6c0678b597f,
|
||||
0x94db483840b717f0, 0xba121a4650e4ddec, 0xe896a0d7e51e1566,
|
||||
0x915e2486ef32cd60, 0xb5b5ada8aaff80b8, 0xe3231912d5bf60e6,
|
||||
0x8df5efabc5979c90, 0xb1736b96b6fd83b4, 0xddd0467c64bce4a1,
|
||||
0x8aa22c0dbef60ee4, 0xad4ab7112eb3929e, 0xd89d64d57a607745,
|
||||
0x87625f056c7c4a8b, 0xa93af6c6c79b5d2e, 0xd389b47879823479,
|
||||
0x843610cb4bf160cc, 0xa54394fe1eedb8ff, 0xce947a3da6a9273e,
|
||||
0x811ccc668829b887, 0xa163ff802a3426a9, 0xc9bcff6034c13053,
|
||||
0xfc2c3f3841f17c68, 0x9d9ba7832936edc1, 0xc5029163f384a931,
|
||||
0xf64335bcf065d37d, 0x99ea0196163fa42e, 0xc06481fb9bcf8d3a,
|
||||
0xf07da27a82c37088, 0x964e858c91ba2655, 0xbbe226efb628afeb,
|
||||
0xeadab0aba3b2dbe5, 0x92c8ae6b464fc96f, 0xb77ada0617e3bbcb,
|
||||
0xe55990879ddcaabe, 0x8f57fa54c2a9eab7, 0xb32df8e9f3546564,
|
||||
0xdff9772470297ebd, 0x8bfbea76c619ef36, 0xaefae51477a06b04,
|
||||
0xdab99e59958885c5, 0x88b402f7fd75539b, 0xaae103b5fcd2a882,
|
||||
0xd59944a37c0752a2, 0x857fcae62d8493a5, 0xa6dfbd9fb8e5b88f,
|
||||
0xd097ad07a71f26b2, 0x825ecc24c8737830, 0xa2f67f2dfa90563b,
|
||||
0xcbb41ef979346bca, 0xfea126b7d78186bd, 0x9f24b832e6b0f436,
|
||||
0xc6ede63fa05d3144, 0xf8a95fcf88747d94, 0x9b69dbe1b548ce7d,
|
||||
0xc24452da229b021c, 0xf2d56790ab41c2a3, 0x97c560ba6b0919a6,
|
||||
0xbdb6b8e905cb600f, 0xed246723473e3813, 0x9436c0760c86e30c,
|
||||
0xb94470938fa89bcf, 0xe7958cb87392c2c3, 0x90bd77f3483bb9ba,
|
||||
0xb4ecd5f01a4aa828, 0xe2280b6c20dd5232, 0x8d590723948a535f,
|
||||
0xb0af48ec79ace837, 0xdcdb1b2798182245, 0x8a08f0f8bf0f156b,
|
||||
0xac8b2d36eed2dac6, 0xd7adf884aa879177, 0x86ccbb52ea94baeb,
|
||||
0xa87fea27a539e9a5, 0xd29fe4b18e88640f, 0x83a3eeeef9153e89,
|
||||
0xa48ceaaab75a8e2b, 0xcdb02555653131b6, 0x808e17555f3ebf12,
|
||||
0xa0b19d2ab70e6ed6, 0xc8de047564d20a8c, 0xfb158592be068d2f,
|
||||
0x9ced737bb6c4183d, 0xc428d05aa4751e4d, 0xf53304714d9265e0,
|
||||
0x993fe2c6d07b7fac, 0xbf8fdb78849a5f97, 0xef73d256a5c0f77d,
|
||||
0x95a8637627989aae, 0xbb127c53b17ec159, 0xe9d71b689dde71b0,
|
||||
0x9226712162ab070e, 0xb6b00d69bb55c8d1, 0xe45c10c42a2b3b06,
|
||||
0x8eb98a7a9a5b04e3, 0xb267ed1940f1c61c, 0xdf01e85f912e37a3,
|
||||
0x8b61313bbabce2c6, 0xae397d8aa96c1b78, 0xd9c7dced53c72256,
|
||||
0x881cea14545c7575, 0xaa242499697392d3, 0xd4ad2dbfc3d07788,
|
||||
0x84ec3c97da624ab5, 0xa6274bbdd0fadd62, 0xcfb11ead453994ba,
|
||||
0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3e,
|
||||
0xfd87b5f28300ca0e, 0x9e74d1b791e07e48, 0xc612062576589ddb,
|
||||
0xf79687aed3eec551, 0x9abe14cd44753b53, 0xc16d9a0095928a27,
|
||||
0xf1c90080baf72cb1, 0x971da05074da7bef, 0xbce5086492111aeb,
|
||||
0xec1e4a7db69561a5, 0x9392ee8e921d5d07, 0xb877aa3236a4b449,
|
||||
0xe69594bec44de15b, 0x901d7cf73ab0acd9, 0xb424dc35095cd80f,
|
||||
0xe12e13424bb40e13, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff,
|
||||
0xdbe6fecebdedd5bf, 0x89705f4136b4a597, 0xabcc77118461cefd,
|
||||
0xd6bf94d5e57a42bc, 0x8637bd05af6c69b6, 0xa7c5ac471b478423,
|
||||
0xd1b71758e219652c, 0x83126e978d4fdf3b, 0xa3d70a3d70a3d70a,
|
||||
0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000,
|
||||
0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,
|
||||
0xc350000000000000, 0xf424000000000000, 0x9896800000000000,
|
||||
0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000,
|
||||
0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000,
|
||||
0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,
|
||||
0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000,
|
||||
0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000,
|
||||
0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0,
|
||||
0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984,
|
||||
0xa18f07d736b90be5, 0xc9f2c9cd04674edf, 0xfc6f7c4045812296,
|
||||
0x9dc5ada82b70b59e, 0xc5371912364ce305, 0xf684df56c3e01bc7,
|
||||
0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20,
|
||||
0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd,
|
||||
0x92efd1b8d0cf37be, 0xb7abc627050305ae, 0xe596b7b0c643c719,
|
||||
0x8f7e32ce7bea5c70, 0xb35dbf821ae4f38c, 0xe0352f62a19e306f,
|
||||
0x8c213d9da502de45, 0xaf298d050e4395d7, 0xdaf3f04651d47b4c,
|
||||
0x88d8762bf324cd10, 0xab0e93b6efee0054, 0xd5d238a4abe98068,
|
||||
0x85a36366eb71f041, 0xa70c3c40a64e6c52, 0xd0cf4b50cfe20766,
|
||||
0x82818f1281ed44a0, 0xa321f2d7226895c8, 0xcbea6f8ceb02bb3a,
|
||||
0xfee50b7025c36a08, 0x9f4f2726179a2245, 0xc722f0ef9d80aad6,
|
||||
0xf8ebad2b84e0d58c, 0x9b934c3b330c8577, 0xc2781f49ffcfa6d5,
|
||||
0xf316271c7fc3908b, 0x97edd871cfda3a57, 0xbde94e8e43d0c8ec,
|
||||
0xed63a231d4c4fb27, 0x945e455f24fb1cf9, 0xb975d6b6ee39e437,
|
||||
0xe7d34c64a9c85d44, 0x90e40fbeea1d3a4b, 0xb51d13aea4a488dd,
|
||||
0xe264589a4dcdab15, 0x8d7eb76070a08aed, 0xb0de65388cc8ada8,
|
||||
0xdd15fe86affad912, 0x8a2dbf142dfcc7ab, 0xacb92ed9397bf996,
|
||||
0xd7e77a8f87daf7fc, 0x86f0ac99b4e8dafd, 0xa8acd7c0222311bd,
|
||||
0xd2d80db02aabd62c, 0x83c7088e1aab65db, 0xa4b8cab1a1563f52,
|
||||
0xcde6fd5e09abcf27, 0x80b05e5ac60b6178, 0xa0dc75f1778e39d6,
|
||||
0xc913936dd571c84c, 0xfb5878494ace3a5f, 0x9d174b2dcec0e47b,
|
||||
0xc45d1df942711d9a, 0xf5746577930d6501, 0x9968bf6abbe85f20,
|
||||
0xbfc2ef456ae276e9, 0xefb3ab16c59b14a3, 0x95d04aee3b80ece6,
|
||||
0xbb445da9ca61281f, 0xea1575143cf97227, 0x924d692ca61be758,
|
||||
0xb6e0c377cfa2e12e, 0xe498f455c38b997a, 0x8edf98b59a373fec,
|
||||
0xb2977ee300c50fe7, 0xdf3d5e9bc0f653e1, 0x8b865b215899f46d,
|
||||
0xae67f1e9aec07188, 0xda01ee641a708dea, 0x884134fe908658b2,
|
||||
0xaa51823e34a7eedf, 0xd4e5e2cdc1d1ea96, 0x850fadc09923329e,
|
||||
0xa6539930bf6bff46, 0xcfe87f7cef46ff17, 0x81f14fae158c5f6e,
|
||||
0xa26da3999aef774a, 0xcb090c8001ab551c, 0xfdcb4fa002162a63,
|
||||
0x9e9f11c4014dda7e, 0xc646d63501a1511e, 0xf7d88bc24209a565,
|
||||
0x9ae757596946075f, 0xc1a12d2fc3978937, 0xf209787bb47d6b85,
|
||||
0x9745eb4d50ce6333, 0xbd176620a501fc00, 0xec5d3fa8ce427b00,
|
||||
0x93ba47c980e98ce0, 0xb8a8d9bbe123f018, 0xe6d3102ad96cec1e,
|
||||
0x9043ea1ac7e41393, 0xb454e4a179dd1877, 0xe16a1dc9d8545e95,
|
||||
0x8ce2529e2734bb1d, 0xb01ae745b101e9e4, 0xdc21a1171d42645d,
|
||||
0x899504ae72497eba, 0xabfa45da0edbde69, 0xd6f8d7509292d603,
|
||||
0x865b86925b9bc5c2, 0xa7f26836f282b733, 0xd1ef0244af2364ff,
|
||||
0x8335616aed761f1f, 0xa402b9c5a8d3a6e7, 0xcd036837130890a1,
|
||||
0x802221226be55a65, 0xa02aa96b06deb0fe, 0xc83553c5c8965d3d,
|
||||
0xfa42a8b73abbf48d, 0x9c69a97284b578d8, 0xc38413cf25e2d70e,
|
||||
0xf46518c2ef5b8cd1, 0x98bf2f79d5993803, 0xbeeefb584aff8604,
|
||||
0xeeaaba2e5dbf6785, 0x952ab45cfa97a0b3, 0xba756174393d88e0,
|
||||
0xe912b9d1478ceb17, 0x91abb422ccb812ef, 0xb616a12b7fe617aa,
|
||||
0xe39c49765fdf9d95, 0x8e41ade9fbebc27d, 0xb1d219647ae6b31c,
|
||||
0xde469fbd99a05fe3, 0x8aec23d680043bee, 0xada72ccc20054aea,
|
||||
0xd910f7ff28069da4, 0x87aa9aff79042287, 0xa99541bf57452b28,
|
||||
0xd3fa922f2d1675f2, 0x847c9b5d7c2e09b7, 0xa59bc234db398c25,
|
||||
0xcf02b2c21207ef2f, 0x8161afb94b44f57d, 0xa1ba1ba79e1632dc,
|
||||
0xca28a291859bbf93, 0xfcb2cb35e702af78, 0x9defbf01b061adab,
|
||||
0xc56baec21c7a1916, 0xf6c69a72a3989f5c, 0x9a3c2087a63f6399,
|
||||
0xc0cb28a98fcf3c80, 0xf0fdf2d3f3c30b9f, 0x969eb7c47859e744,
|
||||
0xbc4665b596706115, 0xeb57ff22fc0c795a, 0x9316ff75dd87cbd8,
|
||||
0xb7dcbf5354e9bece, 0xe5d3ef282a242e82, 0x8fa475791a569d11,
|
||||
0xb38d92d760ec4455, 0xe070f78d3927556b, 0x8c469ab843b89563,
|
||||
0xaf58416654a6babb, 0xdb2e51bfe9d0696a, 0x88fcf317f22241e2,
|
||||
0xab3c2fddeeaad25b, 0xd60b3bd56a5586f2, 0x85c7056562757457,
|
||||
0xa738c6bebb12d16d, 0xd106f86e69d785c8, 0x82a45b450226b39d,
|
||||
0xa34d721642b06084, 0xcc20ce9bd35c78a5, 0xff290242c83396ce,
|
||||
0x9f79a169bd203e41, 0xc75809c42c684dd1, 0xf92e0c3537826146,
|
||||
0x9bbcc7a142b17ccc, 0xc2abf989935ddbfe, 0xf356f7ebf83552fe,
|
||||
0x98165af37b2153df, 0xbe1bf1b059e9a8d6, 0xeda2ee1c7064130c,
|
||||
0x9485d4d1c63e8be8, 0xb9a74a0637ce2ee1, 0xe8111c87c5c1ba9a,
|
||||
0x910ab1d4db9914a0, 0xb54d5e4a127f59c8, 0xe2a0b5dc971f303a,
|
||||
0x8da471a9de737e24, 0xb10d8e1456105dad, 0xdd50f1996b947519,
|
||||
0x8a5296ffe33cc930, 0xace73cbfdc0bfb7b, 0xd8210befd30efa5a,
|
||||
0x8714a775e3e95c78, 0xa8d9d1535ce3b396, 0xd31045a8341ca07c,
|
||||
0x83ea2b892091e44e, 0xa4e4b66b68b65d61, 0xce1de40642e3f4b9,
|
||||
0x80d2ae83e9ce78f4, 0xa1075a24e4421731, 0xc94930ae1d529cfd,
|
||||
0xfb9b7cd9a4a7443c, 0x9d412e0806e88aa6, 0xc491798a08a2ad4f,
|
||||
0xf5b5d7ec8acb58a3, 0x9991a6f3d6bf1766, 0xbff610b0cc6edd3f,
|
||||
0xeff394dcff8a948f, 0x95f83d0a1fb69cd9, 0xbb764c4ca7a44410,
|
||||
0xea53df5fd18d5514, 0x92746b9be2f8552c, 0xb7118682dbb66a77,
|
||||
0xe4d5e82392a40515, 0x8f05b1163ba6832d, 0xb2c71d5bca9023f8,
|
||||
0xdf78e4b2bd342cf7, 0x8bab8eefb6409c1a, 0xae9672aba3d0c321,
|
||||
0xda3c0f568cc4f3e9, 0x8865899617fb1871, 0xaa7eebfb9df9de8e,
|
||||
0xd51ea6fa85785631, 0x8533285c936b35df, 0xa67ff273b8460357,
|
||||
0xd01fef10a657842c, 0x8213f56a67f6b29c, 0xa298f2c501f45f43,
|
||||
0xcb3f2f7642717713, 0xfe0efb53d30dd4d8, 0x9ec95d1463e8a507,
|
||||
0xc67bb4597ce2ce49, 0xf81aa16fdc1b81db, 0x9b10a4e5e9913129,
|
||||
0xc1d4ce1f63f57d73, 0xf24a01a73cf2dcd0, 0x976e41088617ca02,
|
||||
0xbd49d14aa79dbc82, 0xec9c459d51852ba3, 0x93e1ab8252f33b46,
|
||||
0xb8da1662e7b00a17, 0xe7109bfba19c0c9d, 0x906a617d450187e2,
|
||||
0xb484f9dc9641e9db, 0xe1a63853bbd26451, 0x8d07e33455637eb3,
|
||||
0xb049dc016abc5e60, 0xdc5c5301c56b75f7, 0x89b9b3e11b6329bb,
|
||||
0xac2820d9623bf429, 0xd732290fbacaf134, 0x867f59a9d4bed6c0,
|
||||
0xa81f301449ee8c70, 0xd226fc195c6a2f8c, 0x83585d8fd9c25db8,
|
||||
0xa42e74f3d032f526, 0xcd3a1230c43fb26f, 0x80444b5e7aa7cf85,
|
||||
0xa0555e361951c367, 0xc86ab5c39fa63441, 0xfa856334878fc151,
|
||||
0x9c935e00d4b9d8d2, 0xc3b8358109e84f07, 0xf4a642e14c6262c9,
|
||||
0x98e7e9cccfbd7dbe, 0xbf21e44003acdd2d, 0xeeea5d5004981478,
|
||||
0x95527a5202df0ccb, 0xbaa718e68396cffe, 0xe950df20247c83fd,
|
||||
0x91d28b7416cdd27e, 0xb6472e511c81471e, 0xe3d8f9e563a198e5,
|
||||
0x8e679c2f5e44ff8f, 0xb201833b35d63f73, 0xde81e40a034bcf50,
|
||||
0x8b112e86420f6192, 0xadd57a27d29339f6, 0xd94ad8b1c7380874,
|
||||
0x87cec76f1c830549, 0xa9c2794ae3a3c69b, 0xd433179d9c8cb841,
|
||||
0x849feec281d7f329, 0xa5c7ea73224deff3, 0xcf39e50feae16bf0,
|
||||
0x81842f29f2cce376, 0xa1e53af46f801c53, 0xca5e89b18b602368,
|
||||
0xfcf62c1dee382c42, 0x9e19db92b4e31ba9, 0xc5a05277621be294,
|
||||
0xf70867153aa2db39, 0x9a65406d44a5c903, 0xc0fe908895cf3b44,
|
||||
0xf13e34aabb430a15, 0x96c6e0eab509e64d, 0xbc789925624c5fe1,
|
||||
0xeb96bf6ebadf77d9, 0x933e37a534cbaae8, 0xb80dc58e81fe95a1,
|
||||
0xe61136f2227e3b0a, 0x8fcac257558ee4e6, 0xb3bd72ed2af29e20,
|
||||
0xe0accfa875af45a8, 0x8c6c01c9498d8b89, 0xaf87023b9bf0ee6b,
|
||||
0xdb68c2ca82ed2a06, 0x892179be91d43a44, 0xab69d82e364948d4
|
||||
};
|
||||
|
||||
static const int powers_ten_e[] = {
|
||||
-1203, -1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173,
|
||||
-1170, -1166, -1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140,
|
||||
-1136, -1133, -1130, -1127, -1123, -1120, -1117, -1113, -1110, -1107,
|
||||
-1103, -1100, -1097, -1093, -1090, -1087, -1083, -1080, -1077, -1073,
|
||||
-1070, -1067, -1063, -1060, -1057, -1053, -1050, -1047, -1043, -1040,
|
||||
-1037, -1034, -1030, -1027, -1024, -1020, -1017, -1014, -1010, -1007,
|
||||
-1004, -1000, -997, -994, -990, -987, -984, -980, -977, -974, -970,
|
||||
-967, -964, -960, -957, -954, -950, -947, -944, -940, -937, -934, -931,
|
||||
-927, -924, -921, -917, -914, -911, -907, -904, -901, -897, -894, -891,
|
||||
-887, -884, -881, -877, -874, -871, -867, -864, -861, -857, -854, -851,
|
||||
-847, -844, -841, -838, -834, -831, -828, -824, -821, -818, -814, -811,
|
||||
-808, -804, -801, -798, -794, -791, -788, -784, -781, -778, -774, -771,
|
||||
-768, -764, -761, -758, -754, -751, -748, -744, -741, -738, -735, -731,
|
||||
-728, -725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691,
|
||||
-688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655, -651,
|
||||
-648, -645, -642, -638, -635, -632, -628, -625, -622, -618, -615, -612,
|
||||
-608, -605, -602, -598, -595, -592, -588, -585, -582, -578, -575, -572,
|
||||
-568, -565, -562, -558, -555, -552, -549, -545, -542, -539, -535, -532,
|
||||
-529, -525, -522, -519, -515, -512, -509, -505, -502, -499, -495, -492,
|
||||
-489, -485, -482, -479, -475, -472, -469, -465, -462, -459, -455, -452,
|
||||
-449, -446, -442, -439, -436, -432, -429, -426, -422, -419, -416, -412,
|
||||
-409, -406, -402, -399, -396, -392, -389, -386, -382, -379, -376, -372,
|
||||
-369, -366, -362, -359, -356, -353, -349, -346, -343, -339, -336, -333,
|
||||
-329, -326, -323, -319, -316, -313, -309, -306, -303, -299, -296, -293,
|
||||
-289, -286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253,
|
||||
-250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216, -213,
|
||||
-210, -206, -203, -200, -196, -193, -190, -186, -183, -180, -176, -173,
|
||||
-170, -166, -163, -160, -157, -153, -150, -147, -143, -140, -137, -133,
|
||||
-130, -127, -123, -120, -117, -113, -110, -107, -103, -100, -97, -93,
|
||||
-90, -87, -83, -80, -77, -73, -70, -67, -63, -60, -57, -54, -50, -47,
|
||||
-44, -40, -37, -34, -30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3, 6,
|
||||
10, 13, 16, 20, 23, 26, 30, 33, 36, 39, 43, 46, 49, 53, 56, 59, 63, 66,
|
||||
69, 73, 76, 79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113, 116, 119,
|
||||
123, 126, 129, 132, 136, 139, 142, 146, 149, 152, 156, 159, 162, 166,
|
||||
169, 172, 176, 179, 182, 186, 189, 192, 196, 199, 202, 206, 209, 212,
|
||||
216, 219, 222, 226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259,
|
||||
262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295, 299, 302, 305,
|
||||
309, 312, 315, 319, 322, 325, 328, 332, 335, 338, 342, 345, 348, 352,
|
||||
355, 358, 362, 365, 368, 372, 375, 378, 382, 385, 388, 392, 395, 398,
|
||||
402, 405, 408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441, 445,
|
||||
448, 451, 455, 458, 461, 465, 468, 471, 475, 478, 481, 485, 488, 491,
|
||||
495, 498, 501, 505, 508, 511, 515, 518, 521, 524, 528, 531, 534, 538,
|
||||
541, 544, 548, 551, 554, 558, 561, 564, 568, 571, 574, 578, 581, 584,
|
||||
588, 591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624, 627, 631,
|
||||
634, 637, 641, 644, 647, 651, 654, 657, 661, 664, 667, 671, 674, 677,
|
||||
681, 684, 687, 691, 694, 697, 701, 704, 707, 711, 714, 717, 720, 724,
|
||||
727, 730, 734, 737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770,
|
||||
774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807, 810, 813, 817,
|
||||
820, 823, 827, 830, 833, 837, 840, 843, 847, 850, 853, 857, 860, 863,
|
||||
867, 870, 873, 877, 880, 883, 887, 890, 893, 897, 900, 903, 907, 910,
|
||||
913, 916, 920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953, 956,
|
||||
960, 963, 966, 970, 973, 976, 980, 983, 986, 990, 993, 996, 1000, 1003,
|
||||
1006, 1009, 1013, 1016, 1019, 1023, 1026, 1029, 1033, 1036, 1039, 1043,
|
||||
1046, 1049, 1053, 1056, 1059, 1063, 1066, 1069, 1073, 1076
|
||||
};
|
||||
|
||||
static diy_fp_t cached_power(int k)
|
||||
{
|
||||
diy_fp_t res;
|
||||
int index = 343 + k;
|
||||
res.f = powers_ten[index];
|
||||
res.e = powers_ten_e[index];
|
||||
return res;
|
||||
}
|
||||
|
||||
static int k_comp(int e, int alpha, int gamma) {
|
||||
return ceil((alpha-e+63) * D_1_LOG2_10);
|
||||
}
|
||||
|
||||
static diy_fp_t minus(diy_fp_t x, diy_fp_t y)
|
||||
{
|
||||
diy_fp_t r;
|
||||
assert(x.e == y.e);
|
||||
assert(x.f >= y.f);
|
||||
r.f = x.f - y.f;
|
||||
r.e = x.e;
|
||||
return r;
|
||||
}
|
||||
|
||||
static diy_fp_t multiply(diy_fp_t x, diy_fp_t y)
|
||||
{
|
||||
uint64_t a,b,c,d,ac,bc,ad,bd,tmp;
|
||||
diy_fp_t r;
|
||||
uint64_t M32 = 0xFFFFFFFF;
|
||||
a = x.f >> 32; b = x.f & M32;
|
||||
c = y.f >> 32; d = y.f & M32;
|
||||
ac = a*c; bc = b*c; ad = a*d; bd = b*d;
|
||||
tmp = (bd>>32) + (ad&M32) + (bc&M32);
|
||||
tmp += 1U << 31;
|
||||
r.f = ac+(ad>>32)+(bc>>32)+(tmp >>32);
|
||||
r.e = x.e + y.e + 64;
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint64_t double_to_uint64(double d)
|
||||
{
|
||||
uint64_t n;
|
||||
memcpy(&n, &d, 8);
|
||||
return n;
|
||||
}
|
||||
|
||||
#define DP_SIGNIFICAND_SIZE 52
|
||||
#define DP_EXPONENT_BIAS (0x3FF + DP_SIGNIFICAND_SIZE)
|
||||
#define DP_MIN_EXPONENT (-DP_EXPONENT_BIAS)
|
||||
#define DP_EXPONENT_MASK 0x7FF0000000000000
|
||||
#define DP_SIGNIFICAND_MASK 0x000FFFFFFFFFFFFF
|
||||
#define DP_HIDDEN_BIT 0x0010000000000000
|
||||
|
||||
static diy_fp_t double2diy_fp(double d)
|
||||
{
|
||||
uint64_t d64 = double_to_uint64(d);
|
||||
int biased_e = (d64 & DP_EXPONENT_MASK) >> DP_SIGNIFICAND_SIZE;
|
||||
uint64_t significand = (d64 & DP_SIGNIFICAND_MASK);
|
||||
diy_fp_t res;
|
||||
if (biased_e != 0) {
|
||||
res.f = significand + DP_HIDDEN_BIT;
|
||||
res.e = biased_e - DP_EXPONENT_BIAS;
|
||||
} else {
|
||||
res.f = significand;
|
||||
res.e = DP_MIN_EXPONENT + 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static diy_fp_t normalize_boundary(diy_fp_t in)
|
||||
{
|
||||
diy_fp_t res = in;
|
||||
/* Normalize now */
|
||||
/* the original number could have been a denormal. */
|
||||
while (! (res.f & (DP_HIDDEN_BIT << 1))) {
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
/* do the final shifts in one go. Don't forget the hidden bit (the '-1') */
|
||||
res.f <<= (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2);
|
||||
res.e = res.e - (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void normalized_boundaries(double d, diy_fp_t* out_m_minus, diy_fp_t* out_m_plus)
|
||||
{
|
||||
diy_fp_t v = double2diy_fp(d);
|
||||
diy_fp_t pl, mi;
|
||||
int significand_is_zero = v.f == DP_HIDDEN_BIT;
|
||||
pl.f = (v.f << 1) + 1; pl.e = v.e - 1;
|
||||
pl = normalize_boundary(pl);
|
||||
if (significand_is_zero) {
|
||||
mi.f = (v.f << 2) - 1;
|
||||
mi.e = v.e - 2;
|
||||
} else {
|
||||
mi.f = (v.f << 1) - 1;
|
||||
mi.e = v.e - 1;
|
||||
}
|
||||
mi.f <<= mi.e - pl.e;
|
||||
mi.e = pl.e;
|
||||
*out_m_plus = pl;
|
||||
*out_m_minus = mi;
|
||||
}
|
||||
|
||||
#define TEN2 100
|
||||
static void digit_gen(diy_fp_t Mp, diy_fp_t delta, char* buffer, int* len, int* K)
|
||||
{
|
||||
uint32_t div, p1;
|
||||
uint64_t p2;
|
||||
int d,kappa;
|
||||
diy_fp_t one;
|
||||
one.f = ((uint64_t) 1) << -Mp.e; one.e = Mp.e;
|
||||
p1 = Mp.f >> -one.e;
|
||||
p2 = Mp.f & (one.f - 1);
|
||||
*len = 0; kappa = 3; div = TEN2;
|
||||
while (kappa > 0) {
|
||||
d = p1 / div;
|
||||
if (d || *len) buffer[(*len)++] = '0' + d;
|
||||
p1 %= div; kappa--; div /= 10;
|
||||
if ((((uint64_t)p1)<<-one.e)+p2 <= delta.f) {
|
||||
*K += kappa; return;
|
||||
}
|
||||
}
|
||||
do {
|
||||
p2 *= 10;
|
||||
d = p2 >> -one.e;
|
||||
if (d || *len) buffer[(*len)++] = '0' + d;
|
||||
p2 &= one.f - 1; kappa--; delta.f *= 10;
|
||||
} while (p2 > delta.f);
|
||||
*K += kappa;
|
||||
}
|
||||
|
||||
int
|
||||
js_grisu2(double v, char *buffer, int *K)
|
||||
{
|
||||
int length, mk;
|
||||
diy_fp_t w_m, w_p, c_mk, Wp, Wm, delta;
|
||||
int q = 64, alpha = -59, gamma = -56;
|
||||
normalized_boundaries(v, &w_m, &w_p);
|
||||
mk = k_comp(w_p.e + q, alpha, gamma);
|
||||
c_mk = cached_power(mk);
|
||||
Wp = multiply(w_p, c_mk);
|
||||
Wm = multiply(w_m, c_mk);
|
||||
Wm.f++; Wp.f--;
|
||||
delta = minus(Wp, Wm);
|
||||
*K = -mk;
|
||||
digit_gen(Wp, delta, buffer, &length, K);
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
* strtod.c
|
||||
*
|
||||
* Copyright (c) 1988-1993 The Regents of the University of California.
|
||||
* Copyright (c) 1994 Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notice appear in all copies. The University of
|
||||
* California makes no representations about the suitability of this software
|
||||
* for any purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/* Largest possible base 10 exponent. Any exponent larger than this will
|
||||
* already produce underflow or overflow, so there's no need to worry about
|
||||
* additional digits.
|
||||
*/
|
||||
static int maxExponent = 511;
|
||||
|
||||
/* Table giving binary powers of 10. Entry
|
||||
* is 10^2^i. Used to convert decimal
|
||||
* exponents into floating-point numbers.
|
||||
*/
|
||||
static double powersOf10[] = {
|
||||
10.,
|
||||
100.,
|
||||
1.0e4,
|
||||
1.0e8,
|
||||
1.0e16,
|
||||
1.0e32,
|
||||
1.0e64,
|
||||
1.0e128,
|
||||
1.0e256
|
||||
};
|
||||
|
||||
/* Parse a decimal ASCII floating-point number, optionally preceded by white
|
||||
* space. Must have form "-I.FE-X", where I is the integer part of the
|
||||
* mantissa, F is the fractional part of the mantissa, and X is the exponent.
|
||||
* Either of the signs may be "+", "-", or omitted. Either I or F may be
|
||||
* omitted, or both. The decimal point isn't necessary unless F is present.
|
||||
* The "E" may actually be an "e". E and X may both be omitted (but not just
|
||||
* one).
|
||||
*/
|
||||
double
|
||||
js_strtod(const char *string, char **endPtr)
|
||||
{
|
||||
int sign, expSign = FALSE;
|
||||
double fraction, dblExp, *d;
|
||||
register const char *p;
|
||||
register int c;
|
||||
|
||||
/* Exponent read from "EX" field. */
|
||||
int exp = 0;
|
||||
|
||||
/* Exponent that derives from the fractional part. Under normal
|
||||
* circumstances, it is the negative of the number of digits in F.
|
||||
* However, if I is very long, the last digits of I get dropped
|
||||
* (otherwise a long I with a large negative exponent could cause an
|
||||
* unnecessary overflow on I alone). In this case, fracExp is
|
||||
* incremented one for each dropped digit.
|
||||
*/
|
||||
int fracExp = 0;
|
||||
|
||||
/* Number of digits in mantissa. */
|
||||
int mantSize;
|
||||
|
||||
/* Number of mantissa digits BEFORE decimal point. */
|
||||
int decPt;
|
||||
|
||||
/* Temporarily holds location of exponent in string. */
|
||||
const char *pExp;
|
||||
|
||||
/*
|
||||
* Strip off leading blanks and check for a sign.
|
||||
*/
|
||||
|
||||
p = string;
|
||||
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') {
|
||||
p += 1;
|
||||
}
|
||||
if (*p == '-') {
|
||||
sign = TRUE;
|
||||
p += 1;
|
||||
} else {
|
||||
if (*p == '+') {
|
||||
p += 1;
|
||||
}
|
||||
sign = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of digits in the mantissa (including the decimal
|
||||
* point), and also locate the decimal point.
|
||||
*/
|
||||
|
||||
decPt = -1;
|
||||
for (mantSize = 0; ; mantSize += 1)
|
||||
{
|
||||
c = *p;
|
||||
if (!(c>='0'&&c<='9')) {
|
||||
if ((c != '.') || (decPt >= 0)) {
|
||||
break;
|
||||
}
|
||||
decPt = mantSize;
|
||||
}
|
||||
p += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now suck up the digits in the mantissa. Use two integers to
|
||||
* collect 9 digits each (this is faster than using floating-point).
|
||||
* If the mantissa has more than 18 digits, ignore the extras, since
|
||||
* they can't affect the value anyway.
|
||||
*/
|
||||
|
||||
pExp = p;
|
||||
p -= mantSize;
|
||||
if (decPt < 0) {
|
||||
decPt = mantSize;
|
||||
} else {
|
||||
mantSize -= 1; /* One of the digits was the point. */
|
||||
}
|
||||
if (mantSize > 18) {
|
||||
fracExp = decPt - 18;
|
||||
mantSize = 18;
|
||||
} else {
|
||||
fracExp = decPt - mantSize;
|
||||
}
|
||||
if (mantSize == 0) {
|
||||
fraction = 0.0;
|
||||
p = string;
|
||||
goto done;
|
||||
} else {
|
||||
int frac1, frac2;
|
||||
frac1 = 0;
|
||||
for ( ; mantSize > 9; mantSize -= 1)
|
||||
{
|
||||
c = *p;
|
||||
p += 1;
|
||||
if (c == '.') {
|
||||
c = *p;
|
||||
p += 1;
|
||||
}
|
||||
frac1 = 10*frac1 + (c - '0');
|
||||
}
|
||||
frac2 = 0;
|
||||
for (; mantSize > 0; mantSize -= 1)
|
||||
{
|
||||
c = *p;
|
||||
p += 1;
|
||||
if (c == '.') {
|
||||
c = *p;
|
||||
p += 1;
|
||||
}
|
||||
frac2 = 10*frac2 + (c - '0');
|
||||
}
|
||||
fraction = (1.0e9 * frac1) + frac2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skim off the exponent.
|
||||
*/
|
||||
|
||||
p = pExp;
|
||||
if ((*p == 'E') || (*p == 'e')) {
|
||||
p += 1;
|
||||
if (*p == '-') {
|
||||
expSign = TRUE;
|
||||
p += 1;
|
||||
} else {
|
||||
if (*p == '+') {
|
||||
p += 1;
|
||||
}
|
||||
expSign = FALSE;
|
||||
}
|
||||
while ((*p >= '0') && (*p <= '9')) {
|
||||
exp = exp * 10 + (*p - '0');
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
if (expSign) {
|
||||
exp = fracExp - exp;
|
||||
} else {
|
||||
exp = fracExp + exp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a floating-point number that represents the exponent.
|
||||
* Do this by processing the exponent one bit at a time to combine
|
||||
* many powers of 2 of 10. Then combine the exponent with the
|
||||
* fraction.
|
||||
*/
|
||||
|
||||
if (exp < -maxExponent) {
|
||||
exp = maxExponent;
|
||||
expSign = TRUE;
|
||||
errno = ERANGE;
|
||||
} else if (exp > maxExponent) {
|
||||
exp = maxExponent;
|
||||
expSign = FALSE;
|
||||
errno = ERANGE;
|
||||
} else if (exp < 0) {
|
||||
expSign = TRUE;
|
||||
exp = -exp;
|
||||
} else {
|
||||
expSign = FALSE;
|
||||
}
|
||||
dblExp = 1.0;
|
||||
for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
|
||||
if (exp & 01) {
|
||||
dblExp *= *d;
|
||||
}
|
||||
}
|
||||
if (expSign) {
|
||||
fraction /= dblExp;
|
||||
} else {
|
||||
fraction *= dblExp;
|
||||
}
|
||||
|
||||
done:
|
||||
if (endPtr != NULL) {
|
||||
*endPtr = (char *) p;
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
return -fraction;
|
||||
}
|
||||
return fraction;
|
||||
}
|
@ -1,924 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
|
||||
#include "utf.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static const char *astname[] = {
|
||||
#include "astnames.h"
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *opname[] = {
|
||||
#include "opnames.h"
|
||||
NULL
|
||||
};
|
||||
|
||||
static int minify = 0;
|
||||
|
||||
const char *jsP_aststring(enum js_AstType type)
|
||||
{
|
||||
if (type < nelem(astname)-1)
|
||||
return astname[type];
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
const char *jsC_opcodestring(enum js_OpCode opcode)
|
||||
{
|
||||
if (opcode < nelem(opname)-1)
|
||||
return opname[opcode];
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
static int prec(enum js_AstType type)
|
||||
{
|
||||
switch (type) {
|
||||
case AST_IDENTIFIER:
|
||||
case EXP_IDENTIFIER:
|
||||
case EXP_NUMBER:
|
||||
case EXP_STRING:
|
||||
case EXP_REGEXP:
|
||||
case EXP_UNDEF:
|
||||
case EXP_NULL:
|
||||
case EXP_TRUE:
|
||||
case EXP_FALSE:
|
||||
case EXP_THIS:
|
||||
case EXP_ARRAY:
|
||||
case EXP_OBJECT:
|
||||
return 170;
|
||||
|
||||
case EXP_FUN:
|
||||
case EXP_INDEX:
|
||||
case EXP_MEMBER:
|
||||
case EXP_CALL:
|
||||
case EXP_NEW:
|
||||
return 160;
|
||||
|
||||
case EXP_POSTINC:
|
||||
case EXP_POSTDEC:
|
||||
return 150;
|
||||
|
||||
case EXP_DELETE:
|
||||
case EXP_VOID:
|
||||
case EXP_TYPEOF:
|
||||
case EXP_PREINC:
|
||||
case EXP_PREDEC:
|
||||
case EXP_POS:
|
||||
case EXP_NEG:
|
||||
case EXP_BITNOT:
|
||||
case EXP_LOGNOT:
|
||||
return 140;
|
||||
|
||||
case EXP_MOD:
|
||||
case EXP_DIV:
|
||||
case EXP_MUL:
|
||||
return 130;
|
||||
|
||||
case EXP_SUB:
|
||||
case EXP_ADD:
|
||||
return 120;
|
||||
|
||||
case EXP_USHR:
|
||||
case EXP_SHR:
|
||||
case EXP_SHL:
|
||||
return 110;
|
||||
|
||||
case EXP_IN:
|
||||
case EXP_INSTANCEOF:
|
||||
case EXP_GE:
|
||||
case EXP_LE:
|
||||
case EXP_GT:
|
||||
case EXP_LT:
|
||||
return 100;
|
||||
|
||||
case EXP_STRICTNE:
|
||||
case EXP_STRICTEQ:
|
||||
case EXP_NE:
|
||||
case EXP_EQ:
|
||||
return 90;
|
||||
|
||||
case EXP_BITAND: return 80;
|
||||
case EXP_BITXOR: return 70;
|
||||
case EXP_BITOR: return 60;
|
||||
case EXP_LOGAND: return 50;
|
||||
case EXP_LOGOR: return 40;
|
||||
|
||||
case EXP_COND:
|
||||
return 30;
|
||||
|
||||
case EXP_ASS:
|
||||
case EXP_ASS_MUL:
|
||||
case EXP_ASS_DIV:
|
||||
case EXP_ASS_MOD:
|
||||
case EXP_ASS_ADD:
|
||||
case EXP_ASS_SUB:
|
||||
case EXP_ASS_SHL:
|
||||
case EXP_ASS_SHR:
|
||||
case EXP_ASS_USHR:
|
||||
case EXP_ASS_BITAND:
|
||||
case EXP_ASS_BITXOR:
|
||||
case EXP_ASS_BITOR:
|
||||
return 20;
|
||||
|
||||
#define COMMA 15
|
||||
|
||||
case EXP_COMMA:
|
||||
return 10;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void pc(int c)
|
||||
{
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
static void ps(const char *s)
|
||||
{
|
||||
fputs(s, stdout);
|
||||
}
|
||||
|
||||
static void pn(int n)
|
||||
{
|
||||
printf("%d", n);
|
||||
}
|
||||
|
||||
static void in(int d)
|
||||
{
|
||||
if (minify < 1)
|
||||
while (d-- > 0)
|
||||
putchar('\t');
|
||||
}
|
||||
|
||||
static void nl(void)
|
||||
{
|
||||
if (minify < 2)
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void sp(void)
|
||||
{
|
||||
if (minify < 1)
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
static void comma(void)
|
||||
{
|
||||
putchar(',');
|
||||
sp();
|
||||
}
|
||||
|
||||
/* Pretty-printed Javascript syntax */
|
||||
|
||||
static void pstmlist(int d, js_Ast *list);
|
||||
static void pexpi(int d, int i, js_Ast *exp);
|
||||
static void pstm(int d, js_Ast *stm);
|
||||
static void slist(int d, js_Ast *list);
|
||||
static void sblock(int d, js_Ast *list);
|
||||
|
||||
static void pargs(int d, js_Ast *list)
|
||||
{
|
||||
while (list) {
|
||||
assert(list->type == AST_LIST);
|
||||
pexpi(d, COMMA, list->a);
|
||||
list = list->b;
|
||||
if (list)
|
||||
comma();
|
||||
}
|
||||
}
|
||||
|
||||
static void parray(int d, js_Ast *list)
|
||||
{
|
||||
pc('[');
|
||||
while (list) {
|
||||
assert(list->type == AST_LIST);
|
||||
pexpi(d, COMMA, list->a);
|
||||
list = list->b;
|
||||
if (list)
|
||||
comma();
|
||||
}
|
||||
pc(']');
|
||||
}
|
||||
|
||||
static void pobject(int d, js_Ast *list)
|
||||
{
|
||||
pc('{');
|
||||
if (list) {
|
||||
nl();
|
||||
in(d+1);
|
||||
}
|
||||
while (list) {
|
||||
js_Ast *kv = list->a;
|
||||
assert(list->type == AST_LIST);
|
||||
switch (kv->type) {
|
||||
default: break;
|
||||
case EXP_PROP_VAL:
|
||||
pexpi(d+1, COMMA, kv->a);
|
||||
pc(':'); sp();
|
||||
pexpi(d+1, COMMA, kv->b);
|
||||
break;
|
||||
case EXP_PROP_GET:
|
||||
ps("get ");
|
||||
pexpi(d+1, COMMA, kv->a);
|
||||
ps("()"); sp(); pc('{'); nl();
|
||||
pstmlist(d+1, kv->c);
|
||||
in(d+1); pc('}');
|
||||
break;
|
||||
case EXP_PROP_SET:
|
||||
ps("set ");
|
||||
pexpi(d+1, COMMA, kv->a);
|
||||
pc('(');
|
||||
pargs(d+1, kv->b);
|
||||
pc(')'); sp(); pc('{'); nl();
|
||||
pstmlist(d+1, kv->c);
|
||||
in(d+1); pc('}');
|
||||
break;
|
||||
}
|
||||
list = list->b;
|
||||
if (list) {
|
||||
pc(',');
|
||||
nl();
|
||||
in(d+1);
|
||||
} else {
|
||||
nl();
|
||||
in(d);
|
||||
}
|
||||
}
|
||||
pc('}');
|
||||
}
|
||||
|
||||
static void pstr(const char *s)
|
||||
{
|
||||
static const char *HEX = "0123456789ABCDEF";
|
||||
Rune c;
|
||||
pc(minify ? '\'' : '"');
|
||||
while (*s) {
|
||||
s += chartorune(&c, s);
|
||||
switch (c) {
|
||||
case '\'': ps("\\'"); break;
|
||||
case '"': ps("\\\""); break;
|
||||
case '\\': ps("\\\\"); break;
|
||||
case '\b': ps("\\b"); break;
|
||||
case '\f': ps("\\f"); break;
|
||||
case '\n': ps("\\n"); break;
|
||||
case '\r': ps("\\r"); break;
|
||||
case '\t': ps("\\t"); break;
|
||||
default:
|
||||
if (c < ' ' || c > 127) {
|
||||
ps("\\u");
|
||||
pc(HEX[(c>>12)&15]);
|
||||
pc(HEX[(c>>8)&15]);
|
||||
pc(HEX[(c>>4)&15]);
|
||||
pc(HEX[c&15]);
|
||||
} else {
|
||||
pc(c); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pc(minify ? '\'' : '"');
|
||||
}
|
||||
|
||||
static void pregexp(const char *prog, int flags)
|
||||
{
|
||||
pc('/');
|
||||
ps(prog);
|
||||
pc('/');
|
||||
if (flags & JS_REGEXP_G) pc('g');
|
||||
if (flags & JS_REGEXP_I) pc('i');
|
||||
if (flags & JS_REGEXP_M) pc('m');
|
||||
}
|
||||
|
||||
static void pbin(int d, int p, js_Ast *exp, const char *op)
|
||||
{
|
||||
pexpi(d, p, exp->a);
|
||||
sp();
|
||||
ps(op);
|
||||
sp();
|
||||
pexpi(d, p, exp->b);
|
||||
}
|
||||
|
||||
static void puna(int d, int p, js_Ast *exp, const char *pre, const char *suf)
|
||||
{
|
||||
ps(pre);
|
||||
pexpi(d, p, exp->a);
|
||||
ps(suf);
|
||||
}
|
||||
|
||||
static void pexpi(int d, int p, js_Ast *exp)
|
||||
{
|
||||
int tp, paren;
|
||||
|
||||
if (!exp) return;
|
||||
|
||||
tp = prec(exp->type);
|
||||
paren = 0;
|
||||
if (tp < p) {
|
||||
pc('(');
|
||||
paren = 1;
|
||||
}
|
||||
p = tp;
|
||||
|
||||
switch (exp->type) {
|
||||
case AST_IDENTIFIER: ps(exp->string); break;
|
||||
case EXP_IDENTIFIER: ps(exp->string); break;
|
||||
case EXP_NUMBER: printf("%.9g", exp->number); break;
|
||||
case EXP_STRING: pstr(exp->string); break;
|
||||
case EXP_REGEXP: pregexp(exp->string, exp->number); break;
|
||||
|
||||
case EXP_UNDEF: break;
|
||||
case EXP_NULL: ps("null"); break;
|
||||
case EXP_TRUE: ps("true"); break;
|
||||
case EXP_FALSE: ps("false"); break;
|
||||
case EXP_THIS: ps("this"); break;
|
||||
|
||||
case EXP_OBJECT: pobject(d, exp->a); break;
|
||||
case EXP_ARRAY: parray(d, exp->a); break;
|
||||
|
||||
case EXP_DELETE: puna(d, p, exp, "delete ", ""); break;
|
||||
case EXP_VOID: puna(d, p, exp, "void ", ""); break;
|
||||
case EXP_TYPEOF: puna(d, p, exp, "typeof ", ""); break;
|
||||
case EXP_PREINC: puna(d, p, exp, "++", ""); break;
|
||||
case EXP_PREDEC: puna(d, p, exp, "--", ""); break;
|
||||
case EXP_POSTINC: puna(d, p, exp, "", "++"); break;
|
||||
case EXP_POSTDEC: puna(d, p, exp, "", "--"); break;
|
||||
case EXP_POS: puna(d, p, exp, "+", ""); break;
|
||||
case EXP_NEG: puna(d, p, exp, "-", ""); break;
|
||||
case EXP_BITNOT: puna(d, p, exp, "~", ""); break;
|
||||
case EXP_LOGNOT: puna(d, p, exp, "!", ""); break;
|
||||
|
||||
case EXP_LOGOR: pbin(d, p, exp, "||"); break;
|
||||
case EXP_LOGAND: pbin(d, p, exp, "&&"); break;
|
||||
case EXP_BITOR: pbin(d, p, exp, "|"); break;
|
||||
case EXP_BITXOR: pbin(d, p, exp, "^"); break;
|
||||
case EXP_BITAND: pbin(d, p, exp, "&"); break;
|
||||
case EXP_EQ: pbin(d, p, exp, "=="); break;
|
||||
case EXP_NE: pbin(d, p, exp, "!="); break;
|
||||
case EXP_STRICTEQ: pbin(d, p, exp, "==="); break;
|
||||
case EXP_STRICTNE: pbin(d, p, exp, "!=="); break;
|
||||
case EXP_LT: pbin(d, p, exp, "<"); break;
|
||||
case EXP_GT: pbin(d, p, exp, ">"); break;
|
||||
case EXP_LE: pbin(d, p, exp, "<="); break;
|
||||
case EXP_GE: pbin(d, p, exp, ">="); break;
|
||||
case EXP_IN: pbin(d, p, exp, "in"); break;
|
||||
case EXP_SHL: pbin(d, p, exp, "<<"); break;
|
||||
case EXP_SHR: pbin(d, p, exp, ">>"); break;
|
||||
case EXP_USHR: pbin(d, p, exp, ">>>"); break;
|
||||
case EXP_ADD: pbin(d, p, exp, "+"); break;
|
||||
case EXP_SUB: pbin(d, p, exp, "-"); break;
|
||||
case EXP_MUL: pbin(d, p, exp, "*"); break;
|
||||
case EXP_DIV: pbin(d, p, exp, "/"); break;
|
||||
case EXP_MOD: pbin(d, p, exp, "%"); break;
|
||||
case EXP_ASS: pbin(d, p, exp, "="); break;
|
||||
case EXP_ASS_MUL: pbin(d, p, exp, "*="); break;
|
||||
case EXP_ASS_DIV: pbin(d, p, exp, "/="); break;
|
||||
case EXP_ASS_MOD: pbin(d, p, exp, "%="); break;
|
||||
case EXP_ASS_ADD: pbin(d, p, exp, "+="); break;
|
||||
case EXP_ASS_SUB: pbin(d, p, exp, "-="); break;
|
||||
case EXP_ASS_SHL: pbin(d, p, exp, "<<="); break;
|
||||
case EXP_ASS_SHR: pbin(d, p, exp, ">>="); break;
|
||||
case EXP_ASS_USHR: pbin(d, p, exp, ">>>="); break;
|
||||
case EXP_ASS_BITAND: pbin(d, p, exp, "&="); break;
|
||||
case EXP_ASS_BITXOR: pbin(d, p, exp, "^="); break;
|
||||
case EXP_ASS_BITOR: pbin(d, p, exp, "|="); break;
|
||||
|
||||
case EXP_INSTANCEOF:
|
||||
pexpi(d, p, exp->a);
|
||||
ps(" instanceof ");
|
||||
pexpi(d, p, exp->b);
|
||||
break;
|
||||
|
||||
case EXP_COMMA:
|
||||
pexpi(d, p, exp->a);
|
||||
pc(','); sp();
|
||||
pexpi(d, p, exp->b);
|
||||
break;
|
||||
|
||||
case EXP_COND:
|
||||
pexpi(d, p, exp->a);
|
||||
sp(); pc('?'); sp();
|
||||
pexpi(d, p, exp->b);
|
||||
sp(); pc(':'); sp();
|
||||
pexpi(d, p, exp->c);
|
||||
break;
|
||||
|
||||
case EXP_INDEX:
|
||||
pexpi(d, p, exp->a);
|
||||
pc('[');
|
||||
pexpi(d, 0, exp->b);
|
||||
pc(']');
|
||||
break;
|
||||
|
||||
case EXP_MEMBER:
|
||||
pexpi(d, p, exp->a);
|
||||
pc('.');
|
||||
pexpi(d, 0, exp->b);
|
||||
break;
|
||||
|
||||
case EXP_CALL:
|
||||
pexpi(d, p, exp->a);
|
||||
pc('(');
|
||||
pargs(d, exp->b);
|
||||
pc(')');
|
||||
break;
|
||||
|
||||
case EXP_NEW:
|
||||
ps("new ");
|
||||
pexpi(d, p, exp->a);
|
||||
pc('(');
|
||||
pargs(d, exp->b);
|
||||
pc(')');
|
||||
break;
|
||||
|
||||
case EXP_FUN:
|
||||
if (p == 0) pc('(');
|
||||
ps("function ");
|
||||
pexpi(d, 0, exp->a);
|
||||
pc('(');
|
||||
pargs(d, exp->b);
|
||||
pc(')'); sp(); pc('{'); nl();
|
||||
pstmlist(d, exp->c);
|
||||
in(d); pc('}');
|
||||
if (p == 0) pc(')');
|
||||
break;
|
||||
|
||||
default:
|
||||
ps("<UNKNOWN>");
|
||||
break;
|
||||
}
|
||||
|
||||
if (paren) pc(')');
|
||||
}
|
||||
|
||||
static void pexp(int d, js_Ast *exp)
|
||||
{
|
||||
pexpi(d, 0, exp);
|
||||
}
|
||||
|
||||
static void pvar(int d, js_Ast *var)
|
||||
{
|
||||
assert(var->type == EXP_VAR);
|
||||
pexp(d, var->a);
|
||||
if (var->b) {
|
||||
sp(); pc('='); sp();
|
||||
pexp(d, var->b);
|
||||
}
|
||||
}
|
||||
|
||||
static void pvarlist(int d, js_Ast *list)
|
||||
{
|
||||
while (list) {
|
||||
assert(list->type == AST_LIST);
|
||||
pvar(d, list->a);
|
||||
list = list->b;
|
||||
if (list)
|
||||
comma();
|
||||
}
|
||||
}
|
||||
|
||||
static void pblock(int d, js_Ast *block)
|
||||
{
|
||||
assert(block->type == STM_BLOCK);
|
||||
pc('{'); nl();
|
||||
pstmlist(d, block->a);
|
||||
in(d); pc('}');
|
||||
}
|
||||
|
||||
static void pstmh(int d, js_Ast *stm)
|
||||
{
|
||||
if (stm->type == STM_BLOCK) {
|
||||
sp();
|
||||
pblock(d, stm);
|
||||
} else {
|
||||
nl();
|
||||
pstm(d+1, stm);
|
||||
}
|
||||
}
|
||||
|
||||
static void pcaselist(int d, js_Ast *list)
|
||||
{
|
||||
while (list) {
|
||||
js_Ast *stm = list->a;
|
||||
if (stm->type == STM_CASE) {
|
||||
in(d); ps("case "); pexp(d, stm->a); pc(':'); nl();
|
||||
pstmlist(d, stm->b);
|
||||
}
|
||||
if (stm->type == STM_DEFAULT) {
|
||||
in(d); ps("default:"); nl();
|
||||
pstmlist(d, stm->a);
|
||||
}
|
||||
list = list->b;
|
||||
}
|
||||
}
|
||||
|
||||
static void pstm(int d, js_Ast *stm)
|
||||
{
|
||||
if (stm->type == STM_BLOCK) {
|
||||
pblock(d, stm);
|
||||
return;
|
||||
}
|
||||
|
||||
in(d);
|
||||
|
||||
switch (stm->type) {
|
||||
case AST_FUNDEC:
|
||||
ps("function ");
|
||||
pexp(d, stm->a);
|
||||
pc('(');
|
||||
pargs(d, stm->b);
|
||||
pc(')'); sp(); pc('{'); nl();
|
||||
pstmlist(d, stm->c);
|
||||
in(d); pc('}');
|
||||
break;
|
||||
|
||||
case STM_EMPTY:
|
||||
pc(';');
|
||||
break;
|
||||
|
||||
case STM_VAR:
|
||||
ps("var ");
|
||||
pvarlist(d, stm->a);
|
||||
pc(';');
|
||||
break;
|
||||
|
||||
case STM_IF:
|
||||
ps("if"); sp(); pc('('); pexp(d, stm->a); pc(')');
|
||||
pstmh(d, stm->b);
|
||||
if (stm->c) {
|
||||
nl(); in(d); ps("else");
|
||||
pstmh(d, stm->c);
|
||||
}
|
||||
break;
|
||||
|
||||
case STM_DO:
|
||||
ps("do");
|
||||
pstmh(d, stm->a);
|
||||
nl();
|
||||
in(d); ps("while"); sp(); pc('('); pexp(d, stm->b); pc(')'); pc(';');
|
||||
break;
|
||||
|
||||
case STM_WHILE:
|
||||
ps("while"); sp(); pc('('); pexp(d, stm->a); pc(')');
|
||||
pstmh(d, stm->b);
|
||||
break;
|
||||
|
||||
case STM_FOR:
|
||||
ps("for"); sp(); pc('(');
|
||||
pexp(d, stm->a); pc(';'); sp();
|
||||
pexp(d, stm->b); pc(';'); sp();
|
||||
pexp(d, stm->c); pc(')');
|
||||
pstmh(d, stm->d);
|
||||
break;
|
||||
case STM_FOR_VAR:
|
||||
ps("for"); sp(); ps("(var ");
|
||||
pvarlist(d, stm->a); pc(';'); sp();
|
||||
pexp(d, stm->b); pc(';'); sp();
|
||||
pexp(d, stm->c); pc(')');
|
||||
pstmh(d, stm->d);
|
||||
break;
|
||||
case STM_FOR_IN:
|
||||
ps("for"); sp(); pc('(');
|
||||
pexp(d, stm->a); ps(" in ");
|
||||
pexp(d, stm->b); pc(')');
|
||||
pstmh(d, stm->c);
|
||||
break;
|
||||
case STM_FOR_IN_VAR:
|
||||
ps("for"); sp(); ps("(var ");
|
||||
pvarlist(d, stm->a); ps(" in ");
|
||||
pexp(d, stm->b); pc(')');
|
||||
pstmh(d, stm->c);
|
||||
break;
|
||||
|
||||
case STM_CONTINUE:
|
||||
ps("continue");
|
||||
if (stm->a) {
|
||||
pc(' '); pexp(d, stm->a);
|
||||
}
|
||||
pc(';');
|
||||
break;
|
||||
|
||||
case STM_BREAK:
|
||||
ps("break");
|
||||
if (stm->a) {
|
||||
pc(' '); pexp(d, stm->a);
|
||||
}
|
||||
pc(';');
|
||||
break;
|
||||
|
||||
case STM_RETURN:
|
||||
ps("return");
|
||||
if (stm->a) {
|
||||
pc(' '); pexp(d, stm->a);
|
||||
}
|
||||
pc(';');
|
||||
break;
|
||||
|
||||
case STM_WITH:
|
||||
ps("with"); sp(); pc('('); pexp(d, stm->a); pc(')');
|
||||
pstmh(d, stm->b);
|
||||
break;
|
||||
|
||||
case STM_SWITCH:
|
||||
ps("switch"); sp(); pc('(');
|
||||
pexp(d, stm->a);
|
||||
pc(')'); sp(); pc('{'); nl();
|
||||
pcaselist(d, stm->b);
|
||||
in(d); pc('}');
|
||||
break;
|
||||
|
||||
case STM_THROW:
|
||||
ps("throw "); pexp(d, stm->a); pc(';');
|
||||
break;
|
||||
|
||||
case STM_TRY:
|
||||
ps("try");
|
||||
if (minify && stm->a->type != STM_BLOCK)
|
||||
pc(' ');
|
||||
pstmh(d, stm->a);
|
||||
if (stm->b && stm->c) {
|
||||
nl(); in(d); ps("catch"); sp(); pc('('); pexp(d, stm->b); pc(')');
|
||||
pstmh(d, stm->c);
|
||||
}
|
||||
if (stm->d) {
|
||||
nl(); in(d); ps("finally");
|
||||
pstmh(d, stm->d);
|
||||
}
|
||||
break;
|
||||
|
||||
case STM_LABEL:
|
||||
pexp(d, stm->a); pc(':'); sp(); pstm(d, stm->b);
|
||||
break;
|
||||
|
||||
case STM_DEBUGGER:
|
||||
ps("debugger");
|
||||
pc(';');
|
||||
break;
|
||||
|
||||
default:
|
||||
pexp(d, stm);
|
||||
pc(';');
|
||||
}
|
||||
}
|
||||
|
||||
static void pstmlist(int d, js_Ast *list)
|
||||
{
|
||||
while (list) {
|
||||
assert(list->type == AST_LIST);
|
||||
pstm(d+1, list->a);
|
||||
nl();
|
||||
list = list->b;
|
||||
}
|
||||
}
|
||||
|
||||
void jsP_dumpsyntax(js_State *J, js_Ast *prog, int dominify)
|
||||
{
|
||||
minify = dominify;
|
||||
if (prog->type == AST_LIST)
|
||||
pstmlist(-1, prog);
|
||||
else {
|
||||
pstm(0, prog);
|
||||
nl();
|
||||
}
|
||||
if (minify > 1)
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* S-expression list representation */
|
||||
|
||||
static void snode(int d, js_Ast *node)
|
||||
{
|
||||
void (*afun)(int,js_Ast*) = snode;
|
||||
void (*bfun)(int,js_Ast*) = snode;
|
||||
void (*cfun)(int,js_Ast*) = snode;
|
||||
void (*dfun)(int,js_Ast*) = snode;
|
||||
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->type == AST_LIST) {
|
||||
slist(d, node);
|
||||
return;
|
||||
}
|
||||
|
||||
pc('(');
|
||||
ps(astname[node->type]);
|
||||
pc(':');
|
||||
pn(node->line);
|
||||
switch (node->type) {
|
||||
default: break;
|
||||
case AST_IDENTIFIER: pc(' '); ps(node->string); break;
|
||||
case EXP_IDENTIFIER: pc(' '); ps(node->string); break;
|
||||
case EXP_STRING: pc(' '); pstr(node->string); break;
|
||||
case EXP_REGEXP: pc(' '); pregexp(node->string, node->number); break;
|
||||
case EXP_NUMBER: printf(" %.9g", node->number); break;
|
||||
case STM_BLOCK: afun = sblock; break;
|
||||
case AST_FUNDEC: case EXP_FUN: cfun = sblock; break;
|
||||
case EXP_PROP_GET: cfun = sblock; break;
|
||||
case EXP_PROP_SET: cfun = sblock; break;
|
||||
case STM_SWITCH: bfun = sblock; break;
|
||||
case STM_CASE: bfun = sblock; break;
|
||||
case STM_DEFAULT: afun = sblock; break;
|
||||
}
|
||||
if (node->a) { pc(' '); afun(d, node->a); }
|
||||
if (node->b) { pc(' '); bfun(d, node->b); }
|
||||
if (node->c) { pc(' '); cfun(d, node->c); }
|
||||
if (node->d) { pc(' '); dfun(d, node->d); }
|
||||
pc(')');
|
||||
}
|
||||
|
||||
static void slist(int d, js_Ast *list)
|
||||
{
|
||||
pc('[');
|
||||
while (list) {
|
||||
assert(list->type == AST_LIST);
|
||||
snode(d, list->a);
|
||||
list = list->b;
|
||||
if (list)
|
||||
pc(' ');
|
||||
}
|
||||
pc(']');
|
||||
}
|
||||
|
||||
static void sblock(int d, js_Ast *list)
|
||||
{
|
||||
ps("[\n");
|
||||
in(d+1);
|
||||
while (list) {
|
||||
assert(list->type == AST_LIST);
|
||||
snode(d+1, list->a);
|
||||
list = list->b;
|
||||
if (list) {
|
||||
nl();
|
||||
in(d+1);
|
||||
}
|
||||
}
|
||||
nl(); in(d); pc(']');
|
||||
}
|
||||
|
||||
void jsP_dumplist(js_State *J, js_Ast *prog)
|
||||
{
|
||||
minify = 0;
|
||||
if (prog->type == AST_LIST)
|
||||
sblock(0, prog);
|
||||
else
|
||||
snode(0, prog);
|
||||
nl();
|
||||
}
|
||||
|
||||
/* Compiled code */
|
||||
|
||||
void jsC_dumpfunction(js_State *J, js_Function *F)
|
||||
{
|
||||
js_Instruction *p = F->code;
|
||||
js_Instruction *end = F->code + F->codelen;
|
||||
int i;
|
||||
|
||||
minify = 0;
|
||||
|
||||
printf("%s(%d)\n", F->name, F->numparams);
|
||||
if (F->lightweight) printf("\tlightweight\n");
|
||||
if (F->arguments) printf("\targuments\n");
|
||||
printf("\tsource %s:%d\n", F->filename, F->line);
|
||||
for (i = 0; i < F->funlen; ++i)
|
||||
printf("\tfunction %d %s\n", i, F->funtab[i]->name);
|
||||
for (i = 0; i < F->varlen; ++i)
|
||||
printf("\tlocal %d %s\n", i + 1, F->vartab[i]);
|
||||
|
||||
printf("{\n");
|
||||
while (p < end) {
|
||||
int ln = *p++;
|
||||
int c = *p++;
|
||||
|
||||
printf("%5d(%3d): ", (int)(p - F->code) - 2, ln);
|
||||
ps(opname[c]);
|
||||
|
||||
switch (c) {
|
||||
case OP_INTEGER:
|
||||
printf(" %ld", (long)((*p++) - 32768));
|
||||
break;
|
||||
case OP_NUMBER:
|
||||
printf(" %.9g", F->numtab[*p++]);
|
||||
break;
|
||||
case OP_STRING:
|
||||
pc(' ');
|
||||
pstr(F->strtab[*p++]);
|
||||
break;
|
||||
case OP_NEWREGEXP:
|
||||
pc(' ');
|
||||
pregexp(F->strtab[p[0]], p[1]);
|
||||
p += 2;
|
||||
break;
|
||||
|
||||
case OP_GETVAR:
|
||||
case OP_HASVAR:
|
||||
case OP_SETVAR:
|
||||
case OP_DELVAR:
|
||||
case OP_GETPROP_S:
|
||||
case OP_SETPROP_S:
|
||||
case OP_DELPROP_S:
|
||||
case OP_CATCH:
|
||||
pc(' ');
|
||||
ps(F->strtab[*p++]);
|
||||
break;
|
||||
|
||||
case OP_GETLOCAL:
|
||||
case OP_SETLOCAL:
|
||||
case OP_DELLOCAL:
|
||||
printf(" %s", F->vartab[*p++ - 1]);
|
||||
break;
|
||||
|
||||
case OP_CLOSURE:
|
||||
case OP_CALL:
|
||||
case OP_NEW:
|
||||
case OP_JUMP:
|
||||
case OP_JTRUE:
|
||||
case OP_JFALSE:
|
||||
case OP_JCASE:
|
||||
case OP_TRY:
|
||||
printf(" %ld", (long)*p++);
|
||||
break;
|
||||
}
|
||||
|
||||
nl();
|
||||
}
|
||||
printf("}\n");
|
||||
|
||||
for (i = 0; i < F->funlen; ++i) {
|
||||
if (F->funtab[i] != F) {
|
||||
printf("function %d ", i);
|
||||
jsC_dumpfunction(J, F->funtab[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Runtime values */
|
||||
|
||||
void js_dumpvalue(js_State *J, js_Value v)
|
||||
{
|
||||
minify = 0;
|
||||
switch (v.type) {
|
||||
case JS_TUNDEFINED: printf("undefined"); break;
|
||||
case JS_TNULL: printf("null"); break;
|
||||
case JS_TBOOLEAN: printf(v.u.boolean ? "true" : "false"); break;
|
||||
case JS_TNUMBER: printf("%.9g", v.u.number); break;
|
||||
case JS_TSHRSTR: printf("'%s'", v.u.shrstr); break;
|
||||
case JS_TLITSTR: printf("'%s'", v.u.litstr); break;
|
||||
case JS_TMEMSTR: printf("'%s'", v.u.memstr->p); break;
|
||||
case JS_TOBJECT:
|
||||
if (v.u.object == J->G) {
|
||||
printf("[Global]");
|
||||
break;
|
||||
}
|
||||
switch (v.u.object->type) {
|
||||
case JS_COBJECT: printf("[Object %p]", (void*)v.u.object); break;
|
||||
case JS_CARRAY: printf("[Array %p]", (void*)v.u.object); break;
|
||||
case JS_CFUNCTION:
|
||||
printf("[Function %p, %s, %s:%d]",
|
||||
(void*)v.u.object,
|
||||
v.u.object->u.f.function->name,
|
||||
v.u.object->u.f.function->filename,
|
||||
v.u.object->u.f.function->line);
|
||||
break;
|
||||
case JS_CSCRIPT: printf("[Script %s]", v.u.object->u.f.function->filename); break;
|
||||
case JS_CEVAL: printf("[Eval %s]", v.u.object->u.f.function->filename); break;
|
||||
case JS_CCFUNCTION: printf("[CFunction %s]", v.u.object->u.c.name); break;
|
||||
case JS_CBOOLEAN: printf("[Boolean %d]", v.u.object->u.boolean); break;
|
||||
case JS_CNUMBER: printf("[Number %g]", v.u.object->u.number); break;
|
||||
case JS_CSTRING: printf("[String'%s']", v.u.object->u.s.string); break;
|
||||
case JS_CERROR: printf("[Error]"); break;
|
||||
case JS_CARGUMENTS: printf("[Arguments %p]", (void*)v.u.object); break;
|
||||
case JS_CITERATOR: printf("[Iterator %p]", (void*)v.u.object); break;
|
||||
case JS_CUSERDATA:
|
||||
printf("[Userdata %s %p]", v.u.object->u.user.tag, v.u.object->u.user.data);
|
||||
break;
|
||||
default: printf("[Object %p]", (void*)v.u.object); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void js_dumpproperty(js_State *J, js_Property *node)
|
||||
{
|
||||
minify = 0;
|
||||
if (node->left->level)
|
||||
js_dumpproperty(J, node->left);
|
||||
printf("\t%s: ", node->name);
|
||||
js_dumpvalue(J, node->value);
|
||||
printf(",\n");
|
||||
if (node->right->level)
|
||||
js_dumpproperty(J, node->right);
|
||||
}
|
||||
|
||||
void js_dumpobject(js_State *J, js_Object *obj)
|
||||
{
|
||||
minify = 0;
|
||||
printf("{\n");
|
||||
if (obj->properties->level)
|
||||
js_dumpproperty(J, obj->properties);
|
||||
printf("}\n");
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#define QQ(X) #X
|
||||
#define Q(X) QQ(X)
|
||||
|
||||
static int jsB_stacktrace(js_State *J, int skip)
|
||||
{
|
||||
char buf[256];
|
||||
int n = J->tracetop - skip;
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
for (; n > 0; --n) {
|
||||
const char *name = J->trace[n].name;
|
||||
const char *file = J->trace[n].file;
|
||||
int line = J->trace[n].line;
|
||||
if (line > 0) {
|
||||
if (name[0])
|
||||
snprintf(buf, sizeof buf, "\n\tat %s (%s:%d)", name, file, line);
|
||||
else
|
||||
snprintf(buf, sizeof buf, "\n\tat %s:%d", file, line);
|
||||
} else
|
||||
snprintf(buf, sizeof buf, "\n\tat %s (%s)", name, file);
|
||||
js_pushstring(J, buf);
|
||||
if (n < J->tracetop - skip)
|
||||
js_concat(J);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void Ep_toString(js_State *J)
|
||||
{
|
||||
const char *name = "Error";
|
||||
const char *message = "";
|
||||
|
||||
if (!js_isobject(J, -1))
|
||||
js_typeerror(J, "not an object");
|
||||
|
||||
if (js_hasproperty(J, 0, "name"))
|
||||
name = js_tostring(J, -1);
|
||||
if (js_hasproperty(J, 0, "message"))
|
||||
message = js_tostring(J, -1);
|
||||
|
||||
if (name[0] == 0)
|
||||
js_pushstring(J, message);
|
||||
else if (message[0] == 0)
|
||||
js_pushstring(J, name);
|
||||
else {
|
||||
js_pushstring(J, name);
|
||||
js_pushstring(J, ": ");
|
||||
js_concat(J);
|
||||
js_pushstring(J, message);
|
||||
js_concat(J);
|
||||
}
|
||||
}
|
||||
|
||||
static int jsB_ErrorX(js_State *J, js_Object *prototype)
|
||||
{
|
||||
int top = js_gettop(J);
|
||||
js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
|
||||
if (top > 1) {
|
||||
js_pushstring(J, js_tostring(J, 1));
|
||||
js_defproperty(J, -2, "message", JS_DONTENUM);
|
||||
}
|
||||
if (jsB_stacktrace(J, 1))
|
||||
js_defproperty(J, -2, "stackTrace", JS_DONTENUM);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void js_newerrorx(js_State *J, const char *message, js_Object *prototype)
|
||||
{
|
||||
js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
|
||||
js_pushstring(J, message);
|
||||
js_setproperty(J, -2, "message");
|
||||
if (jsB_stacktrace(J, 0))
|
||||
js_setproperty(J, -2, "stackTrace");
|
||||
}
|
||||
|
||||
#define DERROR(name, Name) \
|
||||
static void jsB_##Name(js_State *J) { \
|
||||
jsB_ErrorX(J, J->Name##_prototype); \
|
||||
} \
|
||||
void js_new##name(js_State *J, const char *s) { \
|
||||
js_newerrorx(J, s, J->Name##_prototype); \
|
||||
} \
|
||||
void js_##name(js_State *J, const char *fmt, ...) { \
|
||||
va_list ap; \
|
||||
char buf[256]; \
|
||||
va_start(ap, fmt); \
|
||||
vsnprintf(buf, sizeof buf, fmt, ap); \
|
||||
va_end(ap); \
|
||||
js_newerrorx(J, buf, J->Name##_prototype); \
|
||||
js_throw(J); \
|
||||
}
|
||||
|
||||
DERROR(error, Error)
|
||||
DERROR(evalerror, EvalError)
|
||||
DERROR(rangeerror, RangeError)
|
||||
DERROR(referenceerror, ReferenceError)
|
||||
DERROR(syntaxerror, SyntaxError)
|
||||
DERROR(typeerror, TypeError)
|
||||
DERROR(urierror, URIError)
|
||||
|
||||
#undef DERROR
|
||||
|
||||
void jsB_initerror(js_State *J)
|
||||
{
|
||||
js_pushobject(J, J->Error_prototype);
|
||||
{
|
||||
jsB_props(J, "name", "Error");
|
||||
jsB_props(J, "message", "an error has occurred");
|
||||
jsB_propf(J, "Error.prototype.toString", Ep_toString, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1);
|
||||
js_defglobal(J, "Error", JS_DONTENUM);
|
||||
|
||||
#define IERROR(NAME) \
|
||||
js_pushobject(J, J->NAME##_prototype); \
|
||||
jsB_props(J, "name", Q(NAME)); \
|
||||
js_newcconstructor(J, jsB_##NAME, jsB_##NAME, Q(NAME), 1); \
|
||||
js_defglobal(J, Q(NAME), JS_DONTENUM);
|
||||
|
||||
IERROR(EvalError);
|
||||
IERROR(RangeError);
|
||||
IERROR(ReferenceError);
|
||||
IERROR(SyntaxError);
|
||||
IERROR(TypeError);
|
||||
IERROR(URIError);
|
||||
|
||||
#undef IERROR
|
||||
}
|
@ -1,229 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static void jsB_Function(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
js_Buffer *sb = NULL;
|
||||
const char *body;
|
||||
js_Ast *parse;
|
||||
js_Function *fun;
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
jsP_freeparse(J);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
/* p1, p2, ..., pn */
|
||||
if (top > 2) {
|
||||
for (i = 1; i < top - 1; ++i) {
|
||||
if (i > 1)
|
||||
js_putc(J, &sb, ',');
|
||||
js_puts(J, &sb, js_tostring(J, i));
|
||||
}
|
||||
js_putc(J, &sb, ')');
|
||||
js_putc(J, &sb, 0);
|
||||
}
|
||||
|
||||
/* body */
|
||||
body = js_isdefined(J, top - 1) ? js_tostring(J, top - 1) : "";
|
||||
|
||||
parse = jsP_parsefunction(J, "[string]", sb ? sb->s : NULL, body);
|
||||
fun = jsC_compilefunction(J, parse);
|
||||
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
jsP_freeparse(J);
|
||||
|
||||
js_newfunction(J, fun, J->GE);
|
||||
}
|
||||
|
||||
static void jsB_Function_prototype(js_State *J)
|
||||
{
|
||||
js_pushundefined(J);
|
||||
}
|
||||
|
||||
static void Fp_toString(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
js_Buffer *sb = NULL;
|
||||
int i;
|
||||
|
||||
if (!js_iscallable(J, 0))
|
||||
js_typeerror(J, "not a function");
|
||||
|
||||
if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT || self->type == JS_CEVAL) {
|
||||
js_Function *F = self->u.f.function;
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
js_puts(J, &sb, "function ");
|
||||
js_puts(J, &sb, F->name);
|
||||
js_putc(J, &sb, '(');
|
||||
for (i = 0; i < F->numparams; ++i) {
|
||||
if (i > 0) js_putc(J, &sb, ',');
|
||||
js_puts(J, &sb, F->vartab[i]);
|
||||
}
|
||||
js_puts(J, &sb, ") { [byte code] }");
|
||||
js_putc(J, &sb, 0);
|
||||
|
||||
js_pushstring(J, sb->s);
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
} else if (self->type == JS_CCFUNCTION) {
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
js_puts(J, &sb, "function ");
|
||||
js_puts(J, &sb, self->u.c.name);
|
||||
js_puts(J, &sb, "() { [native code] }");
|
||||
js_putc(J, &sb, 0);
|
||||
|
||||
js_pushstring(J, sb->s);
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
} else {
|
||||
js_pushliteral(J, "function () { }");
|
||||
}
|
||||
}
|
||||
|
||||
static void Fp_apply(js_State *J)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if (!js_iscallable(J, 0))
|
||||
js_typeerror(J, "not a function");
|
||||
|
||||
js_copy(J, 0);
|
||||
js_copy(J, 1);
|
||||
|
||||
if (js_isnull(J, 2) || js_isundefined(J, 2)) {
|
||||
n = 0;
|
||||
} else {
|
||||
n = js_getlength(J, 2);
|
||||
for (i = 0; i < n; ++i)
|
||||
js_getindex(J, 2, i);
|
||||
}
|
||||
|
||||
js_call(J, n);
|
||||
}
|
||||
|
||||
static void Fp_call(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
|
||||
if (!js_iscallable(J, 0))
|
||||
js_typeerror(J, "not a function");
|
||||
|
||||
for (i = 0; i < top; ++i)
|
||||
js_copy(J, i);
|
||||
|
||||
js_call(J, top - 2);
|
||||
}
|
||||
|
||||
static void callbound(js_State *J)
|
||||
{
|
||||
int top = js_gettop(J);
|
||||
int i, fun, args, n;
|
||||
|
||||
fun = js_gettop(J);
|
||||
js_currentfunction(J);
|
||||
js_getproperty(J, fun, "__TargetFunction__");
|
||||
js_getproperty(J, fun, "__BoundThis__");
|
||||
|
||||
args = js_gettop(J);
|
||||
js_getproperty(J, fun, "__BoundArguments__");
|
||||
n = js_getlength(J, args);
|
||||
for (i = 0; i < n; ++i)
|
||||
js_getindex(J, args, i);
|
||||
js_remove(J, args);
|
||||
|
||||
for (i = 1; i < top; ++i)
|
||||
js_copy(J, i);
|
||||
|
||||
js_call(J, n + top - 1);
|
||||
}
|
||||
|
||||
static void constructbound(js_State *J)
|
||||
{
|
||||
int top = js_gettop(J);
|
||||
int i, fun, args, n;
|
||||
|
||||
fun = js_gettop(J);
|
||||
js_currentfunction(J);
|
||||
js_getproperty(J, fun, "__TargetFunction__");
|
||||
|
||||
args = js_gettop(J);
|
||||
js_getproperty(J, fun, "__BoundArguments__");
|
||||
n = js_getlength(J, args);
|
||||
for (i = 0; i < n; ++i)
|
||||
js_getindex(J, args, i);
|
||||
js_remove(J, args);
|
||||
|
||||
for (i = 1; i < top; ++i)
|
||||
js_copy(J, i);
|
||||
|
||||
js_construct(J, n + top - 1);
|
||||
}
|
||||
|
||||
static void Fp_bind(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
int n;
|
||||
|
||||
if (!js_iscallable(J, 0))
|
||||
js_typeerror(J, "not a function");
|
||||
|
||||
n = js_getlength(J, 0);
|
||||
if (n > top - 2)
|
||||
n -= top - 2;
|
||||
else
|
||||
n = 0;
|
||||
|
||||
/* Reuse target function's prototype for HasInstance check. */
|
||||
js_getproperty(J, 0, "prototype");
|
||||
js_newcconstructor(J, callbound, constructbound, "[bind]", n);
|
||||
|
||||
/* target function */
|
||||
js_copy(J, 0);
|
||||
js_defproperty(J, -2, "__TargetFunction__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
|
||||
/* bound this */
|
||||
js_copy(J, 1);
|
||||
js_defproperty(J, -2, "__BoundThis__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
|
||||
/* bound arguments */
|
||||
js_newarray(J);
|
||||
for (i = 2; i < top; ++i) {
|
||||
js_copy(J, i);
|
||||
js_setindex(J, -2, i - 2);
|
||||
}
|
||||
js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
}
|
||||
|
||||
void jsB_initfunction(js_State *J)
|
||||
{
|
||||
J->Function_prototype->u.c.name = "Function.prototype";
|
||||
J->Function_prototype->u.c.function = jsB_Function_prototype;
|
||||
J->Function_prototype->u.c.constructor = NULL;
|
||||
J->Function_prototype->u.c.length = 0;
|
||||
|
||||
js_pushobject(J, J->Function_prototype);
|
||||
{
|
||||
jsB_propf(J, "Function.prototype.toString", Fp_toString, 2);
|
||||
jsB_propf(J, "Function.prototype.apply", Fp_apply, 2);
|
||||
jsB_propf(J, "Function.prototype.call", Fp_call, 1);
|
||||
jsB_propf(J, "Function.prototype.bind", Fp_bind, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Function, jsB_Function, "Function", 1);
|
||||
js_defglobal(J, "Function", JS_DONTENUM);
|
||||
}
|
@ -1,278 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsrun.h"
|
||||
|
||||
#include "regexp.h"
|
||||
|
||||
static void jsG_freeenvironment(js_State *J, js_Environment *env)
|
||||
{
|
||||
js_free(J, env);
|
||||
}
|
||||
|
||||
static void jsG_freefunction(js_State *J, js_Function *fun)
|
||||
{
|
||||
js_free(J, fun->funtab);
|
||||
js_free(J, fun->numtab);
|
||||
js_free(J, fun->strtab);
|
||||
js_free(J, fun->vartab);
|
||||
js_free(J, fun->code);
|
||||
js_free(J, fun);
|
||||
}
|
||||
|
||||
static void jsG_freeproperty(js_State *J, js_Property *node)
|
||||
{
|
||||
if (node->left->level) jsG_freeproperty(J, node->left);
|
||||
if (node->right->level) jsG_freeproperty(J, node->right);
|
||||
js_free(J, node);
|
||||
}
|
||||
|
||||
static void jsG_freeiterator(js_State *J, js_Iterator *node)
|
||||
{
|
||||
while (node) {
|
||||
js_Iterator *next = node->next;
|
||||
js_free(J, node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void jsG_freeobject(js_State *J, js_Object *obj)
|
||||
{
|
||||
if (obj->properties->level)
|
||||
jsG_freeproperty(J, obj->properties);
|
||||
if (obj->type == JS_CREGEXP) {
|
||||
js_free(J, obj->u.r.source);
|
||||
js_regfreex(J->alloc, J->actx, obj->u.r.prog);
|
||||
}
|
||||
if (obj->type == JS_CITERATOR)
|
||||
jsG_freeiterator(J, obj->u.iter.head);
|
||||
if (obj->type == JS_CUSERDATA && obj->u.user.finalize)
|
||||
obj->u.user.finalize(J, obj->u.user.data);
|
||||
js_free(J, obj);
|
||||
}
|
||||
|
||||
/* Mark and add object to scan queue */
|
||||
static void jsG_markobject(js_State *J, int mark, js_Object *obj)
|
||||
{
|
||||
obj->gcmark = mark;
|
||||
obj->gcroot = J->gcroot;
|
||||
J->gcroot = obj;
|
||||
}
|
||||
|
||||
static void jsG_markfunction(js_State *J, int mark, js_Function *fun)
|
||||
{
|
||||
int i;
|
||||
fun->gcmark = mark;
|
||||
for (i = 0; i < fun->funlen; ++i)
|
||||
if (fun->funtab[i]->gcmark != mark)
|
||||
jsG_markfunction(J, mark, fun->funtab[i]);
|
||||
}
|
||||
|
||||
static void jsG_markenvironment(js_State *J, int mark, js_Environment *env)
|
||||
{
|
||||
do {
|
||||
env->gcmark = mark;
|
||||
if (env->variables->gcmark != mark)
|
||||
jsG_markobject(J, mark, env->variables);
|
||||
env = env->outer;
|
||||
} while (env && env->gcmark != mark);
|
||||
}
|
||||
|
||||
static void jsG_markproperty(js_State *J, int mark, js_Property *node)
|
||||
{
|
||||
if (node->left->level) jsG_markproperty(J, mark, node->left);
|
||||
if (node->right->level) jsG_markproperty(J, mark, node->right);
|
||||
|
||||
if (node->value.type == JS_TMEMSTR && node->value.u.memstr->gcmark != mark)
|
||||
node->value.u.memstr->gcmark = mark;
|
||||
if (node->value.type == JS_TOBJECT && node->value.u.object->gcmark != mark)
|
||||
jsG_markobject(J, mark, node->value.u.object);
|
||||
if (node->getter && node->getter->gcmark != mark)
|
||||
jsG_markobject(J, mark, node->getter);
|
||||
if (node->setter && node->setter->gcmark != mark)
|
||||
jsG_markobject(J, mark, node->setter);
|
||||
}
|
||||
|
||||
/* Mark everything the object can reach. */
|
||||
static void jsG_scanobject(js_State *J, int mark, js_Object *obj)
|
||||
{
|
||||
if (obj->properties->level)
|
||||
jsG_markproperty(J, mark, obj->properties);
|
||||
if (obj->prototype && obj->prototype->gcmark != mark)
|
||||
jsG_markobject(J, mark, obj->prototype);
|
||||
if (obj->type == JS_CITERATOR && obj->u.iter.target->gcmark != mark) {
|
||||
jsG_markobject(J, mark, obj->u.iter.target);
|
||||
}
|
||||
if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT || obj->type == JS_CEVAL) {
|
||||
if (obj->u.f.scope && obj->u.f.scope->gcmark != mark)
|
||||
jsG_markenvironment(J, mark, obj->u.f.scope);
|
||||
if (obj->u.f.function && obj->u.f.function->gcmark != mark)
|
||||
jsG_markfunction(J, mark, obj->u.f.function);
|
||||
}
|
||||
}
|
||||
|
||||
static void jsG_markstack(js_State *J, int mark)
|
||||
{
|
||||
js_Value *v = J->stack;
|
||||
int n = J->top;
|
||||
while (n--) {
|
||||
if (v->type == JS_TMEMSTR && v->u.memstr->gcmark != mark)
|
||||
v->u.memstr->gcmark = mark;
|
||||
if (v->type == JS_TOBJECT && v->u.object->gcmark != mark)
|
||||
jsG_markobject(J, mark, v->u.object);
|
||||
++v;
|
||||
}
|
||||
}
|
||||
|
||||
void js_gc(js_State *J, int report)
|
||||
{
|
||||
js_Function *fun, *nextfun, **prevnextfun;
|
||||
js_Object *obj, *nextobj, **prevnextobj;
|
||||
js_String *str, *nextstr, **prevnextstr;
|
||||
js_Environment *env, *nextenv, **prevnextenv;
|
||||
unsigned int nenv = 0, nfun = 0, nobj = 0, nstr = 0, nprop = 0;
|
||||
unsigned int genv = 0, gfun = 0, gobj = 0, gstr = 0, gprop = 0;
|
||||
int mark;
|
||||
int i;
|
||||
|
||||
if (J->gcpause) {
|
||||
if (report)
|
||||
js_report(J, "garbage collector is paused");
|
||||
return;
|
||||
}
|
||||
|
||||
mark = J->gcmark = J->gcmark == 1 ? 2 : 1;
|
||||
|
||||
/* Add initial roots. */
|
||||
|
||||
jsG_markobject(J, mark, J->Object_prototype);
|
||||
jsG_markobject(J, mark, J->Array_prototype);
|
||||
jsG_markobject(J, mark, J->Function_prototype);
|
||||
jsG_markobject(J, mark, J->Boolean_prototype);
|
||||
jsG_markobject(J, mark, J->Number_prototype);
|
||||
jsG_markobject(J, mark, J->String_prototype);
|
||||
jsG_markobject(J, mark, J->RegExp_prototype);
|
||||
jsG_markobject(J, mark, J->Date_prototype);
|
||||
|
||||
jsG_markobject(J, mark, J->Error_prototype);
|
||||
jsG_markobject(J, mark, J->EvalError_prototype);
|
||||
jsG_markobject(J, mark, J->RangeError_prototype);
|
||||
jsG_markobject(J, mark, J->ReferenceError_prototype);
|
||||
jsG_markobject(J, mark, J->SyntaxError_prototype);
|
||||
jsG_markobject(J, mark, J->TypeError_prototype);
|
||||
jsG_markobject(J, mark, J->URIError_prototype);
|
||||
|
||||
jsG_markobject(J, mark, J->R);
|
||||
jsG_markobject(J, mark, J->G);
|
||||
|
||||
jsG_markstack(J, mark);
|
||||
|
||||
jsG_markenvironment(J, mark, J->E);
|
||||
jsG_markenvironment(J, mark, J->GE);
|
||||
for (i = 0; i < J->envtop; ++i)
|
||||
jsG_markenvironment(J, mark, J->envstack[i]);
|
||||
|
||||
/* Scan objects until none remain. */
|
||||
|
||||
while ((obj = J->gcroot) != NULL) {
|
||||
J->gcroot = obj->gcroot;
|
||||
obj->gcroot = NULL;
|
||||
jsG_scanobject(J, mark, obj);
|
||||
}
|
||||
|
||||
/* Free everything not marked. */
|
||||
|
||||
prevnextenv = &J->gcenv;
|
||||
for (env = J->gcenv; env; env = nextenv) {
|
||||
nextenv = env->gcnext;
|
||||
if (env->gcmark != mark) {
|
||||
*prevnextenv = nextenv;
|
||||
jsG_freeenvironment(J, env);
|
||||
++genv;
|
||||
} else {
|
||||
prevnextenv = &env->gcnext;
|
||||
}
|
||||
++nenv;
|
||||
}
|
||||
|
||||
prevnextfun = &J->gcfun;
|
||||
for (fun = J->gcfun; fun; fun = nextfun) {
|
||||
nextfun = fun->gcnext;
|
||||
if (fun->gcmark != mark) {
|
||||
*prevnextfun = nextfun;
|
||||
jsG_freefunction(J, fun);
|
||||
++gfun;
|
||||
} else {
|
||||
prevnextfun = &fun->gcnext;
|
||||
}
|
||||
++nfun;
|
||||
}
|
||||
|
||||
prevnextobj = &J->gcobj;
|
||||
for (obj = J->gcobj; obj; obj = nextobj) {
|
||||
nprop += obj->count;
|
||||
nextobj = obj->gcnext;
|
||||
if (obj->gcmark != mark) {
|
||||
gprop += obj->count;
|
||||
*prevnextobj = nextobj;
|
||||
jsG_freeobject(J, obj);
|
||||
++gobj;
|
||||
} else {
|
||||
prevnextobj = &obj->gcnext;
|
||||
}
|
||||
++nobj;
|
||||
}
|
||||
|
||||
prevnextstr = &J->gcstr;
|
||||
for (str = J->gcstr; str; str = nextstr) {
|
||||
nextstr = str->gcnext;
|
||||
if (str->gcmark != mark) {
|
||||
*prevnextstr = nextstr;
|
||||
js_free(J, str);
|
||||
++gstr;
|
||||
} else {
|
||||
prevnextstr = &str->gcnext;
|
||||
}
|
||||
++nstr;
|
||||
}
|
||||
|
||||
unsigned int ntot = nenv + nfun + nobj + nstr + nprop;
|
||||
unsigned int gtot = genv + gfun + gobj + gstr + gprop;
|
||||
unsigned int remaining = ntot - gtot;
|
||||
|
||||
J->gccounter = remaining;
|
||||
J->gcthresh = remaining * JS_GCFACTOR;
|
||||
|
||||
if (report) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof buf, "garbage collected (%d%%): %d/%d envs, %d/%d funs, %d/%d objs, %d/%d props, %d/%d strs",
|
||||
100*gtot/ntot, genv, nenv, gfun, nfun, gobj, nobj, gprop, nprop, gstr, nstr);
|
||||
js_report(J, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void js_freestate(js_State *J)
|
||||
{
|
||||
js_Function *fun, *nextfun;
|
||||
js_Object *obj, *nextobj;
|
||||
js_Environment *env, *nextenv;
|
||||
js_String *str, *nextstr;
|
||||
|
||||
if (!J)
|
||||
return;
|
||||
|
||||
for (env = J->gcenv; env; env = nextenv)
|
||||
nextenv = env->gcnext, jsG_freeenvironment(J, env);
|
||||
for (fun = J->gcfun; fun; fun = nextfun)
|
||||
nextfun = fun->gcnext, jsG_freefunction(J, fun);
|
||||
for (obj = J->gcobj; obj; obj = nextobj)
|
||||
nextobj = obj->gcnext, jsG_freeobject(J, obj);
|
||||
for (str = J->gcstr; str; str = nextstr)
|
||||
nextstr = str->gcnext, js_free(J, str);
|
||||
|
||||
jsS_freestrings(J);
|
||||
|
||||
js_free(J, J->lexbuf.text);
|
||||
J->alloc(J->actx, J->stack, 0);
|
||||
J->alloc(J->actx, J, 0);
|
||||
}
|
@ -1,265 +0,0 @@
|
||||
#ifndef jsi_h
|
||||
#define jsi_h
|
||||
|
||||
#include "mujs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Microsoft Visual C */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4996) /* _CRT_SECURE_NO_WARNINGS */
|
||||
#pragma warning(disable:4244) /* implicit conversion from double to int */
|
||||
#pragma warning(disable:4267) /* implicit conversion of int to smaller int */
|
||||
#define inline __inline
|
||||
#if _MSC_VER < 1900 /* MSVC 2015 */
|
||||
#define snprintf jsW_snprintf
|
||||
#define vsnprintf jsW_vsnprintf
|
||||
static int jsW_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
|
||||
{
|
||||
int n;
|
||||
n = _vsnprintf(str, size, fmt, ap);
|
||||
str[size-1] = 0;
|
||||
return n;
|
||||
}
|
||||
static int jsW_snprintf(char *str, size_t size, const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
n = jsW_vsnprintf(str, size, fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
#if _MSC_VER <= 1700 /* <= MSVC 2012 */
|
||||
#define isnan(x) _isnan(x)
|
||||
#define isinf(x) (!_finite(x))
|
||||
#define isfinite(x) _finite(x)
|
||||
static __inline int signbit(double x) { __int64 i; memcpy(&i, &x, 8); return i>>63; }
|
||||
#define INFINITY (DBL_MAX+DBL_MAX)
|
||||
#define NAN (INFINITY-INFINITY)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define soffsetof(x,y) ((int)offsetof(x,y))
|
||||
#define nelem(a) (int)(sizeof (a) / sizeof (a)[0])
|
||||
|
||||
void *js_malloc(js_State *J, int size);
|
||||
void *js_realloc(js_State *J, void *ptr, int size);
|
||||
void js_free(js_State *J, void *ptr);
|
||||
|
||||
typedef struct js_Regexp js_Regexp;
|
||||
typedef struct js_Value js_Value;
|
||||
typedef struct js_Object js_Object;
|
||||
typedef struct js_String js_String;
|
||||
typedef struct js_Ast js_Ast;
|
||||
typedef struct js_Function js_Function;
|
||||
typedef struct js_Environment js_Environment;
|
||||
typedef struct js_StringNode js_StringNode;
|
||||
typedef struct js_Jumpbuf js_Jumpbuf;
|
||||
typedef struct js_StackTrace js_StackTrace;
|
||||
|
||||
/* Limits */
|
||||
|
||||
#ifndef JS_STACKSIZE
|
||||
#define JS_STACKSIZE 256 /* value stack size */
|
||||
#endif
|
||||
#ifndef JS_ENVLIMIT
|
||||
#define JS_ENVLIMIT 128 /* environment stack size */
|
||||
#endif
|
||||
#ifndef JS_TRYLIMIT
|
||||
#define JS_TRYLIMIT 64 /* exception stack size */
|
||||
#endif
|
||||
#ifndef JS_GCFACTOR
|
||||
/*
|
||||
* GC will try to trigger when memory usage is this value times the minimum
|
||||
* needed memory. E.g. if there are 100 remaining objects after GC and this
|
||||
* value is 5.0, then the next GC will trigger when the overall number is 500.
|
||||
* I.e. a value of 5.0 aims at 80% garbage, 20% remain-used on each GC.
|
||||
* The bigger the value the less impact GC has on overall performance, but more
|
||||
* memory is used and individual GC pauses are longer (but fewer).
|
||||
*/
|
||||
#define JS_GCFACTOR 5.0 /* memory overhead factor >= 1.0 */
|
||||
#endif
|
||||
#ifndef JS_ASTLIMIT
|
||||
#define JS_ASTLIMIT 100 /* max nested expressions */
|
||||
#endif
|
||||
|
||||
/* instruction size -- change to int if you get integer overflow syntax errors */
|
||||
|
||||
#ifdef JS_INSTRUCTION
|
||||
typedef JS_INSTRUCTION js_Instruction;
|
||||
#else
|
||||
typedef unsigned short js_Instruction;
|
||||
#endif
|
||||
|
||||
/* String interning */
|
||||
|
||||
char *js_strdup(js_State *J, const char *s);
|
||||
const char *js_intern(js_State *J, const char *s);
|
||||
void jsS_dumpstrings(js_State *J);
|
||||
void jsS_freestrings(js_State *J);
|
||||
|
||||
/* Portable strtod and printf float formatting */
|
||||
|
||||
void js_fmtexp(char *p, int e);
|
||||
int js_grisu2(double v, char *buffer, int *K);
|
||||
double js_strtod(const char *as, char **aas);
|
||||
|
||||
/* Private stack functions */
|
||||
|
||||
void js_newarguments(js_State *J);
|
||||
void js_newfunction(js_State *J, js_Function *function, js_Environment *scope);
|
||||
void js_newscript(js_State *J, js_Function *fun, js_Environment *scope, int type);
|
||||
void js_loadeval(js_State *J, const char *filename, const char *source);
|
||||
|
||||
js_Regexp *js_toregexp(js_State *J, int idx);
|
||||
int js_isarrayindex(js_State *J, const char *str, int *idx);
|
||||
int js_runeat(js_State *J, const char *s, int i);
|
||||
int js_utfptrtoidx(const char *s, const char *p);
|
||||
const char *js_utfidxtoptr(const char *s, int i);
|
||||
|
||||
void js_dup(js_State *J);
|
||||
void js_dup2(js_State *J);
|
||||
void js_rot2(js_State *J);
|
||||
void js_rot3(js_State *J);
|
||||
void js_rot4(js_State *J);
|
||||
void js_rot2pop1(js_State *J);
|
||||
void js_rot3pop2(js_State *J);
|
||||
void js_dup1rot3(js_State *J);
|
||||
void js_dup1rot4(js_State *J);
|
||||
|
||||
void js_RegExp_prototype_exec(js_State *J, js_Regexp *re, const char *text);
|
||||
|
||||
void js_trap(js_State *J, int pc); /* dump stack and environment to stdout */
|
||||
|
||||
struct js_StackTrace
|
||||
{
|
||||
const char *name;
|
||||
const char *file;
|
||||
int line;
|
||||
};
|
||||
|
||||
/* Exception handling */
|
||||
|
||||
struct js_Jumpbuf
|
||||
{
|
||||
jmp_buf buf;
|
||||
js_Environment *E;
|
||||
int envtop;
|
||||
int tracetop;
|
||||
int top, bot;
|
||||
int strict;
|
||||
js_Instruction *pc;
|
||||
};
|
||||
|
||||
void *js_savetrypc(js_State *J, js_Instruction *pc);
|
||||
|
||||
#define js_trypc(J, PC) \
|
||||
setjmp(js_savetrypc(J, PC))
|
||||
|
||||
/* String buffer */
|
||||
|
||||
typedef struct js_Buffer { int n, m; char s[64]; } js_Buffer;
|
||||
|
||||
void js_putc(js_State *J, js_Buffer **sbp, int c);
|
||||
void js_puts(js_State *J, js_Buffer **sb, const char *s);
|
||||
void js_putm(js_State *J, js_Buffer **sb, const char *s, const char *e);
|
||||
|
||||
/* State struct */
|
||||
|
||||
struct js_State
|
||||
{
|
||||
void *actx;
|
||||
void *uctx;
|
||||
js_Alloc alloc;
|
||||
js_Report report;
|
||||
js_Panic panic;
|
||||
|
||||
js_StringNode *strings;
|
||||
|
||||
int default_strict;
|
||||
int strict;
|
||||
|
||||
/* parser input source */
|
||||
const char *filename;
|
||||
const char *source;
|
||||
int line;
|
||||
|
||||
/* lexer state */
|
||||
struct { char *text; int len, cap; } lexbuf;
|
||||
int lexline;
|
||||
int lexchar;
|
||||
int lasttoken;
|
||||
int newline;
|
||||
|
||||
/* parser state */
|
||||
int astdepth;
|
||||
int lookahead;
|
||||
const char *text;
|
||||
double number;
|
||||
js_Ast *gcast; /* list of allocated nodes to free after parsing */
|
||||
|
||||
/* runtime environment */
|
||||
js_Object *Object_prototype;
|
||||
js_Object *Array_prototype;
|
||||
js_Object *Function_prototype;
|
||||
js_Object *Boolean_prototype;
|
||||
js_Object *Number_prototype;
|
||||
js_Object *String_prototype;
|
||||
js_Object *RegExp_prototype;
|
||||
js_Object *Date_prototype;
|
||||
|
||||
js_Object *Error_prototype;
|
||||
js_Object *EvalError_prototype;
|
||||
js_Object *RangeError_prototype;
|
||||
js_Object *ReferenceError_prototype;
|
||||
js_Object *SyntaxError_prototype;
|
||||
js_Object *TypeError_prototype;
|
||||
js_Object *URIError_prototype;
|
||||
|
||||
unsigned int seed; /* Math.random seed */
|
||||
|
||||
int nextref; /* for js_ref use */
|
||||
js_Object *R; /* registry of hidden values */
|
||||
js_Object *G; /* the global object */
|
||||
js_Environment *E; /* current environment scope */
|
||||
js_Environment *GE; /* global environment scope (at the root) */
|
||||
|
||||
/* execution stack */
|
||||
int top, bot;
|
||||
js_Value *stack;
|
||||
|
||||
/* garbage collector list */
|
||||
int gcpause;
|
||||
int gcmark;
|
||||
unsigned int gccounter, gcthresh;
|
||||
js_Environment *gcenv;
|
||||
js_Function *gcfun;
|
||||
js_Object *gcobj;
|
||||
js_String *gcstr;
|
||||
|
||||
js_Object *gcroot; /* gc scan list */
|
||||
|
||||
/* environments on the call stack but currently not in scope */
|
||||
int envtop;
|
||||
js_Environment *envstack[JS_ENVLIMIT];
|
||||
|
||||
/* debug info stack trace */
|
||||
int tracetop;
|
||||
js_StackTrace trace[JS_ENVLIMIT];
|
||||
|
||||
/* exception stack */
|
||||
int trytop;
|
||||
js_Jumpbuf trybuf[JS_TRYLIMIT];
|
||||
};
|
||||
|
||||
#endif
|
@ -1,135 +0,0 @@
|
||||
#include "jsi.h"
|
||||
|
||||
/* Dynamically grown string buffer */
|
||||
|
||||
void js_putc(js_State *J, js_Buffer **sbp, int c)
|
||||
{
|
||||
js_Buffer *sb = *sbp;
|
||||
if (!sb) {
|
||||
sb = js_malloc(J, sizeof *sb);
|
||||
sb->n = 0;
|
||||
sb->m = sizeof sb->s;
|
||||
*sbp = sb;
|
||||
} else if (sb->n == sb->m) {
|
||||
sb = js_realloc(J, sb, (sb->m *= 2) + soffsetof(js_Buffer, s));
|
||||
*sbp = sb;
|
||||
}
|
||||
sb->s[sb->n++] = c;
|
||||
}
|
||||
|
||||
void js_puts(js_State *J, js_Buffer **sb, const char *s)
|
||||
{
|
||||
while (*s)
|
||||
js_putc(J, sb, *s++);
|
||||
}
|
||||
|
||||
void js_putm(js_State *J, js_Buffer **sb, const char *s, const char *e)
|
||||
{
|
||||
while (s < e)
|
||||
js_putc(J, sb, *s++);
|
||||
}
|
||||
|
||||
/* Use an AA-tree to quickly look up interned strings. */
|
||||
|
||||
struct js_StringNode
|
||||
{
|
||||
js_StringNode *left, *right;
|
||||
int level;
|
||||
char string[1];
|
||||
};
|
||||
|
||||
static js_StringNode jsS_sentinel = { &jsS_sentinel, &jsS_sentinel, 0, ""};
|
||||
|
||||
static js_StringNode *jsS_newstringnode(js_State *J, const char *string, const char **result)
|
||||
{
|
||||
int n = strlen(string);
|
||||
js_StringNode *node = js_malloc(J, soffsetof(js_StringNode, string) + n + 1);
|
||||
node->left = node->right = &jsS_sentinel;
|
||||
node->level = 1;
|
||||
memcpy(node->string, string, n + 1);
|
||||
return *result = node->string, node;
|
||||
}
|
||||
|
||||
static js_StringNode *jsS_skew(js_StringNode *node)
|
||||
{
|
||||
if (node->left->level == node->level) {
|
||||
js_StringNode *temp = node;
|
||||
node = node->left;
|
||||
temp->left = node->right;
|
||||
node->right = temp;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_StringNode *jsS_split(js_StringNode *node)
|
||||
{
|
||||
if (node->right->right->level == node->level) {
|
||||
js_StringNode *temp = node;
|
||||
node = node->right;
|
||||
temp->right = node->left;
|
||||
node->left = temp;
|
||||
++node->level;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_StringNode *jsS_insert(js_State *J, js_StringNode *node, const char *string, const char **result)
|
||||
{
|
||||
if (node != &jsS_sentinel) {
|
||||
int c = strcmp(string, node->string);
|
||||
if (c < 0)
|
||||
node->left = jsS_insert(J, node->left, string, result);
|
||||
else if (c > 0)
|
||||
node->right = jsS_insert(J, node->right, string, result);
|
||||
else
|
||||
return *result = node->string, node;
|
||||
node = jsS_skew(node);
|
||||
node = jsS_split(node);
|
||||
return node;
|
||||
}
|
||||
return jsS_newstringnode(J, string, result);
|
||||
}
|
||||
|
||||
static void dumpstringnode(js_StringNode *node, int level)
|
||||
{
|
||||
int i;
|
||||
if (node->left != &jsS_sentinel)
|
||||
dumpstringnode(node->left, level + 1);
|
||||
printf("%d: ", node->level);
|
||||
for (i = 0; i < level; ++i)
|
||||
putchar('\t');
|
||||
printf("'%s'\n", node->string);
|
||||
if (node->right != &jsS_sentinel)
|
||||
dumpstringnode(node->right, level + 1);
|
||||
}
|
||||
|
||||
void jsS_dumpstrings(js_State *J)
|
||||
{
|
||||
js_StringNode *root = J->strings;
|
||||
printf("interned strings {\n");
|
||||
if (root && root != &jsS_sentinel)
|
||||
dumpstringnode(root, 1);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
static void jsS_freestringnode(js_State *J, js_StringNode *node)
|
||||
{
|
||||
if (node->left != &jsS_sentinel) jsS_freestringnode(J, node->left);
|
||||
if (node->right != &jsS_sentinel) jsS_freestringnode(J, node->right);
|
||||
js_free(J, node);
|
||||
}
|
||||
|
||||
void jsS_freestrings(js_State *J)
|
||||
{
|
||||
if (J->strings && J->strings != &jsS_sentinel)
|
||||
jsS_freestringnode(J, J->strings);
|
||||
}
|
||||
|
||||
const char *js_intern(js_State *J, const char *s)
|
||||
{
|
||||
const char *result;
|
||||
if (!J->strings)
|
||||
J->strings = &jsS_sentinel;
|
||||
J->strings = jsS_insert(J, J->strings, s, &result);
|
||||
return result;
|
||||
}
|
@ -1,879 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "utf.h"
|
||||
|
||||
JS_NORETURN static void jsY_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
|
||||
|
||||
static void jsY_error(js_State *J, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[512];
|
||||
char msgbuf[256];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msgbuf, 256, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
|
||||
strcat(buf, msgbuf);
|
||||
|
||||
js_newsyntaxerror(J, buf);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
static const char *tokenstring[] = {
|
||||
"(end-of-file)",
|
||||
"'\\x01'", "'\\x02'", "'\\x03'", "'\\x04'", "'\\x05'", "'\\x06'", "'\\x07'",
|
||||
"'\\x08'", "'\\x09'", "'\\x0A'", "'\\x0B'", "'\\x0C'", "'\\x0D'", "'\\x0E'", "'\\x0F'",
|
||||
"'\\x10'", "'\\x11'", "'\\x12'", "'\\x13'", "'\\x14'", "'\\x15'", "'\\x16'", "'\\x17'",
|
||||
"'\\x18'", "'\\x19'", "'\\x1A'", "'\\x1B'", "'\\x1C'", "'\\x1D'", "'\\x1E'", "'\\x1F'",
|
||||
"' '", "'!'", "'\"'", "'#'", "'$'", "'%'", "'&'", "'\\''",
|
||||
"'('", "')'", "'*'", "'+'", "','", "'-'", "'.'", "'/'",
|
||||
"'0'", "'1'", "'2'", "'3'", "'4'", "'5'", "'6'", "'7'",
|
||||
"'8'", "'9'", "':'", "';'", "'<'", "'='", "'>'", "'?'",
|
||||
"'@'", "'A'", "'B'", "'C'", "'D'", "'E'", "'F'", "'G'",
|
||||
"'H'", "'I'", "'J'", "'K'", "'L'", "'M'", "'N'", "'O'",
|
||||
"'P'", "'Q'", "'R'", "'S'", "'T'", "'U'", "'V'", "'W'",
|
||||
"'X'", "'Y'", "'Z'", "'['", "'\'", "']'", "'^'", "'_'",
|
||||
"'`'", "'a'", "'b'", "'c'", "'d'", "'e'", "'f'", "'g'",
|
||||
"'h'", "'i'", "'j'", "'k'", "'l'", "'m'", "'n'", "'o'",
|
||||
"'p'", "'q'", "'r'", "'s'", "'t'", "'u'", "'v'", "'w'",
|
||||
"'x'", "'y'", "'z'", "'{'", "'|'", "'}'", "'~'", "'\\x7F'",
|
||||
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
|
||||
"(identifier)", "(number)", "(string)", "(regexp)",
|
||||
|
||||
"'<='", "'>='", "'=='", "'!='", "'==='", "'!=='",
|
||||
"'<<'", "'>>'", "'>>>'", "'&&'", "'||'",
|
||||
"'+='", "'-='", "'*='", "'/='", "'%='",
|
||||
"'<<='", "'>>='", "'>>>='", "'&='", "'|='", "'^='",
|
||||
"'++'", "'--'",
|
||||
|
||||
"'break'", "'case'", "'catch'", "'continue'", "'debugger'",
|
||||
"'default'", "'delete'", "'do'", "'else'", "'false'", "'finally'", "'for'",
|
||||
"'function'", "'if'", "'in'", "'instanceof'", "'new'", "'null'", "'return'",
|
||||
"'switch'", "'this'", "'throw'", "'true'", "'try'", "'typeof'", "'var'",
|
||||
"'void'", "'while'", "'with'",
|
||||
};
|
||||
|
||||
const char *jsY_tokenstring(int token)
|
||||
{
|
||||
if (token >= 0 && token < (int)nelem(tokenstring))
|
||||
if (tokenstring[token])
|
||||
return tokenstring[token];
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
static const char *keywords[] = {
|
||||
"break", "case", "catch", "continue", "debugger", "default", "delete",
|
||||
"do", "else", "false", "finally", "for", "function", "if", "in",
|
||||
"instanceof", "new", "null", "return", "switch", "this", "throw",
|
||||
"true", "try", "typeof", "var", "void", "while", "with",
|
||||
};
|
||||
|
||||
int jsY_findword(const char *s, const char **list, int num)
|
||||
{
|
||||
int l = 0;
|
||||
int r = num - 1;
|
||||
while (l <= r) {
|
||||
int m = (l + r) >> 1;
|
||||
int c = strcmp(s, list[m]);
|
||||
if (c < 0)
|
||||
r = m - 1;
|
||||
else if (c > 0)
|
||||
l = m + 1;
|
||||
else
|
||||
return m;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int jsY_findkeyword(js_State *J, const char *s)
|
||||
{
|
||||
int i = jsY_findword(s, keywords, nelem(keywords));
|
||||
if (i >= 0) {
|
||||
J->text = keywords[i];
|
||||
return TK_BREAK + i; /* first keyword + i */
|
||||
}
|
||||
J->text = js_intern(J, s);
|
||||
return TK_IDENTIFIER;
|
||||
}
|
||||
|
||||
int jsY_iswhite(int c)
|
||||
{
|
||||
return c == 0x9 || c == 0xB || c == 0xC || c == 0x20 || c == 0xA0 || c == 0xFEFF;
|
||||
}
|
||||
|
||||
int jsY_isnewline(int c)
|
||||
{
|
||||
return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
|
||||
}
|
||||
|
||||
#ifndef isalpha
|
||||
#define isalpha(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
|
||||
#endif
|
||||
#ifndef isdigit
|
||||
#define isdigit(c) (c >= '0' && c <= '9')
|
||||
#endif
|
||||
#ifndef ishex
|
||||
#define ishex(c) ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
|
||||
#endif
|
||||
|
||||
static int jsY_isidentifierstart(int c)
|
||||
{
|
||||
return isalpha(c) || c == '$' || c == '_' || isalpharune(c);
|
||||
}
|
||||
|
||||
static int jsY_isidentifierpart(int c)
|
||||
{
|
||||
return isdigit(c) || isalpha(c) || c == '$' || c == '_' || isalpharune(c);
|
||||
}
|
||||
|
||||
static int jsY_isdec(int c)
|
||||
{
|
||||
return isdigit(c);
|
||||
}
|
||||
|
||||
int jsY_ishex(int c)
|
||||
{
|
||||
return isdigit(c) || ishex(c);
|
||||
}
|
||||
|
||||
int jsY_tohex(int c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 0xA;
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jsY_next(js_State *J)
|
||||
{
|
||||
Rune c;
|
||||
if (*J->source == 0) {
|
||||
J->lexchar = EOF;
|
||||
return;
|
||||
}
|
||||
J->source += chartorune(&c, J->source);
|
||||
/* consume CR LF as one unit */
|
||||
if (c == '\r' && *J->source == '\n')
|
||||
++J->source;
|
||||
if (jsY_isnewline(c)) {
|
||||
J->line++;
|
||||
c = '\n';
|
||||
}
|
||||
J->lexchar = c;
|
||||
}
|
||||
|
||||
#define jsY_accept(J, x) (J->lexchar == x ? (jsY_next(J), 1) : 0)
|
||||
|
||||
#define jsY_expect(J, x) if (!jsY_accept(J, x)) jsY_error(J, "expected '%c'", x)
|
||||
|
||||
static void jsY_unescape(js_State *J)
|
||||
{
|
||||
if (jsY_accept(J, '\\')) {
|
||||
if (jsY_accept(J, 'u')) {
|
||||
int x = 0;
|
||||
if (!jsY_ishex(J->lexchar)) { goto error; } x |= jsY_tohex(J->lexchar) << 12; jsY_next(J);
|
||||
if (!jsY_ishex(J->lexchar)) { goto error; } x |= jsY_tohex(J->lexchar) << 8; jsY_next(J);
|
||||
if (!jsY_ishex(J->lexchar)) { goto error; } x |= jsY_tohex(J->lexchar) << 4; jsY_next(J);
|
||||
if (!jsY_ishex(J->lexchar)) { goto error; } x |= jsY_tohex(J->lexchar);
|
||||
J->lexchar = x;
|
||||
return;
|
||||
}
|
||||
error:
|
||||
jsY_error(J, "unexpected escape sequence");
|
||||
}
|
||||
}
|
||||
|
||||
static void textinit(js_State *J)
|
||||
{
|
||||
if (!J->lexbuf.text) {
|
||||
J->lexbuf.cap = 4096;
|
||||
J->lexbuf.text = js_malloc(J, J->lexbuf.cap);
|
||||
}
|
||||
J->lexbuf.len = 0;
|
||||
}
|
||||
|
||||
static void textpush(js_State *J, Rune c)
|
||||
{
|
||||
int n;
|
||||
if (c == EOF)
|
||||
n = 1;
|
||||
else
|
||||
n = runelen(c);
|
||||
if (J->lexbuf.len + n > J->lexbuf.cap) {
|
||||
J->lexbuf.cap = J->lexbuf.cap * 2;
|
||||
J->lexbuf.text = js_realloc(J, J->lexbuf.text, J->lexbuf.cap);
|
||||
}
|
||||
if (c == EOF)
|
||||
J->lexbuf.text[J->lexbuf.len++] = 0;
|
||||
else
|
||||
J->lexbuf.len += runetochar(J->lexbuf.text + J->lexbuf.len, &c);
|
||||
}
|
||||
|
||||
static char *textend(js_State *J)
|
||||
{
|
||||
textpush(J, EOF);
|
||||
return J->lexbuf.text;
|
||||
}
|
||||
|
||||
static void lexlinecomment(js_State *J)
|
||||
{
|
||||
while (J->lexchar != EOF && J->lexchar != '\n')
|
||||
jsY_next(J);
|
||||
}
|
||||
|
||||
static int lexcomment(js_State *J)
|
||||
{
|
||||
/* already consumed initial '/' '*' sequence */
|
||||
while (J->lexchar != EOF) {
|
||||
if (jsY_accept(J, '*')) {
|
||||
while (J->lexchar == '*')
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '/'))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
jsY_next(J);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static double lexhex(js_State *J)
|
||||
{
|
||||
double n = 0;
|
||||
if (!jsY_ishex(J->lexchar))
|
||||
jsY_error(J, "malformed hexadecimal number");
|
||||
while (jsY_ishex(J->lexchar)) {
|
||||
n = n * 16 + jsY_tohex(J->lexchar);
|
||||
jsY_next(J);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static double lexinteger(js_State *J)
|
||||
{
|
||||
double n = 0;
|
||||
if (!jsY_isdec(J->lexchar))
|
||||
jsY_error(J, "malformed number");
|
||||
while (jsY_isdec(J->lexchar)) {
|
||||
n = n * 10 + (J->lexchar - '0');
|
||||
jsY_next(J);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static double lexfraction(js_State *J)
|
||||
{
|
||||
double n = 0;
|
||||
double d = 1;
|
||||
while (jsY_isdec(J->lexchar)) {
|
||||
n = n * 10 + (J->lexchar - '0');
|
||||
d = d * 10;
|
||||
jsY_next(J);
|
||||
}
|
||||
return n / d;
|
||||
}
|
||||
|
||||
static double lexexponent(js_State *J)
|
||||
{
|
||||
double sign;
|
||||
if (jsY_accept(J, 'e') || jsY_accept(J, 'E')) {
|
||||
if (jsY_accept(J, '-')) sign = -1;
|
||||
else if (jsY_accept(J, '+')) sign = 1;
|
||||
else sign = 1;
|
||||
return sign * lexinteger(J);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lexnumber(js_State *J)
|
||||
{
|
||||
double n;
|
||||
double e;
|
||||
|
||||
if (jsY_accept(J, '0')) {
|
||||
if (jsY_accept(J, 'x') || jsY_accept(J, 'X')) {
|
||||
J->number = lexhex(J);
|
||||
return TK_NUMBER;
|
||||
}
|
||||
if (jsY_isdec(J->lexchar))
|
||||
jsY_error(J, "number with leading zero");
|
||||
n = 0;
|
||||
if (jsY_accept(J, '.'))
|
||||
n += lexfraction(J);
|
||||
} else if (jsY_accept(J, '.')) {
|
||||
if (!jsY_isdec(J->lexchar))
|
||||
return '.';
|
||||
n = lexfraction(J);
|
||||
} else {
|
||||
n = lexinteger(J);
|
||||
if (jsY_accept(J, '.'))
|
||||
n += lexfraction(J);
|
||||
}
|
||||
|
||||
e = lexexponent(J);
|
||||
if (e < 0)
|
||||
n /= pow(10, -e);
|
||||
else if (e > 0)
|
||||
n *= pow(10, e);
|
||||
|
||||
if (jsY_isidentifierstart(J->lexchar))
|
||||
jsY_error(J, "number with letter suffix");
|
||||
|
||||
J->number = n;
|
||||
return TK_NUMBER;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int lexnumber(js_State *J)
|
||||
{
|
||||
const char *s = J->source - 1;
|
||||
|
||||
if (jsY_accept(J, '0')) {
|
||||
if (jsY_accept(J, 'x') || jsY_accept(J, 'X')) {
|
||||
J->number = lexhex(J);
|
||||
return TK_NUMBER;
|
||||
}
|
||||
if (jsY_isdec(J->lexchar))
|
||||
jsY_error(J, "number with leading zero");
|
||||
if (jsY_accept(J, '.')) {
|
||||
while (jsY_isdec(J->lexchar))
|
||||
jsY_next(J);
|
||||
}
|
||||
} else if (jsY_accept(J, '.')) {
|
||||
if (!jsY_isdec(J->lexchar))
|
||||
return '.';
|
||||
while (jsY_isdec(J->lexchar))
|
||||
jsY_next(J);
|
||||
} else {
|
||||
while (jsY_isdec(J->lexchar))
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '.')) {
|
||||
while (jsY_isdec(J->lexchar))
|
||||
jsY_next(J);
|
||||
}
|
||||
}
|
||||
|
||||
if (jsY_accept(J, 'e') || jsY_accept(J, 'E')) {
|
||||
if (J->lexchar == '-' || J->lexchar == '+')
|
||||
jsY_next(J);
|
||||
if (jsY_isdec(J->lexchar))
|
||||
while (jsY_isdec(J->lexchar))
|
||||
jsY_next(J);
|
||||
else
|
||||
jsY_error(J, "missing exponent");
|
||||
}
|
||||
|
||||
if (jsY_isidentifierstart(J->lexchar))
|
||||
jsY_error(J, "number with letter suffix");
|
||||
|
||||
J->number = js_strtod(s, NULL);
|
||||
return TK_NUMBER;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int lexescape(js_State *J)
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
/* already consumed '\' */
|
||||
|
||||
if (jsY_accept(J, '\n'))
|
||||
return 0;
|
||||
|
||||
switch (J->lexchar) {
|
||||
case EOF: jsY_error(J, "unterminated escape sequence");
|
||||
case 'u':
|
||||
jsY_next(J);
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 12; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 8; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 4; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar); jsY_next(J); }
|
||||
textpush(J, x);
|
||||
break;
|
||||
case 'x':
|
||||
jsY_next(J);
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 4; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar); jsY_next(J); }
|
||||
textpush(J, x);
|
||||
break;
|
||||
case '0': textpush(J, 0); jsY_next(J); break;
|
||||
case '\\': textpush(J, '\\'); jsY_next(J); break;
|
||||
case '\'': textpush(J, '\''); jsY_next(J); break;
|
||||
case '"': textpush(J, '"'); jsY_next(J); break;
|
||||
case 'b': textpush(J, '\b'); jsY_next(J); break;
|
||||
case 'f': textpush(J, '\f'); jsY_next(J); break;
|
||||
case 'n': textpush(J, '\n'); jsY_next(J); break;
|
||||
case 'r': textpush(J, '\r'); jsY_next(J); break;
|
||||
case 't': textpush(J, '\t'); jsY_next(J); break;
|
||||
case 'v': textpush(J, '\v'); jsY_next(J); break;
|
||||
default: textpush(J, J->lexchar); jsY_next(J); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lexstring(js_State *J)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
int q = J->lexchar;
|
||||
jsY_next(J);
|
||||
|
||||
textinit(J);
|
||||
|
||||
while (J->lexchar != q) {
|
||||
if (J->lexchar == EOF || J->lexchar == '\n')
|
||||
jsY_error(J, "string not terminated");
|
||||
if (jsY_accept(J, '\\')) {
|
||||
if (lexescape(J))
|
||||
jsY_error(J, "malformed escape sequence");
|
||||
} else {
|
||||
textpush(J, J->lexchar);
|
||||
jsY_next(J);
|
||||
}
|
||||
}
|
||||
jsY_expect(J, q);
|
||||
|
||||
s = textend(J);
|
||||
|
||||
J->text = js_intern(J, s);
|
||||
return TK_STRING;
|
||||
}
|
||||
|
||||
/* the ugliest language wart ever... */
|
||||
static int isregexpcontext(int last)
|
||||
{
|
||||
switch (last) {
|
||||
case ']':
|
||||
case ')':
|
||||
case '}':
|
||||
case TK_IDENTIFIER:
|
||||
case TK_NUMBER:
|
||||
case TK_STRING:
|
||||
case TK_FALSE:
|
||||
case TK_NULL:
|
||||
case TK_THIS:
|
||||
case TK_TRUE:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int lexregexp(js_State *J)
|
||||
{
|
||||
const char *s;
|
||||
int g, m, i;
|
||||
int inclass = 0;
|
||||
|
||||
/* already consumed initial '/' */
|
||||
|
||||
textinit(J);
|
||||
|
||||
/* regexp body */
|
||||
while (J->lexchar != '/' || inclass) {
|
||||
if (J->lexchar == EOF || J->lexchar == '\n') {
|
||||
jsY_error(J, "regular expression not terminated");
|
||||
} else if (jsY_accept(J, '\\')) {
|
||||
if (jsY_accept(J, '/')) {
|
||||
textpush(J, '/');
|
||||
} else {
|
||||
textpush(J, '\\');
|
||||
if (J->lexchar == EOF || J->lexchar == '\n')
|
||||
jsY_error(J, "regular expression not terminated");
|
||||
textpush(J, J->lexchar);
|
||||
jsY_next(J);
|
||||
}
|
||||
} else {
|
||||
if (J->lexchar == '[' && !inclass)
|
||||
inclass = 1;
|
||||
if (J->lexchar == ']' && inclass)
|
||||
inclass = 0;
|
||||
textpush(J, J->lexchar);
|
||||
jsY_next(J);
|
||||
}
|
||||
}
|
||||
jsY_expect(J, '/');
|
||||
|
||||
s = textend(J);
|
||||
|
||||
/* regexp flags */
|
||||
g = i = m = 0;
|
||||
|
||||
while (jsY_isidentifierpart(J->lexchar)) {
|
||||
if (jsY_accept(J, 'g')) ++g;
|
||||
else if (jsY_accept(J, 'i')) ++i;
|
||||
else if (jsY_accept(J, 'm')) ++m;
|
||||
else jsY_error(J, "illegal flag in regular expression: %c", J->lexchar);
|
||||
}
|
||||
|
||||
if (g > 1 || i > 1 || m > 1)
|
||||
jsY_error(J, "duplicated flag in regular expression");
|
||||
|
||||
J->text = js_intern(J, s);
|
||||
J->number = 0;
|
||||
if (g) J->number += JS_REGEXP_G;
|
||||
if (i) J->number += JS_REGEXP_I;
|
||||
if (m) J->number += JS_REGEXP_M;
|
||||
return TK_REGEXP;
|
||||
}
|
||||
|
||||
/* simple "return [no Line Terminator here] ..." contexts */
|
||||
static int isnlthcontext(int last)
|
||||
{
|
||||
switch (last) {
|
||||
case TK_BREAK:
|
||||
case TK_CONTINUE:
|
||||
case TK_RETURN:
|
||||
case TK_THROW:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int jsY_lexx(js_State *J)
|
||||
{
|
||||
J->newline = 0;
|
||||
|
||||
while (1) {
|
||||
J->lexline = J->line; /* save location of beginning of token */
|
||||
|
||||
while (jsY_iswhite(J->lexchar))
|
||||
jsY_next(J);
|
||||
|
||||
if (jsY_accept(J, '\n')) {
|
||||
J->newline = 1;
|
||||
if (isnlthcontext(J->lasttoken))
|
||||
return ';';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jsY_accept(J, '/')) {
|
||||
if (jsY_accept(J, '/')) {
|
||||
lexlinecomment(J);
|
||||
continue;
|
||||
} else if (jsY_accept(J, '*')) {
|
||||
if (lexcomment(J))
|
||||
jsY_error(J, "multi-line comment not terminated");
|
||||
continue;
|
||||
} else if (isregexpcontext(J->lasttoken)) {
|
||||
return lexregexp(J);
|
||||
} else if (jsY_accept(J, '=')) {
|
||||
return TK_DIV_ASS;
|
||||
} else {
|
||||
return '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (J->lexchar >= '0' && J->lexchar <= '9') {
|
||||
return lexnumber(J);
|
||||
}
|
||||
|
||||
switch (J->lexchar) {
|
||||
case '(': jsY_next(J); return '(';
|
||||
case ')': jsY_next(J); return ')';
|
||||
case ',': jsY_next(J); return ',';
|
||||
case ':': jsY_next(J); return ':';
|
||||
case ';': jsY_next(J); return ';';
|
||||
case '?': jsY_next(J); return '?';
|
||||
case '[': jsY_next(J); return '[';
|
||||
case ']': jsY_next(J); return ']';
|
||||
case '{': jsY_next(J); return '{';
|
||||
case '}': jsY_next(J); return '}';
|
||||
case '~': jsY_next(J); return '~';
|
||||
|
||||
case '\'':
|
||||
case '"':
|
||||
return lexstring(J);
|
||||
|
||||
case '.':
|
||||
return lexnumber(J);
|
||||
|
||||
case '<':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '<')) {
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_SHL_ASS;
|
||||
return TK_SHL;
|
||||
}
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_LE;
|
||||
return '<';
|
||||
|
||||
case '>':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '>')) {
|
||||
if (jsY_accept(J, '>')) {
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_USHR_ASS;
|
||||
return TK_USHR;
|
||||
}
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_SHR_ASS;
|
||||
return TK_SHR;
|
||||
}
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_GE;
|
||||
return '>';
|
||||
|
||||
case '=':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '=')) {
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_STRICTEQ;
|
||||
return TK_EQ;
|
||||
}
|
||||
return '=';
|
||||
|
||||
case '!':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '=')) {
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_STRICTNE;
|
||||
return TK_NE;
|
||||
}
|
||||
return '!';
|
||||
|
||||
case '+':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '+'))
|
||||
return TK_INC;
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_ADD_ASS;
|
||||
return '+';
|
||||
|
||||
case '-':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '-'))
|
||||
return TK_DEC;
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_SUB_ASS;
|
||||
return '-';
|
||||
|
||||
case '*':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_MUL_ASS;
|
||||
return '*';
|
||||
|
||||
case '%':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_MOD_ASS;
|
||||
return '%';
|
||||
|
||||
case '&':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '&'))
|
||||
return TK_AND;
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_AND_ASS;
|
||||
return '&';
|
||||
|
||||
case '|':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '|'))
|
||||
return TK_OR;
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_OR_ASS;
|
||||
return '|';
|
||||
|
||||
case '^':
|
||||
jsY_next(J);
|
||||
if (jsY_accept(J, '='))
|
||||
return TK_XOR_ASS;
|
||||
return '^';
|
||||
|
||||
case EOF:
|
||||
return 0; /* EOF */
|
||||
}
|
||||
|
||||
/* Handle \uXXXX escapes in identifiers */
|
||||
jsY_unescape(J);
|
||||
if (jsY_isidentifierstart(J->lexchar)) {
|
||||
textinit(J);
|
||||
textpush(J, J->lexchar);
|
||||
|
||||
jsY_next(J);
|
||||
jsY_unescape(J);
|
||||
while (jsY_isidentifierpart(J->lexchar)) {
|
||||
textpush(J, J->lexchar);
|
||||
jsY_next(J);
|
||||
jsY_unescape(J);
|
||||
}
|
||||
|
||||
textend(J);
|
||||
|
||||
return jsY_findkeyword(J, J->lexbuf.text);
|
||||
}
|
||||
|
||||
if (J->lexchar >= 0x20 && J->lexchar <= 0x7E)
|
||||
jsY_error(J, "unexpected character: '%c'", J->lexchar);
|
||||
jsY_error(J, "unexpected character: \\u%04X", J->lexchar);
|
||||
}
|
||||
}
|
||||
|
||||
void jsY_initlex(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
J->filename = filename;
|
||||
J->source = source;
|
||||
J->line = 1;
|
||||
J->lasttoken = 0;
|
||||
jsY_next(J); /* load first lookahead character */
|
||||
}
|
||||
|
||||
int jsY_lex(js_State *J)
|
||||
{
|
||||
return J->lasttoken = jsY_lexx(J);
|
||||
}
|
||||
|
||||
static int lexjsonnumber(js_State *J)
|
||||
{
|
||||
const char *s = J->source - 1;
|
||||
|
||||
if (J->lexchar == '-')
|
||||
jsY_next(J);
|
||||
|
||||
if (J->lexchar == '0')
|
||||
jsY_next(J);
|
||||
else if (J->lexchar >= '1' && J->lexchar <= '9')
|
||||
while (isdigit(J->lexchar))
|
||||
jsY_next(J);
|
||||
else
|
||||
jsY_error(J, "unexpected non-digit");
|
||||
|
||||
if (jsY_accept(J, '.')) {
|
||||
if (isdigit(J->lexchar))
|
||||
while (isdigit(J->lexchar))
|
||||
jsY_next(J);
|
||||
else
|
||||
jsY_error(J, "missing digits after decimal point");
|
||||
}
|
||||
|
||||
if (jsY_accept(J, 'e') || jsY_accept(J, 'E')) {
|
||||
if (J->lexchar == '-' || J->lexchar == '+')
|
||||
jsY_next(J);
|
||||
if (isdigit(J->lexchar))
|
||||
while (isdigit(J->lexchar))
|
||||
jsY_next(J);
|
||||
else
|
||||
jsY_error(J, "missing digits after exponent indicator");
|
||||
}
|
||||
|
||||
J->number = js_strtod(s, NULL);
|
||||
return TK_NUMBER;
|
||||
}
|
||||
|
||||
static int lexjsonescape(js_State *J)
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
/* already consumed '\' */
|
||||
|
||||
switch (J->lexchar) {
|
||||
default: jsY_error(J, "invalid escape sequence");
|
||||
case 'u':
|
||||
jsY_next(J);
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 12; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 8; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 4; jsY_next(J); }
|
||||
if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar); jsY_next(J); }
|
||||
textpush(J, x);
|
||||
break;
|
||||
case '"': textpush(J, '"'); jsY_next(J); break;
|
||||
case '\\': textpush(J, '\\'); jsY_next(J); break;
|
||||
case '/': textpush(J, '/'); jsY_next(J); break;
|
||||
case 'b': textpush(J, '\b'); jsY_next(J); break;
|
||||
case 'f': textpush(J, '\f'); jsY_next(J); break;
|
||||
case 'n': textpush(J, '\n'); jsY_next(J); break;
|
||||
case 'r': textpush(J, '\r'); jsY_next(J); break;
|
||||
case 't': textpush(J, '\t'); jsY_next(J); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lexjsonstring(js_State *J)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
textinit(J);
|
||||
|
||||
while (J->lexchar != '"') {
|
||||
if (J->lexchar == EOF)
|
||||
jsY_error(J, "unterminated string");
|
||||
else if (J->lexchar < 32)
|
||||
jsY_error(J, "invalid control character in string");
|
||||
else if (jsY_accept(J, '\\'))
|
||||
lexjsonescape(J);
|
||||
else {
|
||||
textpush(J, J->lexchar);
|
||||
jsY_next(J);
|
||||
}
|
||||
}
|
||||
jsY_expect(J, '"');
|
||||
|
||||
s = textend(J);
|
||||
|
||||
J->text = js_intern(J, s);
|
||||
return TK_STRING;
|
||||
}
|
||||
|
||||
int jsY_lexjson(js_State *J)
|
||||
{
|
||||
while (1) {
|
||||
J->lexline = J->line; /* save location of beginning of token */
|
||||
|
||||
while (jsY_iswhite(J->lexchar) || J->lexchar == '\n')
|
||||
jsY_next(J);
|
||||
|
||||
if ((J->lexchar >= '0' && J->lexchar <= '9') || J->lexchar == '-')
|
||||
return lexjsonnumber(J);
|
||||
|
||||
switch (J->lexchar) {
|
||||
case ',': jsY_next(J); return ',';
|
||||
case ':': jsY_next(J); return ':';
|
||||
case '[': jsY_next(J); return '[';
|
||||
case ']': jsY_next(J); return ']';
|
||||
case '{': jsY_next(J); return '{';
|
||||
case '}': jsY_next(J); return '}';
|
||||
|
||||
case '"':
|
||||
jsY_next(J);
|
||||
return lexjsonstring(J);
|
||||
|
||||
case 'f':
|
||||
jsY_next(J); jsY_expect(J, 'a'); jsY_expect(J, 'l'); jsY_expect(J, 's'); jsY_expect(J, 'e');
|
||||
return TK_FALSE;
|
||||
|
||||
case 'n':
|
||||
jsY_next(J); jsY_expect(J, 'u'); jsY_expect(J, 'l'); jsY_expect(J, 'l');
|
||||
return TK_NULL;
|
||||
|
||||
case 't':
|
||||
jsY_next(J); jsY_expect(J, 'r'); jsY_expect(J, 'u'); jsY_expect(J, 'e');
|
||||
return TK_TRUE;
|
||||
|
||||
case EOF:
|
||||
return 0; /* EOF */
|
||||
}
|
||||
|
||||
if (J->lexchar >= 0x20 && J->lexchar <= 0x7E)
|
||||
jsY_error(J, "unexpected character: '%c'", J->lexchar);
|
||||
jsY_error(J, "unexpected character: \\u%04X", J->lexchar);
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
#ifndef js_lex_h
|
||||
#define js_lex_h
|
||||
|
||||
enum
|
||||
{
|
||||
TK_IDENTIFIER = 256,
|
||||
TK_NUMBER,
|
||||
TK_STRING,
|
||||
TK_REGEXP,
|
||||
|
||||
/* multi-character punctuators */
|
||||
TK_LE,
|
||||
TK_GE,
|
||||
TK_EQ,
|
||||
TK_NE,
|
||||
TK_STRICTEQ,
|
||||
TK_STRICTNE,
|
||||
TK_SHL,
|
||||
TK_SHR,
|
||||
TK_USHR,
|
||||
TK_AND,
|
||||
TK_OR,
|
||||
TK_ADD_ASS,
|
||||
TK_SUB_ASS,
|
||||
TK_MUL_ASS,
|
||||
TK_DIV_ASS,
|
||||
TK_MOD_ASS,
|
||||
TK_SHL_ASS,
|
||||
TK_SHR_ASS,
|
||||
TK_USHR_ASS,
|
||||
TK_AND_ASS,
|
||||
TK_OR_ASS,
|
||||
TK_XOR_ASS,
|
||||
TK_INC,
|
||||
TK_DEC,
|
||||
|
||||
/* keywords */
|
||||
TK_BREAK,
|
||||
TK_CASE,
|
||||
TK_CATCH,
|
||||
TK_CONTINUE,
|
||||
TK_DEBUGGER,
|
||||
TK_DEFAULT,
|
||||
TK_DELETE,
|
||||
TK_DO,
|
||||
TK_ELSE,
|
||||
TK_FALSE,
|
||||
TK_FINALLY,
|
||||
TK_FOR,
|
||||
TK_FUNCTION,
|
||||
TK_IF,
|
||||
TK_IN,
|
||||
TK_INSTANCEOF,
|
||||
TK_NEW,
|
||||
TK_NULL,
|
||||
TK_RETURN,
|
||||
TK_SWITCH,
|
||||
TK_THIS,
|
||||
TK_THROW,
|
||||
TK_TRUE,
|
||||
TK_TRY,
|
||||
TK_TYPEOF,
|
||||
TK_VAR,
|
||||
TK_VOID,
|
||||
TK_WHILE,
|
||||
TK_WITH,
|
||||
};
|
||||
|
||||
int jsY_iswhite(int c);
|
||||
int jsY_isnewline(int c);
|
||||
int jsY_ishex(int c);
|
||||
int jsY_tohex(int c);
|
||||
|
||||
const char *jsY_tokenstring(int token);
|
||||
int jsY_findword(const char *s, const char **list, int num);
|
||||
|
||||
void jsY_initlex(js_State *J, const char *filename, const char *source);
|
||||
int jsY_lex(js_State *J);
|
||||
int jsY_lexjson(js_State *J);
|
||||
|
||||
#endif
|
@ -1,192 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define JS_RAND_MAX (0x7fffffff)
|
||||
|
||||
static unsigned int jsM_rand_temper(unsigned int x)
|
||||
{
|
||||
x ^= x>>11;
|
||||
x ^= x<<7 & 0x9D2C5680;
|
||||
x ^= x<<15 & 0xEFC60000;
|
||||
x ^= x>>18;
|
||||
return x;
|
||||
}
|
||||
|
||||
static int jsM_rand_r(unsigned int *seed)
|
||||
{
|
||||
return jsM_rand_temper(*seed = *seed * 1103515245 + 12345)/2;
|
||||
}
|
||||
|
||||
static double jsM_round(double x)
|
||||
{
|
||||
if (isnan(x)) return x;
|
||||
if (isinf(x)) return x;
|
||||
if (x == 0) return x;
|
||||
if (x > 0 && x < 0.5) return 0;
|
||||
if (x < 0 && x >= -0.5) return -0;
|
||||
return floor(x + 0.5);
|
||||
}
|
||||
|
||||
static void Math_abs(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, fabs(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_acos(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, acos(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_asin(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, asin(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_atan(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, atan(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_atan2(js_State *J)
|
||||
{
|
||||
double y = js_tonumber(J, 1);
|
||||
double x = js_tonumber(J, 2);
|
||||
js_pushnumber(J, atan2(y, x));
|
||||
}
|
||||
|
||||
static void Math_ceil(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, ceil(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_cos(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, cos(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_exp(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, exp(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_floor(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, floor(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_log(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, log(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_pow(js_State *J)
|
||||
{
|
||||
double x = js_tonumber(J, 1);
|
||||
double y = js_tonumber(J, 2);
|
||||
if (!isfinite(y) && fabs(x) == 1)
|
||||
js_pushnumber(J, NAN);
|
||||
else
|
||||
js_pushnumber(J, pow(x,y));
|
||||
}
|
||||
|
||||
static void Math_random(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, jsM_rand_r(&J->seed) / (JS_RAND_MAX + 1.0));
|
||||
}
|
||||
|
||||
static void Math_round(js_State *J)
|
||||
{
|
||||
double x = js_tonumber(J, 1);
|
||||
js_pushnumber(J, jsM_round(x));
|
||||
}
|
||||
|
||||
static void Math_sin(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, sin(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_sqrt(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, sqrt(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_tan(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, tan(js_tonumber(J, 1)));
|
||||
}
|
||||
|
||||
static void Math_max(js_State *J)
|
||||
{
|
||||
int i, n = js_gettop(J);
|
||||
double x = -INFINITY;
|
||||
for (i = 1; i < n; ++i) {
|
||||
double y = js_tonumber(J, i);
|
||||
if (isnan(y)) {
|
||||
x = y;
|
||||
break;
|
||||
}
|
||||
if (signbit(x) == signbit(y))
|
||||
x = x > y ? x : y;
|
||||
else if (signbit(x))
|
||||
x = y;
|
||||
}
|
||||
js_pushnumber(J, x);
|
||||
}
|
||||
|
||||
static void Math_min(js_State *J)
|
||||
{
|
||||
int i, n = js_gettop(J);
|
||||
double x = INFINITY;
|
||||
for (i = 1; i < n; ++i) {
|
||||
double y = js_tonumber(J, i);
|
||||
if (isnan(y)) {
|
||||
x = y;
|
||||
break;
|
||||
}
|
||||
if (signbit(x) == signbit(y))
|
||||
x = x < y ? x : y;
|
||||
else if (signbit(y))
|
||||
x = y;
|
||||
}
|
||||
js_pushnumber(J, x);
|
||||
}
|
||||
|
||||
void jsB_initmath(js_State *J)
|
||||
{
|
||||
J->seed = time(NULL);
|
||||
|
||||
js_pushobject(J, jsV_newobject(J, JS_CMATH, J->Object_prototype));
|
||||
{
|
||||
jsB_propn(J, "E", 2.7182818284590452354);
|
||||
jsB_propn(J, "LN10", 2.302585092994046);
|
||||
jsB_propn(J, "LN2", 0.6931471805599453);
|
||||
jsB_propn(J, "LOG2E", 1.4426950408889634);
|
||||
jsB_propn(J, "LOG10E", 0.4342944819032518);
|
||||
jsB_propn(J, "PI", 3.1415926535897932);
|
||||
jsB_propn(J, "SQRT1_2", 0.7071067811865476);
|
||||
jsB_propn(J, "SQRT2", 1.4142135623730951);
|
||||
|
||||
jsB_propf(J, "Math.abs", Math_abs, 1);
|
||||
jsB_propf(J, "Math.acos", Math_acos, 1);
|
||||
jsB_propf(J, "Math.asin", Math_asin, 1);
|
||||
jsB_propf(J, "Math.atan", Math_atan, 1);
|
||||
jsB_propf(J, "Math.atan2", Math_atan2, 2);
|
||||
jsB_propf(J, "Math.ceil", Math_ceil, 1);
|
||||
jsB_propf(J, "Math.cos", Math_cos, 1);
|
||||
jsB_propf(J, "Math.exp", Math_exp, 1);
|
||||
jsB_propf(J, "Math.floor", Math_floor, 1);
|
||||
jsB_propf(J, "Math.log", Math_log, 1);
|
||||
jsB_propf(J, "Math.max", Math_max, 0); /* 2 */
|
||||
jsB_propf(J, "Math.min", Math_min, 0); /* 2 */
|
||||
jsB_propf(J, "Math.pow", Math_pow, 2);
|
||||
jsB_propf(J, "Math.random", Math_random, 0);
|
||||
jsB_propf(J, "Math.round", Math_round, 1);
|
||||
jsB_propf(J, "Math.sin", Math_sin, 1);
|
||||
jsB_propf(J, "Math.sqrt", Math_sqrt, 1);
|
||||
jsB_propf(J, "Math.tan", Math_tan, 1);
|
||||
}
|
||||
js_defglobal(J, "Math", JS_DONTENUM);
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1700) /* VS2012 has stdint.h */
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
static void jsB_new_Number(js_State *J)
|
||||
{
|
||||
js_newnumber(J, js_gettop(J) > 1 ? js_tonumber(J, 1) : 0);
|
||||
}
|
||||
|
||||
static void jsB_Number(js_State *J)
|
||||
{
|
||||
js_pushnumber(J, js_gettop(J) > 1 ? js_tonumber(J, 1) : 0);
|
||||
}
|
||||
|
||||
static void Np_valueOf(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
|
||||
js_pushnumber(J, self->u.number);
|
||||
}
|
||||
|
||||
static void Np_toString(js_State *J)
|
||||
{
|
||||
char buf[100];
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
int radix = js_isundefined(J, 1) ? 10 : js_tointeger(J, 1);
|
||||
if (self->type != JS_CNUMBER)
|
||||
js_typeerror(J, "not a number");
|
||||
if (radix == 10) {
|
||||
js_pushstring(J, jsV_numbertostring(J, buf, self->u.number));
|
||||
return;
|
||||
}
|
||||
if (radix < 2 || radix > 36)
|
||||
js_rangeerror(J, "invalid radix");
|
||||
|
||||
/* lame number to string conversion for any radix from 2 to 36 */
|
||||
{
|
||||
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
double number = self->u.number;
|
||||
int sign = self->u.number < 0;
|
||||
js_Buffer *sb = NULL;
|
||||
uint64_t u, limit = ((uint64_t)1<<52);
|
||||
|
||||
int ndigits, exp, point;
|
||||
|
||||
if (number == 0) { js_pushstring(J, "0"); return; }
|
||||
if (isnan(number)) { js_pushstring(J, "NaN"); return; }
|
||||
if (isinf(number)) { js_pushstring(J, sign ? "-Infinity" : "Infinity"); return; }
|
||||
|
||||
if (sign)
|
||||
number = -number;
|
||||
|
||||
/* fit as many digits as we want in an int */
|
||||
exp = 0;
|
||||
while (number * pow(radix, exp) > limit)
|
||||
--exp;
|
||||
while (number * pow(radix, exp+1) < limit)
|
||||
++exp;
|
||||
u = number * pow(radix, exp) + 0.5;
|
||||
|
||||
/* trim trailing zeros */
|
||||
while (u > 0 && (u % radix) == 0) {
|
||||
u /= radix;
|
||||
--exp;
|
||||
}
|
||||
|
||||
/* serialize digits */
|
||||
ndigits = 0;
|
||||
while (u > 0) {
|
||||
buf[ndigits++] = digits[u % radix];
|
||||
u /= radix;
|
||||
}
|
||||
point = ndigits - exp;
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
if (sign)
|
||||
js_putc(J, &sb, '-');
|
||||
|
||||
if (point <= 0) {
|
||||
js_putc(J, &sb, '0');
|
||||
js_putc(J, &sb, '.');
|
||||
while (point++ < 0)
|
||||
js_putc(J, &sb, '0');
|
||||
while (ndigits-- > 0)
|
||||
js_putc(J, &sb, buf[ndigits]);
|
||||
} else {
|
||||
while (ndigits-- > 0) {
|
||||
js_putc(J, &sb, buf[ndigits]);
|
||||
if (--point == 0 && ndigits > 0)
|
||||
js_putc(J, &sb, '.');
|
||||
}
|
||||
while (point-- > 0)
|
||||
js_putc(J, &sb, '0');
|
||||
}
|
||||
|
||||
js_putc(J, &sb, 0);
|
||||
js_pushstring(J, sb->s);
|
||||
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Customized ToString() on a number */
|
||||
static void numtostr(js_State *J, const char *fmt, int w, double n)
|
||||
{
|
||||
/* buf needs to fit printf("%.20f", 1e20) */
|
||||
char buf[50], *e;
|
||||
sprintf(buf, fmt, w, n);
|
||||
e = strchr(buf, 'e');
|
||||
if (e) {
|
||||
int exp = atoi(e+1);
|
||||
sprintf(e, "e%+d", exp);
|
||||
}
|
||||
js_pushstring(J, buf);
|
||||
}
|
||||
|
||||
static void Np_toFixed(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
int width = js_tointeger(J, 1);
|
||||
char buf[32];
|
||||
double x;
|
||||
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
|
||||
if (width < 0) js_rangeerror(J, "precision %d out of range", width);
|
||||
if (width > 20) js_rangeerror(J, "precision %d out of range", width);
|
||||
x = self->u.number;
|
||||
if (isnan(x) || isinf(x) || x <= -1e21 || x >= 1e21)
|
||||
js_pushstring(J, jsV_numbertostring(J, buf, x));
|
||||
else
|
||||
numtostr(J, "%.*f", width, x);
|
||||
}
|
||||
|
||||
static void Np_toExponential(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
int width = js_tointeger(J, 1);
|
||||
char buf[32];
|
||||
double x;
|
||||
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
|
||||
if (width < 0) js_rangeerror(J, "precision %d out of range", width);
|
||||
if (width > 20) js_rangeerror(J, "precision %d out of range", width);
|
||||
x = self->u.number;
|
||||
if (isnan(x) || isinf(x))
|
||||
js_pushstring(J, jsV_numbertostring(J, buf, x));
|
||||
else
|
||||
numtostr(J, "%.*e", width, self->u.number);
|
||||
}
|
||||
|
||||
static void Np_toPrecision(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
int width = js_tointeger(J, 1);
|
||||
char buf[32];
|
||||
double x;
|
||||
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
|
||||
if (width < 1) js_rangeerror(J, "precision %d out of range", width);
|
||||
if (width > 21) js_rangeerror(J, "precision %d out of range", width);
|
||||
x = self->u.number;
|
||||
if (isnan(x) || isinf(x))
|
||||
js_pushstring(J, jsV_numbertostring(J, buf, x));
|
||||
else
|
||||
numtostr(J, "%.*g", width, self->u.number);
|
||||
}
|
||||
|
||||
void jsB_initnumber(js_State *J)
|
||||
{
|
||||
J->Number_prototype->u.number = 0;
|
||||
|
||||
js_pushobject(J, J->Number_prototype);
|
||||
{
|
||||
jsB_propf(J, "Number.prototype.valueOf", Np_valueOf, 0);
|
||||
jsB_propf(J, "Number.prototype.toString", Np_toString, 1);
|
||||
jsB_propf(J, "Number.prototype.toLocaleString", Np_toString, 0);
|
||||
jsB_propf(J, "Number.prototype.toFixed", Np_toFixed, 1);
|
||||
jsB_propf(J, "Number.prototype.toExponential", Np_toExponential, 1);
|
||||
jsB_propf(J, "Number.prototype.toPrecision", Np_toPrecision, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Number, jsB_new_Number, "Number", 0); /* 1 */
|
||||
{
|
||||
jsB_propn(J, "MAX_VALUE", 1.7976931348623157e+308);
|
||||
jsB_propn(J, "MIN_VALUE", 5e-324);
|
||||
jsB_propn(J, "NaN", NAN);
|
||||
jsB_propn(J, "NEGATIVE_INFINITY", -INFINITY);
|
||||
jsB_propn(J, "POSITIVE_INFINITY", INFINITY);
|
||||
}
|
||||
js_defglobal(J, "Number", JS_DONTENUM);
|
||||
}
|
@ -1,521 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
static void jsB_new_Object(js_State *J)
|
||||
{
|
||||
if (js_isundefined(J, 1) || js_isnull(J, 1))
|
||||
js_newobject(J);
|
||||
else
|
||||
js_pushobject(J, js_toobject(J, 1));
|
||||
}
|
||||
|
||||
static void jsB_Object(js_State *J)
|
||||
{
|
||||
if (js_isundefined(J, 1) || js_isnull(J, 1))
|
||||
js_newobject(J);
|
||||
else
|
||||
js_pushobject(J, js_toobject(J, 1));
|
||||
}
|
||||
|
||||
static void Op_toString(js_State *J)
|
||||
{
|
||||
if (js_isundefined(J, 0))
|
||||
js_pushliteral(J, "[object Undefined]");
|
||||
else if (js_isnull(J, 0))
|
||||
js_pushliteral(J, "[object Null]");
|
||||
else {
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
switch (self->type) {
|
||||
case JS_COBJECT: js_pushliteral(J, "[object Object]"); break;
|
||||
case JS_CARRAY: js_pushliteral(J, "[object Array]"); break;
|
||||
case JS_CFUNCTION: js_pushliteral(J, "[object Function]"); break;
|
||||
case JS_CSCRIPT: js_pushliteral(J, "[object Function]"); break;
|
||||
case JS_CEVAL: js_pushliteral(J, "[object Function]"); break;
|
||||
case JS_CCFUNCTION: js_pushliteral(J, "[object Function]"); break;
|
||||
case JS_CERROR: js_pushliteral(J, "[object Error]"); break;
|
||||
case JS_CBOOLEAN: js_pushliteral(J, "[object Boolean]"); break;
|
||||
case JS_CNUMBER: js_pushliteral(J, "[object Number]"); break;
|
||||
case JS_CSTRING: js_pushliteral(J, "[object String]"); break;
|
||||
case JS_CREGEXP: js_pushliteral(J, "[object RegExp]"); break;
|
||||
case JS_CDATE: js_pushliteral(J, "[object Date]"); break;
|
||||
case JS_CMATH: js_pushliteral(J, "[object Math]"); break;
|
||||
case JS_CJSON: js_pushliteral(J, "[object JSON]"); break;
|
||||
case JS_CARGUMENTS: js_pushliteral(J, "[object Arguments]"); break;
|
||||
case JS_CITERATOR: js_pushliteral(J, "[object Iterator]"); break;
|
||||
case JS_CUSERDATA:
|
||||
js_pushliteral(J, "[object ");
|
||||
js_pushliteral(J, self->u.user.tag);
|
||||
js_concat(J);
|
||||
js_pushliteral(J, "]");
|
||||
js_concat(J);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Op_valueOf(js_State *J)
|
||||
{
|
||||
js_copy(J, 0);
|
||||
}
|
||||
|
||||
static void Op_hasOwnProperty(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
const char *name = js_tostring(J, 1);
|
||||
js_Property *ref = jsV_getownproperty(J, self, name);
|
||||
js_pushboolean(J, ref != NULL);
|
||||
}
|
||||
|
||||
static void Op_isPrototypeOf(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
if (js_isobject(J, 1)) {
|
||||
js_Object *V = js_toobject(J, 1);
|
||||
do {
|
||||
V = V->prototype;
|
||||
if (V == self) {
|
||||
js_pushboolean(J, 1);
|
||||
return;
|
||||
}
|
||||
} while (V);
|
||||
}
|
||||
js_pushboolean(J, 0);
|
||||
}
|
||||
|
||||
static void Op_propertyIsEnumerable(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
const char *name = js_tostring(J, 1);
|
||||
js_Property *ref = jsV_getownproperty(J, self, name);
|
||||
js_pushboolean(J, ref && !(ref->atts & JS_DONTENUM));
|
||||
}
|
||||
|
||||
static void O_getPrototypeOf(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
obj = js_toobject(J, 1);
|
||||
if (obj->prototype)
|
||||
js_pushobject(J, obj->prototype);
|
||||
else
|
||||
js_pushnull(J);
|
||||
}
|
||||
|
||||
static void O_getOwnPropertyDescriptor(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
js_Property *ref;
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
obj = js_toobject(J, 1);
|
||||
ref = jsV_getproperty(J, obj, js_tostring(J, 2));
|
||||
if (!ref)
|
||||
js_pushundefined(J);
|
||||
else {
|
||||
js_newobject(J);
|
||||
if (!ref->getter && !ref->setter) {
|
||||
js_pushvalue(J, ref->value);
|
||||
js_setproperty(J, -2, "value");
|
||||
js_pushboolean(J, !(ref->atts & JS_READONLY));
|
||||
js_setproperty(J, -2, "writable");
|
||||
} else {
|
||||
if (ref->getter)
|
||||
js_pushobject(J, ref->getter);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_setproperty(J, -2, "get");
|
||||
if (ref->setter)
|
||||
js_pushobject(J, ref->setter);
|
||||
else
|
||||
js_pushundefined(J);
|
||||
js_setproperty(J, -2, "set");
|
||||
}
|
||||
js_pushboolean(J, !(ref->atts & JS_DONTENUM));
|
||||
js_setproperty(J, -2, "enumerable");
|
||||
js_pushboolean(J, !(ref->atts & JS_DONTCONF));
|
||||
js_setproperty(J, -2, "configurable");
|
||||
}
|
||||
}
|
||||
|
||||
static int O_getOwnPropertyNames_walk(js_State *J, js_Property *ref, int i)
|
||||
{
|
||||
if (ref->left->level)
|
||||
i = O_getOwnPropertyNames_walk(J, ref->left, i);
|
||||
js_pushliteral(J, ref->name);
|
||||
js_setindex(J, -2, i++);
|
||||
if (ref->right->level)
|
||||
i = O_getOwnPropertyNames_walk(J, ref->right, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void O_getOwnPropertyNames(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
int k;
|
||||
int i;
|
||||
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
obj = js_toobject(J, 1);
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
if (obj->properties->level)
|
||||
i = O_getOwnPropertyNames_walk(J, obj->properties, 0);
|
||||
else
|
||||
i = 0;
|
||||
|
||||
if (obj->type == JS_CARRAY) {
|
||||
js_pushliteral(J, "length");
|
||||
js_setindex(J, -2, i++);
|
||||
}
|
||||
|
||||
if (obj->type == JS_CSTRING) {
|
||||
js_pushliteral(J, "length");
|
||||
js_setindex(J, -2, i++);
|
||||
for (k = 0; k < obj->u.s.length; ++k) {
|
||||
js_pushnumber(J, k);
|
||||
js_setindex(J, -2, i++);
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->type == JS_CREGEXP) {
|
||||
js_pushliteral(J, "source");
|
||||
js_setindex(J, -2, i++);
|
||||
js_pushliteral(J, "global");
|
||||
js_setindex(J, -2, i++);
|
||||
js_pushliteral(J, "ignoreCase");
|
||||
js_setindex(J, -2, i++);
|
||||
js_pushliteral(J, "multiline");
|
||||
js_setindex(J, -2, i++);
|
||||
js_pushliteral(J, "lastIndex");
|
||||
js_setindex(J, -2, i++);
|
||||
}
|
||||
}
|
||||
|
||||
static void ToPropertyDescriptor(js_State *J, js_Object *obj, const char *name, js_Object *desc)
|
||||
{
|
||||
int haswritable = 0;
|
||||
int hasvalue = 0;
|
||||
int enumerable = 0;
|
||||
int configurable = 0;
|
||||
int writable = 0;
|
||||
int atts = 0;
|
||||
|
||||
js_pushobject(J, obj);
|
||||
js_pushobject(J, desc);
|
||||
|
||||
if (js_hasproperty(J, -1, "writable")) {
|
||||
haswritable = 1;
|
||||
writable = js_toboolean(J, -1);
|
||||
js_pop(J, 1);
|
||||
}
|
||||
if (js_hasproperty(J, -1, "enumerable")) {
|
||||
enumerable = js_toboolean(J, -1);
|
||||
js_pop(J, 1);
|
||||
}
|
||||
if (js_hasproperty(J, -1, "configurable")) {
|
||||
configurable = js_toboolean(J, -1);
|
||||
js_pop(J, 1);
|
||||
}
|
||||
if (js_hasproperty(J, -1, "value")) {
|
||||
hasvalue = 1;
|
||||
js_setproperty(J, -3, name);
|
||||
}
|
||||
|
||||
if (!writable) atts |= JS_READONLY;
|
||||
if (!enumerable) atts |= JS_DONTENUM;
|
||||
if (!configurable) atts |= JS_DONTCONF;
|
||||
|
||||
if (js_hasproperty(J, -1, "get")) {
|
||||
if (haswritable || hasvalue)
|
||||
js_typeerror(J, "value/writable and get/set attributes are exclusive");
|
||||
} else {
|
||||
js_pushundefined(J);
|
||||
}
|
||||
|
||||
if (js_hasproperty(J, -2, "set")) {
|
||||
if (haswritable || hasvalue)
|
||||
js_typeerror(J, "value/writable and get/set attributes are exclusive");
|
||||
} else {
|
||||
js_pushundefined(J);
|
||||
}
|
||||
|
||||
js_defaccessor(J, -4, name, atts);
|
||||
|
||||
js_pop(J, 2);
|
||||
}
|
||||
|
||||
static void O_defineProperty(js_State *J)
|
||||
{
|
||||
if (!js_isobject(J, 1)) js_typeerror(J, "not an object");
|
||||
if (!js_isobject(J, 3)) js_typeerror(J, "not an object");
|
||||
ToPropertyDescriptor(J, js_toobject(J, 1), js_tostring(J, 2), js_toobject(J, 3));
|
||||
js_copy(J, 1);
|
||||
}
|
||||
|
||||
static void O_defineProperties_walk(js_State *J, js_Property *ref)
|
||||
{
|
||||
if (ref->left->level)
|
||||
O_defineProperties_walk(J, ref->left);
|
||||
if (!(ref->atts & JS_DONTENUM)) {
|
||||
js_pushvalue(J, ref->value);
|
||||
ToPropertyDescriptor(J, js_toobject(J, 1), ref->name, js_toobject(J, -1));
|
||||
js_pop(J, 1);
|
||||
}
|
||||
if (ref->right->level)
|
||||
O_defineProperties_walk(J, ref->right);
|
||||
}
|
||||
|
||||
static void O_defineProperties(js_State *J)
|
||||
{
|
||||
js_Object *props;
|
||||
|
||||
if (!js_isobject(J, 1)) js_typeerror(J, "not an object");
|
||||
if (!js_isobject(J, 2)) js_typeerror(J, "not an object");
|
||||
|
||||
props = js_toobject(J, 2);
|
||||
if (props->properties->level)
|
||||
O_defineProperties_walk(J, props->properties);
|
||||
|
||||
js_copy(J, 1);
|
||||
}
|
||||
|
||||
static void O_create_walk(js_State *J, js_Object *obj, js_Property *ref)
|
||||
{
|
||||
if (ref->left->level)
|
||||
O_create_walk(J, obj, ref->left);
|
||||
if (!(ref->atts & JS_DONTENUM)) {
|
||||
if (ref->value.type != JS_TOBJECT)
|
||||
js_typeerror(J, "not an object");
|
||||
ToPropertyDescriptor(J, obj, ref->name, ref->value.u.object);
|
||||
}
|
||||
if (ref->right->level)
|
||||
O_create_walk(J, obj, ref->right);
|
||||
}
|
||||
|
||||
static void O_create(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
js_Object *proto;
|
||||
js_Object *props;
|
||||
|
||||
if (js_isobject(J, 1))
|
||||
proto = js_toobject(J, 1);
|
||||
else if (js_isnull(J, 1))
|
||||
proto = NULL;
|
||||
else
|
||||
js_typeerror(J, "not an object or null");
|
||||
|
||||
obj = jsV_newobject(J, JS_COBJECT, proto);
|
||||
js_pushobject(J, obj);
|
||||
|
||||
if (js_isdefined(J, 2)) {
|
||||
if (!js_isobject(J, 2))
|
||||
js_typeerror(J, "not an object");
|
||||
props = js_toobject(J, 2);
|
||||
if (props->properties->level)
|
||||
O_create_walk(J, obj, props->properties);
|
||||
}
|
||||
}
|
||||
|
||||
static int O_keys_walk(js_State *J, js_Property *ref, int i)
|
||||
{
|
||||
if (ref->left->level)
|
||||
i = O_keys_walk(J, ref->left, i);
|
||||
if (!(ref->atts & JS_DONTENUM)) {
|
||||
js_pushliteral(J, ref->name);
|
||||
js_setindex(J, -2, i++);
|
||||
}
|
||||
if (ref->right->level)
|
||||
i = O_keys_walk(J, ref->right, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void O_keys(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
int i, k;
|
||||
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
obj = js_toobject(J, 1);
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
if (obj->properties->level)
|
||||
i = O_keys_walk(J, obj->properties, 0);
|
||||
else
|
||||
i = 0;
|
||||
|
||||
if (obj->type == JS_CSTRING) {
|
||||
for (k = 0; k < obj->u.s.length; ++k) {
|
||||
js_pushnumber(J, k);
|
||||
js_setindex(J, -2, i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void O_preventExtensions(js_State *J)
|
||||
{
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
js_toobject(J, 1)->extensible = 0;
|
||||
js_copy(J, 1);
|
||||
}
|
||||
|
||||
static void O_isExtensible(js_State *J)
|
||||
{
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
js_pushboolean(J, js_toobject(J, 1)->extensible);
|
||||
}
|
||||
|
||||
static void O_seal_walk(js_State *J, js_Property *ref)
|
||||
{
|
||||
if (ref->left->level)
|
||||
O_seal_walk(J, ref->left);
|
||||
ref->atts |= JS_DONTCONF;
|
||||
if (ref->right->level)
|
||||
O_seal_walk(J, ref->right);
|
||||
}
|
||||
|
||||
static void O_seal(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
|
||||
obj = js_toobject(J, 1);
|
||||
obj->extensible = 0;
|
||||
|
||||
if (obj->properties->level)
|
||||
O_seal_walk(J, obj->properties);
|
||||
|
||||
js_copy(J, 1);
|
||||
}
|
||||
|
||||
static int O_isSealed_walk(js_State *J, js_Property *ref)
|
||||
{
|
||||
if (ref->left->level)
|
||||
if (!O_isSealed_walk(J, ref->left))
|
||||
return 0;
|
||||
if (!(ref->atts & JS_DONTCONF))
|
||||
return 0;
|
||||
if (ref->right->level)
|
||||
if (!O_isSealed_walk(J, ref->right))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void O_isSealed(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
|
||||
obj = js_toobject(J, 1);
|
||||
if (obj->extensible) {
|
||||
js_pushboolean(J, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->properties->level)
|
||||
js_pushboolean(J, O_isSealed_walk(J, obj->properties));
|
||||
else
|
||||
js_pushboolean(J, 1);
|
||||
}
|
||||
|
||||
static void O_freeze_walk(js_State *J, js_Property *ref)
|
||||
{
|
||||
if (ref->left->level)
|
||||
O_freeze_walk(J, ref->left);
|
||||
ref->atts |= JS_READONLY | JS_DONTCONF;
|
||||
if (ref->right->level)
|
||||
O_freeze_walk(J, ref->right);
|
||||
}
|
||||
|
||||
static void O_freeze(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
|
||||
obj = js_toobject(J, 1);
|
||||
obj->extensible = 0;
|
||||
|
||||
if (obj->properties->level)
|
||||
O_freeze_walk(J, obj->properties);
|
||||
|
||||
js_copy(J, 1);
|
||||
}
|
||||
|
||||
static int O_isFrozen_walk(js_State *J, js_Property *ref)
|
||||
{
|
||||
if (ref->left->level)
|
||||
if (!O_isFrozen_walk(J, ref->left))
|
||||
return 0;
|
||||
if (!(ref->atts & JS_READONLY))
|
||||
return 0;
|
||||
if (!(ref->atts & JS_DONTCONF))
|
||||
return 0;
|
||||
if (ref->right->level)
|
||||
if (!O_isFrozen_walk(J, ref->right))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void O_isFrozen(js_State *J)
|
||||
{
|
||||
js_Object *obj;
|
||||
|
||||
if (!js_isobject(J, 1))
|
||||
js_typeerror(J, "not an object");
|
||||
|
||||
obj = js_toobject(J, 1);
|
||||
|
||||
if (obj->properties->level) {
|
||||
if (!O_isFrozen_walk(J, obj->properties)) {
|
||||
js_pushboolean(J, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
js_pushboolean(J, !obj->extensible);
|
||||
}
|
||||
|
||||
void jsB_initobject(js_State *J)
|
||||
{
|
||||
js_pushobject(J, J->Object_prototype);
|
||||
{
|
||||
jsB_propf(J, "Object.prototype.toString", Op_toString, 0);
|
||||
jsB_propf(J, "Object.prototype.toLocaleString", Op_toString, 0);
|
||||
jsB_propf(J, "Object.prototype.valueOf", Op_valueOf, 0);
|
||||
jsB_propf(J, "Object.prototype.hasOwnProperty", Op_hasOwnProperty, 1);
|
||||
jsB_propf(J, "Object.prototype.isPrototypeOf", Op_isPrototypeOf, 1);
|
||||
jsB_propf(J, "Object.prototype.propertyIsEnumerable", Op_propertyIsEnumerable, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Object, jsB_new_Object, "Object", 1);
|
||||
{
|
||||
/* ES5 */
|
||||
jsB_propf(J, "Object.getPrototypeOf", O_getPrototypeOf, 1);
|
||||
jsB_propf(J, "Object.getOwnPropertyDescriptor", O_getOwnPropertyDescriptor, 2);
|
||||
jsB_propf(J, "Object.getOwnPropertyNames", O_getOwnPropertyNames, 1);
|
||||
jsB_propf(J, "Object.create", O_create, 2);
|
||||
jsB_propf(J, "Object.defineProperty", O_defineProperty, 3);
|
||||
jsB_propf(J, "Object.defineProperties", O_defineProperties, 2);
|
||||
jsB_propf(J, "Object.seal", O_seal, 1);
|
||||
jsB_propf(J, "Object.freeze", O_freeze, 1);
|
||||
jsB_propf(J, "Object.preventExtensions", O_preventExtensions, 1);
|
||||
jsB_propf(J, "Object.isSealed", O_isSealed, 1);
|
||||
jsB_propf(J, "Object.isFrozen", O_isFrozen, 1);
|
||||
jsB_propf(J, "Object.isExtensible", O_isExtensible, 1);
|
||||
jsB_propf(J, "Object.keys", O_keys, 1);
|
||||
}
|
||||
js_defglobal(J, "Object", JS_DONTENUM);
|
||||
}
|
@ -1,414 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#include "utf.h"
|
||||
|
||||
int js_isnumberobject(js_State *J, int idx)
|
||||
{
|
||||
return js_isobject(J, idx) && js_toobject(J, idx)->type == JS_CNUMBER;
|
||||
}
|
||||
|
||||
int js_isstringobject(js_State *J, int idx)
|
||||
{
|
||||
return js_isobject(J, idx) && js_toobject(J, idx)->type == JS_CSTRING;
|
||||
}
|
||||
|
||||
static void jsonnext(js_State *J)
|
||||
{
|
||||
J->lookahead = jsY_lexjson(J);
|
||||
}
|
||||
|
||||
static int jsonaccept(js_State *J, int t)
|
||||
{
|
||||
if (J->lookahead == t) {
|
||||
jsonnext(J);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jsonexpect(js_State *J, int t)
|
||||
{
|
||||
if (!jsonaccept(J, t))
|
||||
js_syntaxerror(J, "JSON: unexpected token: %s (expected %s)",
|
||||
jsY_tokenstring(J->lookahead), jsY_tokenstring(t));
|
||||
}
|
||||
|
||||
static void jsonvalue(js_State *J)
|
||||
{
|
||||
int i;
|
||||
const char *name;
|
||||
|
||||
switch (J->lookahead) {
|
||||
case TK_STRING:
|
||||
js_pushstring(J, J->text);
|
||||
jsonnext(J);
|
||||
break;
|
||||
|
||||
case TK_NUMBER:
|
||||
js_pushnumber(J, J->number);
|
||||
jsonnext(J);
|
||||
break;
|
||||
|
||||
case '{':
|
||||
js_newobject(J);
|
||||
jsonnext(J);
|
||||
if (jsonaccept(J, '}'))
|
||||
return;
|
||||
do {
|
||||
if (J->lookahead != TK_STRING)
|
||||
js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead));
|
||||
name = J->text;
|
||||
jsonnext(J);
|
||||
jsonexpect(J, ':');
|
||||
jsonvalue(J);
|
||||
js_setproperty(J, -2, name);
|
||||
} while (jsonaccept(J, ','));
|
||||
jsonexpect(J, '}');
|
||||
break;
|
||||
|
||||
case '[':
|
||||
js_newarray(J);
|
||||
jsonnext(J);
|
||||
i = 0;
|
||||
if (jsonaccept(J, ']'))
|
||||
return;
|
||||
do {
|
||||
jsonvalue(J);
|
||||
js_setindex(J, -2, i++);
|
||||
} while (jsonaccept(J, ','));
|
||||
jsonexpect(J, ']');
|
||||
break;
|
||||
|
||||
case TK_TRUE:
|
||||
js_pushboolean(J, 1);
|
||||
jsonnext(J);
|
||||
break;
|
||||
|
||||
case TK_FALSE:
|
||||
js_pushboolean(J, 0);
|
||||
jsonnext(J);
|
||||
break;
|
||||
|
||||
case TK_NULL:
|
||||
js_pushnull(J);
|
||||
jsonnext(J);
|
||||
break;
|
||||
|
||||
default:
|
||||
js_syntaxerror(J, "JSON: unexpected token: %s", jsY_tokenstring(J->lookahead));
|
||||
}
|
||||
}
|
||||
|
||||
static void jsonrevive(js_State *J, const char *name)
|
||||
{
|
||||
const char *key;
|
||||
char buf[32];
|
||||
|
||||
/* revive is in 2 */
|
||||
/* holder is in -1 */
|
||||
|
||||
js_getproperty(J, -1, name); /* get value from holder */
|
||||
|
||||
if (js_isobject(J, -1)) {
|
||||
if (js_isarray(J, -1)) {
|
||||
int i = 0;
|
||||
int n = js_getlength(J, -1);
|
||||
for (i = 0; i < n; ++i) {
|
||||
jsonrevive(J, js_itoa(buf, i));
|
||||
if (js_isundefined(J, -1)) {
|
||||
js_pop(J, 1);
|
||||
js_delproperty(J, -1, buf);
|
||||
} else {
|
||||
js_setproperty(J, -2, buf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
js_pushiterator(J, -1, 1);
|
||||
while ((key = js_nextiterator(J, -1))) {
|
||||
js_rot2(J);
|
||||
jsonrevive(J, key);
|
||||
if (js_isundefined(J, -1)) {
|
||||
js_pop(J, 1);
|
||||
js_delproperty(J, -1, key);
|
||||
} else {
|
||||
js_setproperty(J, -2, key);
|
||||
}
|
||||
js_rot2(J);
|
||||
}
|
||||
js_pop(J, 1);
|
||||
}
|
||||
}
|
||||
|
||||
js_copy(J, 2); /* reviver function */
|
||||
js_copy(J, -3); /* holder as this */
|
||||
js_pushstring(J, name); /* name */
|
||||
js_copy(J, -4); /* value */
|
||||
js_call(J, 2);
|
||||
js_rot2pop1(J); /* pop old value, leave new value on stack */
|
||||
}
|
||||
|
||||
static void JSON_parse(js_State *J)
|
||||
{
|
||||
const char *source = js_tostring(J, 1);
|
||||
jsY_initlex(J, "JSON", source);
|
||||
jsonnext(J);
|
||||
|
||||
if (js_iscallable(J, 2)) {
|
||||
js_newobject(J);
|
||||
jsonvalue(J);
|
||||
js_defproperty(J, -2, "", 0);
|
||||
jsonrevive(J, "");
|
||||
} else {
|
||||
jsonvalue(J);
|
||||
}
|
||||
}
|
||||
|
||||
static void fmtnum(js_State *J, js_Buffer **sb, double n)
|
||||
{
|
||||
if (isnan(n)) js_puts(J, sb, "null");
|
||||
else if (isinf(n)) js_puts(J, sb, "null");
|
||||
else if (n == 0) js_puts(J, sb, "0");
|
||||
else {
|
||||
char buf[40];
|
||||
js_puts(J, sb, jsV_numbertostring(J, buf, n));
|
||||
}
|
||||
}
|
||||
|
||||
static void fmtstr(js_State *J, js_Buffer **sb, const char *s)
|
||||
{
|
||||
static const char *HEX = "0123456789ABCDEF";
|
||||
int i, n;
|
||||
Rune c;
|
||||
js_putc(J, sb, '"');
|
||||
while (*s) {
|
||||
n = chartorune(&c, s);
|
||||
switch (c) {
|
||||
case '"': js_puts(J, sb, "\\\""); break;
|
||||
case '\\': js_puts(J, sb, "\\\\"); break;
|
||||
case '\b': js_puts(J, sb, "\\b"); break;
|
||||
case '\f': js_puts(J, sb, "\\f"); break;
|
||||
case '\n': js_puts(J, sb, "\\n"); break;
|
||||
case '\r': js_puts(J, sb, "\\r"); break;
|
||||
case '\t': js_puts(J, sb, "\\t"); break;
|
||||
default:
|
||||
if (c < ' ') {
|
||||
js_putc(J, sb, '\\');
|
||||
js_putc(J, sb, 'u');
|
||||
js_putc(J, sb, HEX[(c>>12)&15]);
|
||||
js_putc(J, sb, HEX[(c>>8)&15]);
|
||||
js_putc(J, sb, HEX[(c>>4)&15]);
|
||||
js_putc(J, sb, HEX[c&15]);
|
||||
} else if (c < 128) {
|
||||
js_putc(J, sb, c);
|
||||
} else {
|
||||
for (i = 0; i < n; ++i)
|
||||
js_putc(J, sb, s[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
s += n;
|
||||
}
|
||||
js_putc(J, sb, '"');
|
||||
}
|
||||
|
||||
static void fmtindent(js_State *J, js_Buffer **sb, const char *gap, int level)
|
||||
{
|
||||
js_putc(J, sb, '\n');
|
||||
while (level--)
|
||||
js_puts(J, sb, gap);
|
||||
}
|
||||
|
||||
static int fmtvalue(js_State *J, js_Buffer **sb, const char *key, const char *gap, int level);
|
||||
|
||||
static int filterprop(js_State *J, const char *key)
|
||||
{
|
||||
int i, n, found;
|
||||
/* replacer/property-list is in stack slot 2 */
|
||||
if (js_isarray(J, 2)) {
|
||||
found = 0;
|
||||
n = js_getlength(J, 2);
|
||||
for (i = 0; i < n && !found; ++i) {
|
||||
js_getindex(J, 2, i);
|
||||
if (js_isstring(J, -1) || js_isnumber(J, -1) ||
|
||||
js_isstringobject(J, -1) || js_isnumberobject(J, -1))
|
||||
found = !strcmp(key, js_tostring(J, -1));
|
||||
js_pop(J, 1);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void fmtobject(js_State *J, js_Buffer **sb, js_Object *obj, const char *gap, int level)
|
||||
{
|
||||
const char *key;
|
||||
int save;
|
||||
int i, n;
|
||||
|
||||
n = js_gettop(J) - 1;
|
||||
for (i = 4; i < n; ++i)
|
||||
if (js_isobject(J, i))
|
||||
if (js_toobject(J, i) == js_toobject(J, -1))
|
||||
js_typeerror(J, "cyclic object value");
|
||||
|
||||
n = 0;
|
||||
js_putc(J, sb, '{');
|
||||
js_pushiterator(J, -1, 1);
|
||||
while ((key = js_nextiterator(J, -1))) {
|
||||
if (filterprop(J, key)) {
|
||||
save = (*sb)->n;
|
||||
if (n) js_putc(J, sb, ',');
|
||||
if (gap) fmtindent(J, sb, gap, level + 1);
|
||||
fmtstr(J, sb, key);
|
||||
js_putc(J, sb, ':');
|
||||
if (gap)
|
||||
js_putc(J, sb, ' ');
|
||||
js_rot2(J);
|
||||
if (!fmtvalue(J, sb, key, gap, level + 1))
|
||||
(*sb)->n = save;
|
||||
else
|
||||
++n;
|
||||
js_rot2(J);
|
||||
}
|
||||
}
|
||||
js_pop(J, 1);
|
||||
if (gap && n) fmtindent(J, sb, gap, level);
|
||||
js_putc(J, sb, '}');
|
||||
}
|
||||
|
||||
static void fmtarray(js_State *J, js_Buffer **sb, const char *gap, int level)
|
||||
{
|
||||
int n, i;
|
||||
char buf[32];
|
||||
|
||||
n = js_gettop(J) - 1;
|
||||
for (i = 4; i < n; ++i)
|
||||
if (js_isobject(J, i))
|
||||
if (js_toobject(J, i) == js_toobject(J, -1))
|
||||
js_typeerror(J, "cyclic object value");
|
||||
|
||||
js_putc(J, sb, '[');
|
||||
n = js_getlength(J, -1);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (i) js_putc(J, sb, ',');
|
||||
if (gap) fmtindent(J, sb, gap, level + 1);
|
||||
if (!fmtvalue(J, sb, js_itoa(buf, i), gap, level + 1))
|
||||
js_puts(J, sb, "null");
|
||||
}
|
||||
if (gap && n) fmtindent(J, sb, gap, level);
|
||||
js_putc(J, sb, ']');
|
||||
}
|
||||
|
||||
static int fmtvalue(js_State *J, js_Buffer **sb, const char *key, const char *gap, int level)
|
||||
{
|
||||
/* replacer/property-list is in 2 */
|
||||
/* holder is in -1 */
|
||||
|
||||
js_getproperty(J, -1, key);
|
||||
|
||||
if (js_isobject(J, -1)) {
|
||||
if (js_hasproperty(J, -1, "toJSON")) {
|
||||
if (js_iscallable(J, -1)) {
|
||||
js_copy(J, -2);
|
||||
js_pushstring(J, key);
|
||||
js_call(J, 1);
|
||||
js_rot2pop1(J);
|
||||
} else {
|
||||
js_pop(J, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (js_iscallable(J, 2)) {
|
||||
js_copy(J, 2); /* replacer function */
|
||||
js_copy(J, -3); /* holder as this */
|
||||
js_pushstring(J, key); /* name */
|
||||
js_copy(J, -4); /* old value */
|
||||
js_call(J, 2);
|
||||
js_rot2pop1(J); /* pop old value, leave new value on stack */
|
||||
}
|
||||
|
||||
if (js_isobject(J, -1) && !js_iscallable(J, -1)) {
|
||||
js_Object *obj = js_toobject(J, -1);
|
||||
switch (obj->type) {
|
||||
case JS_CNUMBER: fmtnum(J, sb, obj->u.number); break;
|
||||
case JS_CSTRING: fmtstr(J, sb, obj->u.s.string); break;
|
||||
case JS_CBOOLEAN: js_puts(J, sb, obj->u.boolean ? "true" : "false"); break;
|
||||
case JS_CARRAY: fmtarray(J, sb, gap, level); break;
|
||||
default: fmtobject(J, sb, obj, gap, level); break;
|
||||
}
|
||||
}
|
||||
else if (js_isboolean(J, -1))
|
||||
js_puts(J, sb, js_toboolean(J, -1) ? "true" : "false");
|
||||
else if (js_isnumber(J, -1))
|
||||
fmtnum(J, sb, js_tonumber(J, -1));
|
||||
else if (js_isstring(J, -1))
|
||||
fmtstr(J, sb, js_tostring(J, -1));
|
||||
else if (js_isnull(J, -1))
|
||||
js_puts(J, sb, "null");
|
||||
else {
|
||||
js_pop(J, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
js_pop(J, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void JSON_stringify(js_State *J)
|
||||
{
|
||||
js_Buffer *sb = NULL;
|
||||
char buf[12];
|
||||
const char *s, *gap;
|
||||
int n;
|
||||
|
||||
gap = NULL;
|
||||
|
||||
if (js_isnumber(J, 3) || js_isnumberobject(J, 3)) {
|
||||
n = js_tointeger(J, 3);
|
||||
if (n < 0) n = 0;
|
||||
if (n > 10) n = 10;
|
||||
memset(buf, ' ', n);
|
||||
buf[n] = 0;
|
||||
if (n > 0) gap = buf;
|
||||
} else if (js_isstring(J, 3) || js_isstringobject(J, 3)) {
|
||||
s = js_tostring(J, 3);
|
||||
n = strlen(s);
|
||||
if (n > 10) n = 10;
|
||||
memcpy(buf, s, n);
|
||||
buf[n] = 0;
|
||||
if (n > 0) gap = buf;
|
||||
}
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
js_newobject(J); /* wrapper */
|
||||
js_copy(J, 1);
|
||||
js_defproperty(J, -2, "", 0);
|
||||
if (!fmtvalue(J, &sb, "", gap, 0)) {
|
||||
js_pushundefined(J);
|
||||
} else {
|
||||
js_putc(J, &sb, 0);
|
||||
js_pushstring(J, sb ? sb->s : "");
|
||||
js_rot2pop1(J);
|
||||
}
|
||||
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
|
||||
void jsB_initjson(js_State *J)
|
||||
{
|
||||
js_pushobject(J, jsV_newobject(J, JS_CJSON, J->Object_prototype));
|
||||
{
|
||||
jsB_propf(J, "JSON.parse", JSON_parse, 2);
|
||||
jsB_propf(J, "JSON.stringify", JSON_stringify, 3);
|
||||
}
|
||||
js_defglobal(J, "JSON", JS_DONTENUM);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,146 +0,0 @@
|
||||
#ifndef js_parse_h
|
||||
#define js_parse_h
|
||||
|
||||
enum js_AstType
|
||||
{
|
||||
AST_LIST,
|
||||
AST_FUNDEC,
|
||||
AST_IDENTIFIER,
|
||||
|
||||
EXP_IDENTIFIER,
|
||||
EXP_NUMBER,
|
||||
EXP_STRING,
|
||||
EXP_REGEXP,
|
||||
|
||||
/* literals */
|
||||
EXP_UNDEF, /* for array elisions */
|
||||
EXP_NULL,
|
||||
EXP_TRUE,
|
||||
EXP_FALSE,
|
||||
EXP_THIS,
|
||||
|
||||
EXP_ARRAY,
|
||||
EXP_OBJECT,
|
||||
EXP_PROP_VAL,
|
||||
EXP_PROP_GET,
|
||||
EXP_PROP_SET,
|
||||
|
||||
EXP_FUN,
|
||||
|
||||
/* expressions */
|
||||
EXP_INDEX,
|
||||
EXP_MEMBER,
|
||||
EXP_CALL,
|
||||
EXP_NEW,
|
||||
|
||||
EXP_POSTINC,
|
||||
EXP_POSTDEC,
|
||||
|
||||
EXP_DELETE,
|
||||
EXP_VOID,
|
||||
EXP_TYPEOF,
|
||||
EXP_PREINC,
|
||||
EXP_PREDEC,
|
||||
EXP_POS,
|
||||
EXP_NEG,
|
||||
EXP_BITNOT,
|
||||
EXP_LOGNOT,
|
||||
|
||||
EXP_MOD,
|
||||
EXP_DIV,
|
||||
EXP_MUL,
|
||||
EXP_SUB,
|
||||
EXP_ADD,
|
||||
EXP_USHR,
|
||||
EXP_SHR,
|
||||
EXP_SHL,
|
||||
EXP_IN,
|
||||
EXP_INSTANCEOF,
|
||||
EXP_GE,
|
||||
EXP_LE,
|
||||
EXP_GT,
|
||||
EXP_LT,
|
||||
EXP_STRICTNE,
|
||||
EXP_STRICTEQ,
|
||||
EXP_NE,
|
||||
EXP_EQ,
|
||||
EXP_BITAND,
|
||||
EXP_BITXOR,
|
||||
EXP_BITOR,
|
||||
EXP_LOGAND,
|
||||
EXP_LOGOR,
|
||||
|
||||
EXP_COND,
|
||||
|
||||
EXP_ASS,
|
||||
EXP_ASS_MUL,
|
||||
EXP_ASS_DIV,
|
||||
EXP_ASS_MOD,
|
||||
EXP_ASS_ADD,
|
||||
EXP_ASS_SUB,
|
||||
EXP_ASS_SHL,
|
||||
EXP_ASS_SHR,
|
||||
EXP_ASS_USHR,
|
||||
EXP_ASS_BITAND,
|
||||
EXP_ASS_BITXOR,
|
||||
EXP_ASS_BITOR,
|
||||
|
||||
EXP_COMMA,
|
||||
|
||||
EXP_VAR, /* var initializer */
|
||||
|
||||
/* statements */
|
||||
STM_BLOCK,
|
||||
STM_EMPTY,
|
||||
STM_VAR,
|
||||
STM_IF,
|
||||
STM_DO,
|
||||
STM_WHILE,
|
||||
STM_FOR,
|
||||
STM_FOR_VAR,
|
||||
STM_FOR_IN,
|
||||
STM_FOR_IN_VAR,
|
||||
STM_CONTINUE,
|
||||
STM_BREAK,
|
||||
STM_RETURN,
|
||||
STM_WITH,
|
||||
STM_SWITCH,
|
||||
STM_THROW,
|
||||
STM_TRY,
|
||||
STM_DEBUGGER,
|
||||
|
||||
STM_LABEL,
|
||||
STM_CASE,
|
||||
STM_DEFAULT,
|
||||
};
|
||||
|
||||
typedef struct js_JumpList js_JumpList;
|
||||
|
||||
struct js_JumpList
|
||||
{
|
||||
enum js_AstType type;
|
||||
int inst;
|
||||
js_JumpList *next;
|
||||
};
|
||||
|
||||
struct js_Ast
|
||||
{
|
||||
enum js_AstType type;
|
||||
int line;
|
||||
js_Ast *parent, *a, *b, *c, *d;
|
||||
double number;
|
||||
const char *string;
|
||||
js_JumpList *jumps; /* list of break/continue jumps to patch */
|
||||
int casejump; /* for switch case clauses */
|
||||
js_Ast *gcnext; /* next in alloc list */
|
||||
};
|
||||
|
||||
js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body);
|
||||
js_Ast *jsP_parse(js_State *J, const char *filename, const char *source);
|
||||
void jsP_freeparse(js_State *J);
|
||||
|
||||
const char *jsP_aststring(enum js_AstType type);
|
||||
void jsP_dumpsyntax(js_State *J, js_Ast *prog, int minify);
|
||||
void jsP_dumplist(js_State *J, js_Ast *prog);
|
||||
|
||||
#endif
|
@ -1,333 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
|
||||
/*
|
||||
Use an AA-tree to quickly look up properties in objects:
|
||||
|
||||
The level of every leaf node is one.
|
||||
The level of every left child is one less than its parent.
|
||||
The level of every right child is equal or one less than its parent.
|
||||
The level of every right grandchild is less than its grandparent.
|
||||
Every node of level greater than one has two children.
|
||||
|
||||
A link where the child's level is equal to that of its parent is called a horizontal link.
|
||||
Individual right horizontal links are allowed, but consecutive ones are forbidden.
|
||||
Left horizontal links are forbidden.
|
||||
|
||||
skew() fixes left horizontal links.
|
||||
split() fixes consecutive right horizontal links.
|
||||
*/
|
||||
|
||||
static js_Property sentinel = {
|
||||
"",
|
||||
&sentinel, &sentinel,
|
||||
0, 0,
|
||||
{ {0}, {0}, JS_TUNDEFINED },
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
static js_Property *newproperty(js_State *J, js_Object *obj, const char *name)
|
||||
{
|
||||
js_Property *node = js_malloc(J, sizeof *node);
|
||||
node->name = js_intern(J, name);
|
||||
node->left = node->right = &sentinel;
|
||||
node->level = 1;
|
||||
node->atts = 0;
|
||||
node->value.type = JS_TUNDEFINED;
|
||||
node->value.u.number = 0;
|
||||
node->getter = NULL;
|
||||
node->setter = NULL;
|
||||
++obj->count;
|
||||
++J->gccounter;
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_Property *lookup(js_Property *node, const char *name)
|
||||
{
|
||||
while (node != &sentinel) {
|
||||
int c = strcmp(name, node->name);
|
||||
if (c == 0)
|
||||
return node;
|
||||
else if (c < 0)
|
||||
node = node->left;
|
||||
else
|
||||
node = node->right;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static js_Property *skew(js_Property *node)
|
||||
{
|
||||
if (node->left->level == node->level) {
|
||||
js_Property *temp = node;
|
||||
node = node->left;
|
||||
temp->left = node->right;
|
||||
node->right = temp;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_Property *split(js_Property *node)
|
||||
{
|
||||
if (node->right->right->level == node->level) {
|
||||
js_Property *temp = node;
|
||||
node = node->right;
|
||||
temp->right = node->left;
|
||||
node->left = temp;
|
||||
++node->level;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static js_Property *insert(js_State *J, js_Object *obj, js_Property *node, const char *name, js_Property **result)
|
||||
{
|
||||
if (node != &sentinel) {
|
||||
int c = strcmp(name, node->name);
|
||||
if (c < 0)
|
||||
node->left = insert(J, obj, node->left, name, result);
|
||||
else if (c > 0)
|
||||
node->right = insert(J, obj, node->right, name, result);
|
||||
else
|
||||
return *result = node;
|
||||
node = skew(node);
|
||||
node = split(node);
|
||||
return node;
|
||||
}
|
||||
return *result = newproperty(J, obj, name);
|
||||
}
|
||||
|
||||
static void freeproperty(js_State *J, js_Object *obj, js_Property *node)
|
||||
{
|
||||
js_free(J, node);
|
||||
--obj->count;
|
||||
}
|
||||
|
||||
static js_Property *delete(js_State *J, js_Object *obj, js_Property *node, const char *name)
|
||||
{
|
||||
js_Property *temp, *succ;
|
||||
|
||||
if (node != &sentinel) {
|
||||
int c = strcmp(name, node->name);
|
||||
if (c < 0) {
|
||||
node->left = delete(J, obj, node->left, name);
|
||||
} else if (c > 0) {
|
||||
node->right = delete(J, obj, node->right, name);
|
||||
} else {
|
||||
if (node->left == &sentinel) {
|
||||
temp = node;
|
||||
node = node->right;
|
||||
freeproperty(J, obj, temp);
|
||||
} else if (node->right == &sentinel) {
|
||||
temp = node;
|
||||
node = node->left;
|
||||
freeproperty(J, obj, temp);
|
||||
} else {
|
||||
succ = node->right;
|
||||
while (succ->left != &sentinel)
|
||||
succ = succ->left;
|
||||
node->name = succ->name;
|
||||
node->atts = succ->atts;
|
||||
node->value = succ->value;
|
||||
node->right = delete(J, obj, node->right, succ->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (node->left->level < node->level - 1 ||
|
||||
node->right->level < node->level - 1)
|
||||
{
|
||||
if (node->right->level > --node->level)
|
||||
node->right->level = node->level;
|
||||
node = skew(node);
|
||||
node->right = skew(node->right);
|
||||
node->right->right = skew(node->right->right);
|
||||
node = split(node);
|
||||
node->right = split(node->right);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
js_Object *jsV_newobject(js_State *J, enum js_Class type, js_Object *prototype)
|
||||
{
|
||||
js_Object *obj = js_malloc(J, sizeof *obj);
|
||||
memset(obj, 0, sizeof *obj);
|
||||
obj->gcmark = 0;
|
||||
obj->gcnext = J->gcobj;
|
||||
J->gcobj = obj;
|
||||
++J->gccounter;
|
||||
|
||||
obj->type = type;
|
||||
obj->properties = &sentinel;
|
||||
obj->prototype = prototype;
|
||||
obj->extensible = 1;
|
||||
return obj;
|
||||
}
|
||||
|
||||
js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name)
|
||||
{
|
||||
return lookup(obj->properties, name);
|
||||
}
|
||||
|
||||
js_Property *jsV_getpropertyx(js_State *J, js_Object *obj, const char *name, int *own)
|
||||
{
|
||||
*own = 1;
|
||||
do {
|
||||
js_Property *ref = lookup(obj->properties, name);
|
||||
if (ref)
|
||||
return ref;
|
||||
obj = obj->prototype;
|
||||
*own = 0;
|
||||
} while (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name)
|
||||
{
|
||||
do {
|
||||
js_Property *ref = lookup(obj->properties, name);
|
||||
if (ref)
|
||||
return ref;
|
||||
obj = obj->prototype;
|
||||
} while (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static js_Property *jsV_getenumproperty(js_State *J, js_Object *obj, const char *name)
|
||||
{
|
||||
do {
|
||||
js_Property *ref = lookup(obj->properties, name);
|
||||
if (ref && !(ref->atts & JS_DONTENUM))
|
||||
return ref;
|
||||
obj = obj->prototype;
|
||||
} while (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name)
|
||||
{
|
||||
js_Property *result;
|
||||
|
||||
if (!obj->extensible) {
|
||||
result = lookup(obj->properties, name);
|
||||
if (J->strict && !result)
|
||||
js_typeerror(J, "object is non-extensible");
|
||||
return result;
|
||||
}
|
||||
|
||||
obj->properties = insert(J, obj, obj->properties, name, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void jsV_delproperty(js_State *J, js_Object *obj, const char *name)
|
||||
{
|
||||
obj->properties = delete(J, obj, obj->properties, name);
|
||||
}
|
||||
|
||||
/* Flatten hierarchy of enumerable properties into an iterator object */
|
||||
|
||||
static js_Iterator *itwalk(js_State *J, js_Iterator *iter, js_Property *prop, js_Object *seen)
|
||||
{
|
||||
if (prop->right != &sentinel)
|
||||
iter = itwalk(J, iter, prop->right, seen);
|
||||
if (!(prop->atts & JS_DONTENUM)) {
|
||||
if (!seen || !jsV_getenumproperty(J, seen, prop->name)) {
|
||||
js_Iterator *head = js_malloc(J, sizeof *head);
|
||||
head->name = prop->name;
|
||||
head->next = iter;
|
||||
iter = head;
|
||||
}
|
||||
}
|
||||
if (prop->left != &sentinel)
|
||||
iter = itwalk(J, iter, prop->left, seen);
|
||||
return iter;
|
||||
}
|
||||
|
||||
static js_Iterator *itflatten(js_State *J, js_Object *obj)
|
||||
{
|
||||
js_Iterator *iter = NULL;
|
||||
if (obj->prototype)
|
||||
iter = itflatten(J, obj->prototype);
|
||||
if (obj->properties != &sentinel)
|
||||
iter = itwalk(J, iter, obj->properties, obj->prototype);
|
||||
return iter;
|
||||
}
|
||||
|
||||
js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own)
|
||||
{
|
||||
char buf[32];
|
||||
int k;
|
||||
js_Object *io = jsV_newobject(J, JS_CITERATOR, NULL);
|
||||
io->u.iter.target = obj;
|
||||
if (own) {
|
||||
io->u.iter.head = NULL;
|
||||
if (obj->properties != &sentinel)
|
||||
io->u.iter.head = itwalk(J, io->u.iter.head, obj->properties, NULL);
|
||||
} else {
|
||||
io->u.iter.head = itflatten(J, obj);
|
||||
}
|
||||
if (obj->type == JS_CSTRING) {
|
||||
js_Iterator *tail = io->u.iter.head;
|
||||
if (tail)
|
||||
while (tail->next)
|
||||
tail = tail->next;
|
||||
for (k = 0; k < obj->u.s.length; ++k) {
|
||||
js_itoa(buf, k);
|
||||
if (!jsV_getenumproperty(J, obj, buf)) {
|
||||
js_Iterator *node = js_malloc(J, sizeof *node);
|
||||
node->name = js_intern(J, js_itoa(buf, k));
|
||||
node->next = NULL;
|
||||
if (!tail)
|
||||
io->u.iter.head = tail = node;
|
||||
else {
|
||||
tail->next = node;
|
||||
tail = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return io;
|
||||
}
|
||||
|
||||
const char *jsV_nextiterator(js_State *J, js_Object *io)
|
||||
{
|
||||
int k;
|
||||
if (io->type != JS_CITERATOR)
|
||||
js_typeerror(J, "not an iterator");
|
||||
while (io->u.iter.head) {
|
||||
js_Iterator *next = io->u.iter.head->next;
|
||||
const char *name = io->u.iter.head->name;
|
||||
js_free(J, io->u.iter.head);
|
||||
io->u.iter.head = next;
|
||||
if (jsV_getproperty(J, io->u.iter.target, name))
|
||||
return name;
|
||||
if (io->u.iter.target->type == JS_CSTRING)
|
||||
if (js_isarrayindex(J, name, &k) && k < io->u.iter.target->u.s.length)
|
||||
return name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Walk all the properties and delete them one by one for arrays */
|
||||
|
||||
void jsV_resizearray(js_State *J, js_Object *obj, int newlen)
|
||||
{
|
||||
char buf[32];
|
||||
const char *s;
|
||||
int k;
|
||||
if (newlen < obj->u.a.length) {
|
||||
if (obj->u.a.length > obj->count * 2) {
|
||||
js_Object *it = jsV_newiterator(J, obj, 1);
|
||||
while ((s = jsV_nextiterator(J, it))) {
|
||||
k = jsV_numbertointeger(jsV_stringtonumber(J, s));
|
||||
if (k >= newlen && !strcmp(s, jsV_numbertostring(J, buf, k)))
|
||||
jsV_delproperty(J, obj, s);
|
||||
}
|
||||
} else {
|
||||
for (k = newlen; k < obj->u.a.length; ++k) {
|
||||
jsV_delproperty(J, obj, js_itoa(buf, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
obj->u.a.length = newlen;
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
#include "regexp.h"
|
||||
|
||||
void js_newregexp(js_State *J, const char *pattern, int flags)
|
||||
{
|
||||
const char *error;
|
||||
js_Object *obj;
|
||||
Reprog *prog;
|
||||
int opts;
|
||||
|
||||
obj = jsV_newobject(J, JS_CREGEXP, J->RegExp_prototype);
|
||||
|
||||
opts = 0;
|
||||
if (flags & JS_REGEXP_I) opts |= REG_ICASE;
|
||||
if (flags & JS_REGEXP_M) opts |= REG_NEWLINE;
|
||||
|
||||
prog = js_regcompx(J->alloc, J->actx, pattern, opts, &error);
|
||||
if (!prog)
|
||||
js_syntaxerror(J, "regular expression: %s", error);
|
||||
|
||||
obj->u.r.prog = prog;
|
||||
obj->u.r.source = js_strdup(J, pattern);
|
||||
obj->u.r.flags = flags;
|
||||
obj->u.r.last = 0;
|
||||
js_pushobject(J, obj);
|
||||
}
|
||||
|
||||
void js_RegExp_prototype_exec(js_State *J, js_Regexp *re, const char *text)
|
||||
{
|
||||
int result;
|
||||
int i;
|
||||
int opts;
|
||||
Resub m;
|
||||
|
||||
opts = 0;
|
||||
if (re->flags & JS_REGEXP_G) {
|
||||
if (re->last > strlen(text)) {
|
||||
re->last = 0;
|
||||
js_pushnull(J);
|
||||
return;
|
||||
}
|
||||
if (re->last > 0) {
|
||||
text += re->last;
|
||||
opts |= REG_NOTBOL;
|
||||
}
|
||||
}
|
||||
|
||||
result = js_regexec(re->prog, text, &m, opts);
|
||||
if (result < 0)
|
||||
js_error(J, "regexec failed");
|
||||
if (result == 0) {
|
||||
js_newarray(J);
|
||||
js_pushstring(J, text);
|
||||
js_setproperty(J, -2, "input");
|
||||
js_pushnumber(J, js_utfptrtoidx(text, m.sub[0].sp));
|
||||
js_setproperty(J, -2, "index");
|
||||
for (i = 0; i < m.nsub; ++i) {
|
||||
js_pushlstring(J, m.sub[i].sp, m.sub[i].ep - m.sub[i].sp);
|
||||
js_setindex(J, -2, i);
|
||||
}
|
||||
if (re->flags & JS_REGEXP_G)
|
||||
re->last = re->last + (m.sub[0].ep - text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (re->flags & JS_REGEXP_G)
|
||||
re->last = 0;
|
||||
|
||||
js_pushnull(J);
|
||||
}
|
||||
|
||||
static void Rp_test(js_State *J)
|
||||
{
|
||||
js_Regexp *re;
|
||||
const char *text;
|
||||
int result;
|
||||
int opts;
|
||||
Resub m;
|
||||
|
||||
re = js_toregexp(J, 0);
|
||||
text = js_tostring(J, 1);
|
||||
|
||||
opts = 0;
|
||||
if (re->flags & JS_REGEXP_G) {
|
||||
if (re->last > strlen(text)) {
|
||||
re->last = 0;
|
||||
js_pushboolean(J, 0);
|
||||
return;
|
||||
}
|
||||
if (re->last > 0) {
|
||||
text += re->last;
|
||||
opts |= REG_NOTBOL;
|
||||
}
|
||||
}
|
||||
|
||||
result = js_regexec(re->prog, text, &m, opts);
|
||||
if (result < 0)
|
||||
js_error(J, "regexec failed");
|
||||
if (result == 0) {
|
||||
if (re->flags & JS_REGEXP_G)
|
||||
re->last = re->last + (m.sub[0].ep - text);
|
||||
js_pushboolean(J, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (re->flags & JS_REGEXP_G)
|
||||
re->last = 0;
|
||||
|
||||
js_pushboolean(J, 0);
|
||||
}
|
||||
|
||||
static void jsB_new_RegExp(js_State *J)
|
||||
{
|
||||
js_Regexp *old;
|
||||
const char *pattern;
|
||||
int flags;
|
||||
|
||||
if (js_isregexp(J, 1)) {
|
||||
if (js_isdefined(J, 2))
|
||||
js_typeerror(J, "cannot supply flags when creating one RegExp from another");
|
||||
old = js_toregexp(J, 1);
|
||||
pattern = old->source;
|
||||
flags = old->flags;
|
||||
} else if (js_isundefined(J, 1)) {
|
||||
pattern = "(?:)";
|
||||
flags = 0;
|
||||
} else {
|
||||
pattern = js_tostring(J, 1);
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
if (strlen(pattern) == 0)
|
||||
pattern = "(?:)";
|
||||
|
||||
if (js_isdefined(J, 2)) {
|
||||
const char *s = js_tostring(J, 2);
|
||||
int g = 0, i = 0, m = 0;
|
||||
while (*s) {
|
||||
if (*s == 'g') ++g;
|
||||
else if (*s == 'i') ++i;
|
||||
else if (*s == 'm') ++m;
|
||||
else js_syntaxerror(J, "invalid regular expression flag: '%c'", *s);
|
||||
++s;
|
||||
}
|
||||
if (g > 1) js_syntaxerror(J, "invalid regular expression flag: 'g'");
|
||||
if (i > 1) js_syntaxerror(J, "invalid regular expression flag: 'i'");
|
||||
if (m > 1) js_syntaxerror(J, "invalid regular expression flag: 'm'");
|
||||
if (g) flags |= JS_REGEXP_G;
|
||||
if (i) flags |= JS_REGEXP_I;
|
||||
if (m) flags |= JS_REGEXP_M;
|
||||
}
|
||||
|
||||
js_newregexp(J, pattern, flags);
|
||||
}
|
||||
|
||||
static void jsB_RegExp(js_State *J)
|
||||
{
|
||||
if (js_isregexp(J, 1))
|
||||
return;
|
||||
jsB_new_RegExp(J);
|
||||
}
|
||||
|
||||
static void Rp_toString(js_State *J)
|
||||
{
|
||||
js_Regexp *re;
|
||||
char *out;
|
||||
|
||||
re = js_toregexp(J, 0);
|
||||
|
||||
out = js_malloc(J, strlen(re->source) + 6); /* extra space for //gim */
|
||||
strcpy(out, "/");
|
||||
strcat(out, re->source);
|
||||
strcat(out, "/");
|
||||
if (re->flags & JS_REGEXP_G) strcat(out, "g");
|
||||
if (re->flags & JS_REGEXP_I) strcat(out, "i");
|
||||
if (re->flags & JS_REGEXP_M) strcat(out, "m");
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, out);
|
||||
js_throw(J);
|
||||
}
|
||||
js_pop(J, 0);
|
||||
js_pushstring(J, out);
|
||||
js_endtry(J);
|
||||
js_free(J, out);
|
||||
}
|
||||
|
||||
static void Rp_exec(js_State *J)
|
||||
{
|
||||
js_RegExp_prototype_exec(J, js_toregexp(J, 0), js_tostring(J, 1));
|
||||
}
|
||||
|
||||
void jsB_initregexp(js_State *J)
|
||||
{
|
||||
js_pushobject(J, J->RegExp_prototype);
|
||||
{
|
||||
jsB_propf(J, "RegExp.prototype.toString", Rp_toString, 0);
|
||||
jsB_propf(J, "RegExp.prototype.test", Rp_test, 0);
|
||||
jsB_propf(J, "RegExp.prototype.exec", Rp_exec, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_RegExp, jsB_new_RegExp, "RegExp", 1);
|
||||
js_defglobal(J, "RegExp", JS_DONTENUM);
|
||||
}
|
@ -1,289 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
#include "jscompile.h"
|
||||
#include "utf.h"
|
||||
|
||||
static void reprvalue(js_State *J, js_Buffer **sb);
|
||||
|
||||
static void reprnum(js_State *J, js_Buffer **sb, double n)
|
||||
{
|
||||
char buf[40];
|
||||
if (n == 0 && signbit(n))
|
||||
js_puts(J, sb, "-0");
|
||||
else
|
||||
js_puts(J, sb, jsV_numbertostring(J, buf, n));
|
||||
}
|
||||
|
||||
static void reprstr(js_State *J, js_Buffer **sb, const char *s)
|
||||
{
|
||||
static const char *HEX = "0123456789ABCDEF";
|
||||
int i, n;
|
||||
Rune c;
|
||||
js_putc(J, sb, '"');
|
||||
while (*s) {
|
||||
n = chartorune(&c, s);
|
||||
switch (c) {
|
||||
case '"': js_puts(J, sb, "\\\""); break;
|
||||
case '\\': js_puts(J, sb, "\\\\"); break;
|
||||
case '\b': js_puts(J, sb, "\\b"); break;
|
||||
case '\f': js_puts(J, sb, "\\f"); break;
|
||||
case '\n': js_puts(J, sb, "\\n"); break;
|
||||
case '\r': js_puts(J, sb, "\\r"); break;
|
||||
case '\t': js_puts(J, sb, "\\t"); break;
|
||||
default:
|
||||
if (c < ' ') {
|
||||
js_putc(J, sb, '\\');
|
||||
js_putc(J, sb, 'x');
|
||||
js_putc(J, sb, HEX[(c>>4)&15]);
|
||||
js_putc(J, sb, HEX[c&15]);
|
||||
} else if (c < 128) {
|
||||
js_putc(J, sb, c);
|
||||
} else if (c < 0x10000) {
|
||||
js_putc(J, sb, '\\');
|
||||
js_putc(J, sb, 'u');
|
||||
js_putc(J, sb, HEX[(c>>12)&15]);
|
||||
js_putc(J, sb, HEX[(c>>8)&15]);
|
||||
js_putc(J, sb, HEX[(c>>4)&15]);
|
||||
js_putc(J, sb, HEX[c&15]);
|
||||
} else {
|
||||
for (i = 0; i < n; ++i)
|
||||
js_putc(J, sb, s[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
s += n;
|
||||
}
|
||||
js_putc(J, sb, '"');
|
||||
}
|
||||
|
||||
#ifndef isalpha
|
||||
#define isalpha(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
|
||||
#endif
|
||||
#ifndef isdigit
|
||||
#define isdigit(c) (c >= '0' && c <= '9')
|
||||
#endif
|
||||
|
||||
static void reprident(js_State *J, js_Buffer **sb, const char *name)
|
||||
{
|
||||
const char *p = name;
|
||||
if (isdigit(*p))
|
||||
while (isdigit(*p))
|
||||
++p;
|
||||
else if (isalpha(*p) || *p == '_')
|
||||
while (isdigit(*p) || isalpha(*p) || *p == '_')
|
||||
++p;
|
||||
if (p > name && *p == 0)
|
||||
js_puts(J, sb, name);
|
||||
else
|
||||
reprstr(J, sb, name);
|
||||
}
|
||||
|
||||
static void reprobject(js_State *J, js_Buffer **sb)
|
||||
{
|
||||
const char *key;
|
||||
int i, n;
|
||||
|
||||
n = js_gettop(J) - 1;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (js_isobject(J, i)) {
|
||||
if (js_toobject(J, i) == js_toobject(J, -1)) {
|
||||
js_puts(J, sb, "{}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n = 0;
|
||||
js_putc(J, sb, '{');
|
||||
js_pushiterator(J, -1, 1);
|
||||
while ((key = js_nextiterator(J, -1))) {
|
||||
if (n++ > 0)
|
||||
js_puts(J, sb, ", ");
|
||||
reprident(J, sb, key);
|
||||
js_puts(J, sb, ": ");
|
||||
js_getproperty(J, -2, key);
|
||||
reprvalue(J, sb);
|
||||
js_pop(J, 1);
|
||||
}
|
||||
js_pop(J, 1);
|
||||
js_putc(J, sb, '}');
|
||||
}
|
||||
|
||||
static void reprarray(js_State *J, js_Buffer **sb)
|
||||
{
|
||||
int n, i;
|
||||
|
||||
n = js_gettop(J) - 1;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (js_isobject(J, i)) {
|
||||
if (js_toobject(J, i) == js_toobject(J, -1)) {
|
||||
js_puts(J, sb, "[]");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
js_putc(J, sb, '[');
|
||||
n = js_getlength(J, -1);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (i > 0)
|
||||
js_puts(J, sb, ", ");
|
||||
if (js_hasindex(J, -1, i)) {
|
||||
reprvalue(J, sb);
|
||||
js_pop(J, 1);
|
||||
}
|
||||
}
|
||||
js_putc(J, sb, ']');
|
||||
}
|
||||
|
||||
static void reprfun(js_State *J, js_Buffer **sb, js_Function *fun)
|
||||
{
|
||||
int i;
|
||||
js_puts(J, sb, "function ");
|
||||
js_puts(J, sb, fun->name);
|
||||
js_putc(J, sb, '(');
|
||||
for (i = 0; i < fun->numparams; ++i) {
|
||||
if (i > 0)
|
||||
js_puts(J, sb, ", ");
|
||||
js_puts(J, sb, fun->vartab[i]);
|
||||
}
|
||||
js_puts(J, sb, ") { [byte code] }");
|
||||
}
|
||||
|
||||
static void reprvalue(js_State *J, js_Buffer **sb)
|
||||
{
|
||||
if (js_isundefined(J, -1))
|
||||
js_puts(J, sb, "undefined");
|
||||
else if (js_isnull(J, -1))
|
||||
js_puts(J, sb, "null");
|
||||
else if (js_isboolean(J, -1))
|
||||
js_puts(J, sb, js_toboolean(J, -1) ? "true" : "false");
|
||||
else if (js_isnumber(J, -1))
|
||||
reprnum(J, sb, js_tonumber(J, -1));
|
||||
else if (js_isstring(J, -1))
|
||||
reprstr(J, sb, js_tostring(J, -1));
|
||||
else if (js_isobject(J, -1)) {
|
||||
js_Object *obj = js_toobject(J, -1);
|
||||
switch (obj->type) {
|
||||
default:
|
||||
reprobject(J, sb);
|
||||
break;
|
||||
case JS_CARRAY:
|
||||
reprarray(J, sb);
|
||||
break;
|
||||
case JS_CFUNCTION:
|
||||
case JS_CSCRIPT:
|
||||
case JS_CEVAL:
|
||||
reprfun(J, sb, obj->u.f.function);
|
||||
break;
|
||||
case JS_CCFUNCTION:
|
||||
js_puts(J, sb, "function ");
|
||||
js_puts(J, sb, obj->u.c.name);
|
||||
js_puts(J, sb, "() { [native code] }");
|
||||
break;
|
||||
case JS_CBOOLEAN:
|
||||
js_puts(J, sb, "(new Boolean(");
|
||||
js_puts(J, sb, obj->u.boolean ? "true" : "false");
|
||||
js_puts(J, sb, "))");
|
||||
break;
|
||||
case JS_CNUMBER:
|
||||
js_puts(J, sb, "(new Number(");
|
||||
reprnum(J, sb, obj->u.number);
|
||||
js_puts(J, sb, "))");
|
||||
break;
|
||||
case JS_CSTRING:
|
||||
js_puts(J, sb, "(new String(");
|
||||
reprstr(J, sb, obj->u.s.string);
|
||||
js_puts(J, sb, "))");
|
||||
break;
|
||||
case JS_CREGEXP:
|
||||
js_putc(J, sb, '/');
|
||||
js_puts(J, sb, obj->u.r.source);
|
||||
js_putc(J, sb, '/');
|
||||
if (obj->u.r.flags & JS_REGEXP_G) js_putc(J, sb, 'g');
|
||||
if (obj->u.r.flags & JS_REGEXP_I) js_putc(J, sb, 'i');
|
||||
if (obj->u.r.flags & JS_REGEXP_M) js_putc(J, sb, 'm');
|
||||
break;
|
||||
case JS_CDATE:
|
||||
{
|
||||
char buf[40];
|
||||
js_puts(J, sb, "(new Date(");
|
||||
js_puts(J, sb, jsV_numbertostring(J, buf, obj->u.number));
|
||||
js_puts(J, sb, "))");
|
||||
}
|
||||
break;
|
||||
case JS_CERROR:
|
||||
js_puts(J, sb, "(new ");
|
||||
js_getproperty(J, -1, "name");
|
||||
js_puts(J, sb, js_tostring(J, -1));
|
||||
js_pop(J, 1);
|
||||
js_putc(J, sb, '(');
|
||||
js_getproperty(J, -1, "message");
|
||||
reprstr(J, sb, js_tostring(J, -1));
|
||||
js_pop(J, 1);
|
||||
js_puts(J, sb, "))");
|
||||
break;
|
||||
case JS_CMATH:
|
||||
js_puts(J, sb, "Math");
|
||||
break;
|
||||
case JS_CJSON:
|
||||
js_puts(J, sb, "JSON");
|
||||
break;
|
||||
case JS_CITERATOR:
|
||||
js_puts(J, sb, "[iterator ");
|
||||
break;
|
||||
case JS_CUSERDATA:
|
||||
js_puts(J, sb, "[userdata ");
|
||||
js_puts(J, sb, obj->u.user.tag);
|
||||
js_putc(J, sb, ']');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void js_repr(js_State *J, int idx)
|
||||
{
|
||||
js_Buffer *sb = NULL;
|
||||
int savebot;
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
js_copy(J, idx);
|
||||
|
||||
savebot = J->bot;
|
||||
J->bot = J->top - 1;
|
||||
reprvalue(J, &sb);
|
||||
J->bot = savebot;
|
||||
|
||||
js_pop(J, 1);
|
||||
|
||||
js_putc(J, &sb, 0);
|
||||
js_pushstring(J, sb ? sb->s : "undefined");
|
||||
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
|
||||
const char *js_torepr(js_State *J, int idx)
|
||||
{
|
||||
js_repr(J, idx);
|
||||
js_replace(J, idx < 0 ? idx-1 : idx);
|
||||
return js_tostring(J, idx);
|
||||
}
|
||||
|
||||
const char *js_tryrepr(js_State *J, int idx, const char *error)
|
||||
{
|
||||
const char *s;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
s = js_torepr(J, idx);
|
||||
js_endtry(J);
|
||||
return s;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +0,0 @@
|
||||
#ifndef js_run_h
|
||||
#define js_run_h
|
||||
|
||||
js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
|
||||
|
||||
struct js_Environment
|
||||
{
|
||||
js_Environment *outer;
|
||||
js_Object *variables;
|
||||
|
||||
js_Environment *gcnext;
|
||||
int gcmark;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,298 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void *js_defaultalloc(void *actx, void *ptr, int size)
|
||||
{
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return realloc(ptr, (size_t)size);
|
||||
}
|
||||
|
||||
static void js_defaultreport(js_State *J, const char *message)
|
||||
{
|
||||
fputs(message, stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static void js_defaultpanic(js_State *J)
|
||||
{
|
||||
js_report(J, "uncaught exception");
|
||||
/* return to javascript to abort */
|
||||
}
|
||||
|
||||
int js_ploadstring(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
if (js_try(J))
|
||||
return 1;
|
||||
js_loadstring(J, filename, source);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int js_ploadfile(js_State *J, const char *filename)
|
||||
{
|
||||
if (js_try(J))
|
||||
return 1;
|
||||
js_loadfile(J, filename);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *js_trystring(js_State *J, int idx, const char *error)
|
||||
{
|
||||
const char *s;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
s = js_tostring(J, idx);
|
||||
js_endtry(J);
|
||||
return s;
|
||||
}
|
||||
|
||||
double js_trynumber(js_State *J, int idx, double error)
|
||||
{
|
||||
double v;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
v = js_tonumber(J, idx);
|
||||
js_endtry(J);
|
||||
return v;
|
||||
}
|
||||
|
||||
int js_tryinteger(js_State *J, int idx, int error)
|
||||
{
|
||||
int v;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
v = js_tointeger(J, idx);
|
||||
js_endtry(J);
|
||||
return v;
|
||||
}
|
||||
|
||||
int js_tryboolean(js_State *J, int idx, int error)
|
||||
{
|
||||
int v;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
v = js_toboolean(J, idx);
|
||||
js_endtry(J);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void js_loadstringx(js_State *J, const char *filename, const char *source, int iseval)
|
||||
{
|
||||
js_Ast *P;
|
||||
js_Function *F;
|
||||
|
||||
if (js_try(J)) {
|
||||
jsP_freeparse(J);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
P = jsP_parse(J, filename, source);
|
||||
F = jsC_compilescript(J, P, iseval ? J->strict : J->default_strict);
|
||||
jsP_freeparse(J);
|
||||
js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE, iseval ? JS_CEVAL : JS_CSCRIPT);
|
||||
|
||||
js_endtry(J);
|
||||
}
|
||||
|
||||
void js_loadeval(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
js_loadstringx(J, filename, source, 1);
|
||||
}
|
||||
|
||||
void js_loadstring(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
js_loadstringx(J, filename, source, 0);
|
||||
}
|
||||
|
||||
void js_loadfile(js_State *J, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char *s, *p;
|
||||
int n, t;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f) {
|
||||
js_error(J, "cannot open file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (fseek(f, 0, SEEK_END) < 0) {
|
||||
fclose(f);
|
||||
js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
n = ftell(f);
|
||||
if (n < 0) {
|
||||
fclose(f);
|
||||
js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (fseek(f, 0, SEEK_SET) < 0) {
|
||||
fclose(f);
|
||||
js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (js_try(J)) {
|
||||
fclose(f);
|
||||
js_throw(J);
|
||||
}
|
||||
s = js_malloc(J, n + 1); /* add space for string terminator */
|
||||
js_endtry(J);
|
||||
|
||||
t = fread(s, 1, (size_t)n, f);
|
||||
if (t != n) {
|
||||
js_free(J, s);
|
||||
fclose(f);
|
||||
js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
s[n] = 0; /* zero-terminate string containing file data */
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, s);
|
||||
fclose(f);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
/* skip first line if it starts with "#!" */
|
||||
p = s;
|
||||
if (p[0] == '#' && p[1] == '!') {
|
||||
p += 2;
|
||||
while (*p && *p != '\n')
|
||||
++p;
|
||||
}
|
||||
|
||||
js_loadstring(J, filename, p);
|
||||
|
||||
js_free(J, s);
|
||||
fclose(f);
|
||||
js_endtry(J);
|
||||
}
|
||||
|
||||
int js_dostring(js_State *J, const char *source)
|
||||
{
|
||||
if (js_try(J)) {
|
||||
js_report(J, js_trystring(J, -1, "Error"));
|
||||
js_pop(J, 1);
|
||||
return 1;
|
||||
}
|
||||
js_loadstring(J, "[string]", source);
|
||||
js_pushundefined(J);
|
||||
js_call(J, 0);
|
||||
js_pop(J, 1);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int js_dofile(js_State *J, const char *filename)
|
||||
{
|
||||
if (js_try(J)) {
|
||||
js_report(J, js_trystring(J, -1, "Error"));
|
||||
js_pop(J, 1);
|
||||
return 1;
|
||||
}
|
||||
js_loadfile(J, filename);
|
||||
js_pushundefined(J);
|
||||
js_call(J, 0);
|
||||
js_pop(J, 1);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
js_Panic js_atpanic(js_State *J, js_Panic panic)
|
||||
{
|
||||
js_Panic old = J->panic;
|
||||
J->panic = panic;
|
||||
return old;
|
||||
}
|
||||
|
||||
void js_report(js_State *J, const char *message)
|
||||
{
|
||||
if (J->report)
|
||||
J->report(J, message);
|
||||
}
|
||||
|
||||
void js_setreport(js_State *J, js_Report report)
|
||||
{
|
||||
J->report = report;
|
||||
}
|
||||
|
||||
void js_setcontext(js_State *J, void *uctx)
|
||||
{
|
||||
J->uctx = uctx;
|
||||
}
|
||||
|
||||
void *js_getcontext(js_State *J)
|
||||
{
|
||||
return J->uctx;
|
||||
}
|
||||
|
||||
js_State *js_newstate(js_Alloc alloc, void *actx, int flags)
|
||||
{
|
||||
js_State *J;
|
||||
|
||||
assert(sizeof(js_Value) == 16);
|
||||
assert(soffsetof(js_Value, type) == 15);
|
||||
|
||||
if (!alloc)
|
||||
alloc = js_defaultalloc;
|
||||
|
||||
J = alloc(actx, NULL, sizeof *J);
|
||||
if (!J)
|
||||
return NULL;
|
||||
memset(J, 0, sizeof(*J));
|
||||
J->actx = actx;
|
||||
J->alloc = alloc;
|
||||
|
||||
if (flags & JS_STRICT)
|
||||
J->strict = J->default_strict = 1;
|
||||
|
||||
J->trace[0].name = "-top-";
|
||||
J->trace[0].file = "native";
|
||||
J->trace[0].line = 0;
|
||||
|
||||
J->report = js_defaultreport;
|
||||
J->panic = js_defaultpanic;
|
||||
|
||||
J->stack = alloc(actx, NULL, JS_STACKSIZE * sizeof *J->stack);
|
||||
if (!J->stack) {
|
||||
alloc(actx, NULL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
J->gcmark = 1;
|
||||
J->nextref = 0;
|
||||
J->gcthresh = 0; /* reaches stability within ~ 2-5 GC cycles */
|
||||
|
||||
J->R = jsV_newobject(J, JS_COBJECT, NULL);
|
||||
J->G = jsV_newobject(J, JS_COBJECT, NULL);
|
||||
J->E = jsR_newenvironment(J, J->G, NULL);
|
||||
J->GE = J->E;
|
||||
|
||||
jsB_init(J);
|
||||
|
||||
return J;
|
||||
}
|
@ -1,711 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
#include "utf.h"
|
||||
#include "regexp.h"
|
||||
|
||||
static int js_doregexec(js_State *J, Reprog *prog, const char *string, Resub *sub, int eflags)
|
||||
{
|
||||
int result = js_regexec(prog, string, sub, eflags);
|
||||
if (result < 0)
|
||||
js_error(J, "regexec failed");
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *checkstring(js_State *J, int idx)
|
||||
{
|
||||
if (!js_iscoercible(J, idx))
|
||||
js_typeerror(J, "string function called on null or undefined");
|
||||
return js_tostring(J, idx);
|
||||
}
|
||||
|
||||
int js_runeat(js_State *J, const char *s, int i)
|
||||
{
|
||||
Rune rune = EOF;
|
||||
while (i-- >= 0) {
|
||||
rune = *(unsigned char*)s;
|
||||
if (rune < Runeself) {
|
||||
if (rune == 0)
|
||||
return EOF;
|
||||
++s;
|
||||
} else
|
||||
s += chartorune(&rune, s);
|
||||
}
|
||||
return rune;
|
||||
}
|
||||
|
||||
const char *js_utfidxtoptr(const char *s, int i)
|
||||
{
|
||||
Rune rune;
|
||||
while (i-- > 0) {
|
||||
rune = *(unsigned char*)s;
|
||||
if (rune < Runeself) {
|
||||
if (rune == 0)
|
||||
return NULL;
|
||||
++s;
|
||||
} else
|
||||
s += chartorune(&rune, s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int js_utfptrtoidx(const char *s, const char *p)
|
||||
{
|
||||
Rune rune;
|
||||
int i = 0;
|
||||
while (s < p) {
|
||||
if (*(unsigned char *)s < Runeself)
|
||||
++s;
|
||||
else
|
||||
s += chartorune(&rune, s);
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void jsB_new_String(js_State *J)
|
||||
{
|
||||
js_newstring(J, js_gettop(J) > 1 ? js_tostring(J, 1) : "");
|
||||
}
|
||||
|
||||
static void jsB_String(js_State *J)
|
||||
{
|
||||
js_pushstring(J, js_gettop(J) > 1 ? js_tostring(J, 1) : "");
|
||||
}
|
||||
|
||||
static void Sp_toString(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
|
||||
js_pushliteral(J, self->u.s.string);
|
||||
}
|
||||
|
||||
static void Sp_valueOf(js_State *J)
|
||||
{
|
||||
js_Object *self = js_toobject(J, 0);
|
||||
if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
|
||||
js_pushliteral(J, self->u.s.string);
|
||||
}
|
||||
|
||||
static void Sp_charAt(js_State *J)
|
||||
{
|
||||
char buf[UTFmax + 1];
|
||||
const char *s = checkstring(J, 0);
|
||||
int pos = js_tointeger(J, 1);
|
||||
Rune rune = js_runeat(J, s, pos);
|
||||
if (rune >= 0) {
|
||||
buf[runetochar(buf, &rune)] = 0;
|
||||
js_pushstring(J, buf);
|
||||
} else {
|
||||
js_pushliteral(J, "");
|
||||
}
|
||||
}
|
||||
|
||||
static void Sp_charCodeAt(js_State *J)
|
||||
{
|
||||
const char *s = checkstring(J, 0);
|
||||
int pos = js_tointeger(J, 1);
|
||||
Rune rune = js_runeat(J, s, pos);
|
||||
if (rune >= 0)
|
||||
js_pushnumber(J, rune);
|
||||
else
|
||||
js_pushnumber(J, NAN);
|
||||
}
|
||||
|
||||
static void Sp_concat(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
int n;
|
||||
char * volatile out;
|
||||
const char *s;
|
||||
|
||||
if (top == 1)
|
||||
return;
|
||||
|
||||
s = checkstring(J, 0);
|
||||
n = strlen(s);
|
||||
out = js_malloc(J, n + 1);
|
||||
strcpy(out, s);
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, out);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
for (i = 1; i < top; ++i) {
|
||||
s = js_tostring(J, i);
|
||||
n += strlen(s);
|
||||
out = js_realloc(J, out, n + 1);
|
||||
strcat(out, s);
|
||||
}
|
||||
|
||||
js_pushstring(J, out);
|
||||
js_endtry(J);
|
||||
js_free(J, out);
|
||||
}
|
||||
|
||||
static void Sp_indexOf(js_State *J)
|
||||
{
|
||||
const char *haystack = checkstring(J, 0);
|
||||
const char *needle = js_tostring(J, 1);
|
||||
int pos = js_tointeger(J, 2);
|
||||
int len = strlen(needle);
|
||||
int k = 0;
|
||||
Rune rune;
|
||||
while (*haystack) {
|
||||
if (k >= pos && !strncmp(haystack, needle, len)) {
|
||||
js_pushnumber(J, k);
|
||||
return;
|
||||
}
|
||||
haystack += chartorune(&rune, haystack);
|
||||
++k;
|
||||
}
|
||||
js_pushnumber(J, -1);
|
||||
}
|
||||
|
||||
static void Sp_lastIndexOf(js_State *J)
|
||||
{
|
||||
const char *haystack = checkstring(J, 0);
|
||||
const char *needle = js_tostring(J, 1);
|
||||
int pos = js_isdefined(J, 2) ? js_tointeger(J, 2) : (int)strlen(haystack);
|
||||
int len = strlen(needle);
|
||||
int k = 0, last = -1;
|
||||
Rune rune;
|
||||
while (*haystack && k <= pos) {
|
||||
if (!strncmp(haystack, needle, len))
|
||||
last = k;
|
||||
haystack += chartorune(&rune, haystack);
|
||||
++k;
|
||||
}
|
||||
js_pushnumber(J, last);
|
||||
}
|
||||
|
||||
static void Sp_localeCompare(js_State *J)
|
||||
{
|
||||
const char *a = checkstring(J, 0);
|
||||
const char *b = js_tostring(J, 1);
|
||||
js_pushnumber(J, strcmp(a, b));
|
||||
}
|
||||
|
||||
static void Sp_slice(js_State *J)
|
||||
{
|
||||
const char *str = checkstring(J, 0);
|
||||
const char *ss, *ee;
|
||||
int len = utflen(str);
|
||||
int s = js_tointeger(J, 1);
|
||||
int e = js_isdefined(J, 2) ? js_tointeger(J, 2) : len;
|
||||
|
||||
s = s < 0 ? s + len : s;
|
||||
e = e < 0 ? e + len : e;
|
||||
|
||||
s = s < 0 ? 0 : s > len ? len : s;
|
||||
e = e < 0 ? 0 : e > len ? len : e;
|
||||
|
||||
if (s < e) {
|
||||
ss = js_utfidxtoptr(str, s);
|
||||
ee = js_utfidxtoptr(ss, e - s);
|
||||
} else {
|
||||
ss = js_utfidxtoptr(str, e);
|
||||
ee = js_utfidxtoptr(ss, s - e);
|
||||
}
|
||||
|
||||
js_pushlstring(J, ss, ee - ss);
|
||||
}
|
||||
|
||||
static void Sp_substring(js_State *J)
|
||||
{
|
||||
const char *str = checkstring(J, 0);
|
||||
const char *ss, *ee;
|
||||
int len = utflen(str);
|
||||
int s = js_tointeger(J, 1);
|
||||
int e = js_isdefined(J, 2) ? js_tointeger(J, 2) : len;
|
||||
|
||||
s = s < 0 ? 0 : s > len ? len : s;
|
||||
e = e < 0 ? 0 : e > len ? len : e;
|
||||
|
||||
if (s < e) {
|
||||
ss = js_utfidxtoptr(str, s);
|
||||
ee = js_utfidxtoptr(ss, e - s);
|
||||
} else {
|
||||
ss = js_utfidxtoptr(str, e);
|
||||
ee = js_utfidxtoptr(ss, s - e);
|
||||
}
|
||||
|
||||
js_pushlstring(J, ss, ee - ss);
|
||||
}
|
||||
|
||||
static void Sp_toLowerCase(js_State *J)
|
||||
{
|
||||
const char *src = checkstring(J, 0);
|
||||
char *dst = js_malloc(J, UTFmax * strlen(src) + 1);
|
||||
const char *s = src;
|
||||
char *d = dst;
|
||||
Rune rune;
|
||||
while (*s) {
|
||||
s += chartorune(&rune, s);
|
||||
rune = tolowerrune(rune);
|
||||
d += runetochar(d, &rune);
|
||||
}
|
||||
*d = 0;
|
||||
if (js_try(J)) {
|
||||
js_free(J, dst);
|
||||
js_throw(J);
|
||||
}
|
||||
js_pushstring(J, dst);
|
||||
js_endtry(J);
|
||||
js_free(J, dst);
|
||||
}
|
||||
|
||||
static void Sp_toUpperCase(js_State *J)
|
||||
{
|
||||
const char *src = checkstring(J, 0);
|
||||
char *dst = js_malloc(J, UTFmax * strlen(src) + 1);
|
||||
const char *s = src;
|
||||
char *d = dst;
|
||||
Rune rune;
|
||||
while (*s) {
|
||||
s += chartorune(&rune, s);
|
||||
rune = toupperrune(rune);
|
||||
d += runetochar(d, &rune);
|
||||
}
|
||||
*d = 0;
|
||||
if (js_try(J)) {
|
||||
js_free(J, dst);
|
||||
js_throw(J);
|
||||
}
|
||||
js_pushstring(J, dst);
|
||||
js_endtry(J);
|
||||
js_free(J, dst);
|
||||
}
|
||||
|
||||
static int istrim(int c)
|
||||
{
|
||||
return c == 0x9 || c == 0xB || c == 0xC || c == 0x20 || c == 0xA0 || c == 0xFEFF ||
|
||||
c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
|
||||
}
|
||||
|
||||
static void Sp_trim(js_State *J)
|
||||
{
|
||||
const char *s, *e;
|
||||
s = checkstring(J, 0);
|
||||
while (istrim(*s))
|
||||
++s;
|
||||
e = s + strlen(s);
|
||||
while (e > s && istrim(e[-1]))
|
||||
--e;
|
||||
js_pushlstring(J, s, e - s);
|
||||
}
|
||||
|
||||
static void S_fromCharCode(js_State *J)
|
||||
{
|
||||
int i, top = js_gettop(J);
|
||||
Rune c;
|
||||
char *s, *p;
|
||||
|
||||
s = p = js_malloc(J, (top-1) * UTFmax + 1);
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, s);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
for (i = 1; i < top; ++i) {
|
||||
c = js_touint32(J, i);
|
||||
p += runetochar(p, &c);
|
||||
}
|
||||
*p = 0;
|
||||
js_pushstring(J, s);
|
||||
|
||||
js_endtry(J);
|
||||
js_free(J, s);
|
||||
}
|
||||
|
||||
static void Sp_match(js_State *J)
|
||||
{
|
||||
js_Regexp *re;
|
||||
const char *text;
|
||||
int len;
|
||||
const char *a, *b, *c, *e;
|
||||
Resub m;
|
||||
|
||||
text = checkstring(J, 0);
|
||||
|
||||
if (js_isregexp(J, 1))
|
||||
js_copy(J, 1);
|
||||
else if (js_isundefined(J, 1))
|
||||
js_newregexp(J, "", 0);
|
||||
else
|
||||
js_newregexp(J, js_tostring(J, 1), 0);
|
||||
|
||||
re = js_toregexp(J, -1);
|
||||
if (!(re->flags & JS_REGEXP_G)) {
|
||||
js_RegExp_prototype_exec(J, re, text);
|
||||
return;
|
||||
}
|
||||
|
||||
re->last = 0;
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
len = 0;
|
||||
a = text;
|
||||
e = text + strlen(text);
|
||||
while (a <= e) {
|
||||
if (js_doregexec(J, re->prog, a, &m, a > text ? REG_NOTBOL : 0))
|
||||
break;
|
||||
|
||||
b = m.sub[0].sp;
|
||||
c = m.sub[0].ep;
|
||||
|
||||
js_pushlstring(J, b, c - b);
|
||||
js_setindex(J, -2, len++);
|
||||
|
||||
a = c;
|
||||
if (c - b == 0)
|
||||
++a;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
js_pop(J, 1);
|
||||
js_pushnull(J);
|
||||
}
|
||||
}
|
||||
|
||||
static void Sp_search(js_State *J)
|
||||
{
|
||||
js_Regexp *re;
|
||||
const char *text;
|
||||
Resub m;
|
||||
|
||||
text = checkstring(J, 0);
|
||||
|
||||
if (js_isregexp(J, 1))
|
||||
js_copy(J, 1);
|
||||
else if (js_isundefined(J, 1))
|
||||
js_newregexp(J, "", 0);
|
||||
else
|
||||
js_newregexp(J, js_tostring(J, 1), 0);
|
||||
|
||||
re = js_toregexp(J, -1);
|
||||
|
||||
if (!js_doregexec(J, re->prog, text, &m, 0))
|
||||
js_pushnumber(J, js_utfptrtoidx(text, m.sub[0].sp));
|
||||
else
|
||||
js_pushnumber(J, -1);
|
||||
}
|
||||
|
||||
static void Sp_replace_regexp(js_State *J)
|
||||
{
|
||||
js_Regexp *re;
|
||||
const char *source, *s, *r;
|
||||
js_Buffer *sb = NULL;
|
||||
int n, x;
|
||||
Resub m;
|
||||
|
||||
source = checkstring(J, 0);
|
||||
re = js_toregexp(J, 1);
|
||||
|
||||
if (js_doregexec(J, re->prog, source, &m, 0)) {
|
||||
js_copy(J, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
re->last = 0;
|
||||
|
||||
loop:
|
||||
s = m.sub[0].sp;
|
||||
n = m.sub[0].ep - m.sub[0].sp;
|
||||
|
||||
if (js_iscallable(J, 2)) {
|
||||
js_copy(J, 2);
|
||||
js_pushundefined(J);
|
||||
for (x = 0; m.sub[x].sp; ++x) /* arg 0..x: substring and subexps that matched */
|
||||
js_pushlstring(J, m.sub[x].sp, m.sub[x].ep - m.sub[x].sp);
|
||||
js_pushnumber(J, s - source); /* arg x+2: offset within search string */
|
||||
js_copy(J, 0); /* arg x+3: search string */
|
||||
js_call(J, 2 + x);
|
||||
r = js_tostring(J, -1);
|
||||
js_putm(J, &sb, source, s);
|
||||
js_puts(J, &sb, r);
|
||||
js_pop(J, 1);
|
||||
} else {
|
||||
r = js_tostring(J, 2);
|
||||
js_putm(J, &sb, source, s);
|
||||
while (*r) {
|
||||
if (*r == '$') {
|
||||
switch (*(++r)) {
|
||||
case 0: --r; /* end of string; back up */
|
||||
/* fallthrough */
|
||||
case '$': js_putc(J, &sb, '$'); break;
|
||||
case '`': js_putm(J, &sb, source, s); break;
|
||||
case '\'': js_puts(J, &sb, s + n); break;
|
||||
case '&':
|
||||
js_putm(J, &sb, s, s + n);
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
x = *r - '0';
|
||||
if (r[1] >= '0' && r[1] <= '9')
|
||||
x = x * 10 + *(++r) - '0';
|
||||
if (x > 0 && x < m.nsub) {
|
||||
js_putm(J, &sb, m.sub[x].sp, m.sub[x].ep);
|
||||
} else {
|
||||
js_putc(J, &sb, '$');
|
||||
if (x > 10) {
|
||||
js_putc(J, &sb, '0' + x / 10);
|
||||
js_putc(J, &sb, '0' + x % 10);
|
||||
} else {
|
||||
js_putc(J, &sb, '0' + x);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
js_putc(J, &sb, '$');
|
||||
js_putc(J, &sb, *r);
|
||||
break;
|
||||
}
|
||||
++r;
|
||||
} else {
|
||||
js_putc(J, &sb, *r++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (re->flags & JS_REGEXP_G) {
|
||||
source = m.sub[0].ep;
|
||||
if (n == 0) {
|
||||
if (*source)
|
||||
js_putc(J, &sb, *source++);
|
||||
else
|
||||
goto end;
|
||||
}
|
||||
if (!js_doregexec(J, re->prog, source, &m, REG_NOTBOL))
|
||||
goto loop;
|
||||
}
|
||||
|
||||
end:
|
||||
js_puts(J, &sb, s + n);
|
||||
js_putc(J, &sb, 0);
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
js_pushstring(J, sb ? sb->s : "");
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
|
||||
static void Sp_replace_string(js_State *J)
|
||||
{
|
||||
const char *source, *needle, *s, *r;
|
||||
js_Buffer *sb = NULL;
|
||||
int n;
|
||||
|
||||
source = checkstring(J, 0);
|
||||
needle = js_tostring(J, 1);
|
||||
|
||||
s = strstr(source, needle);
|
||||
if (!s) {
|
||||
js_copy(J, 0);
|
||||
return;
|
||||
}
|
||||
n = strlen(needle);
|
||||
|
||||
if (js_iscallable(J, 2)) {
|
||||
js_copy(J, 2);
|
||||
js_pushundefined(J);
|
||||
js_pushlstring(J, s, n); /* arg 1: substring that matched */
|
||||
js_pushnumber(J, s - source); /* arg 2: offset within search string */
|
||||
js_copy(J, 0); /* arg 3: search string */
|
||||
js_call(J, 3);
|
||||
r = js_tostring(J, -1);
|
||||
js_putm(J, &sb, source, s);
|
||||
js_puts(J, &sb, r);
|
||||
js_puts(J, &sb, s + n);
|
||||
js_putc(J, &sb, 0);
|
||||
js_pop(J, 1);
|
||||
} else {
|
||||
r = js_tostring(J, 2);
|
||||
js_putm(J, &sb, source, s);
|
||||
while (*r) {
|
||||
if (*r == '$') {
|
||||
switch (*(++r)) {
|
||||
case 0: --r; /* end of string; back up */
|
||||
/* fallthrough */
|
||||
case '$': js_putc(J, &sb, '$'); break;
|
||||
case '&': js_putm(J, &sb, s, s + n); break;
|
||||
case '`': js_putm(J, &sb, source, s); break;
|
||||
case '\'': js_puts(J, &sb, s + n); break;
|
||||
default: js_putc(J, &sb, '$'); js_putc(J, &sb, *r); break;
|
||||
}
|
||||
++r;
|
||||
} else {
|
||||
js_putc(J, &sb, *r++);
|
||||
}
|
||||
}
|
||||
js_puts(J, &sb, s + n);
|
||||
js_putc(J, &sb, 0);
|
||||
}
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, sb);
|
||||
js_throw(J);
|
||||
}
|
||||
js_pushstring(J, sb ? sb->s : "");
|
||||
js_endtry(J);
|
||||
js_free(J, sb);
|
||||
}
|
||||
|
||||
static void Sp_replace(js_State *J)
|
||||
{
|
||||
if (js_isregexp(J, 1))
|
||||
Sp_replace_regexp(J);
|
||||
else
|
||||
Sp_replace_string(J);
|
||||
}
|
||||
|
||||
static void Sp_split_regexp(js_State *J)
|
||||
{
|
||||
js_Regexp *re;
|
||||
const char *text;
|
||||
int limit, len, k;
|
||||
const char *p, *a, *b, *c, *e;
|
||||
Resub m;
|
||||
|
||||
text = checkstring(J, 0);
|
||||
re = js_toregexp(J, 1);
|
||||
limit = js_isdefined(J, 2) ? js_tointeger(J, 2) : 1 << 30;
|
||||
|
||||
js_newarray(J);
|
||||
len = 0;
|
||||
|
||||
e = text + strlen(text);
|
||||
|
||||
/* splitting the empty string */
|
||||
if (e == text) {
|
||||
if (js_doregexec(J, re->prog, text, &m, 0)) {
|
||||
if (len == limit) return;
|
||||
js_pushliteral(J, "");
|
||||
js_setindex(J, -2, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
p = a = text;
|
||||
while (a < e) {
|
||||
if (js_doregexec(J, re->prog, a, &m, a > text ? REG_NOTBOL : 0))
|
||||
break; /* no match */
|
||||
|
||||
b = m.sub[0].sp;
|
||||
c = m.sub[0].ep;
|
||||
|
||||
/* empty string at end of last match */
|
||||
if (b == p) {
|
||||
++a;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == limit) return;
|
||||
js_pushlstring(J, p, b - p);
|
||||
js_setindex(J, -2, len++);
|
||||
|
||||
for (k = 1; k < m.nsub; ++k) {
|
||||
if (len == limit) return;
|
||||
js_pushlstring(J, m.sub[k].sp, m.sub[k].ep - m.sub[k].sp);
|
||||
js_setindex(J, -2, len++);
|
||||
}
|
||||
|
||||
a = p = c;
|
||||
}
|
||||
|
||||
if (len == limit) return;
|
||||
js_pushstring(J, p);
|
||||
js_setindex(J, -2, len);
|
||||
}
|
||||
|
||||
static void Sp_split_string(js_State *J)
|
||||
{
|
||||
const char *str = checkstring(J, 0);
|
||||
const char *sep = js_tostring(J, 1);
|
||||
int limit = js_isdefined(J, 2) ? js_tointeger(J, 2) : 1 << 30;
|
||||
int i, n;
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
n = strlen(sep);
|
||||
|
||||
/* empty string */
|
||||
if (n == 0) {
|
||||
Rune rune;
|
||||
for (i = 0; *str && i < limit; ++i) {
|
||||
n = chartorune(&rune, str);
|
||||
js_pushlstring(J, str, n);
|
||||
js_setindex(J, -2, i);
|
||||
str += n;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; str && i < limit; ++i) {
|
||||
const char *s = strstr(str, sep);
|
||||
if (s) {
|
||||
js_pushlstring(J, str, s-str);
|
||||
js_setindex(J, -2, i);
|
||||
str = s + n;
|
||||
} else {
|
||||
js_pushstring(J, str);
|
||||
js_setindex(J, -2, i);
|
||||
str = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Sp_split(js_State *J)
|
||||
{
|
||||
if (js_isundefined(J, 1)) {
|
||||
js_newarray(J);
|
||||
js_copy(J, 0);
|
||||
js_setindex(J, -2, 0);
|
||||
} else if (js_isregexp(J, 1)) {
|
||||
Sp_split_regexp(J);
|
||||
} else {
|
||||
Sp_split_string(J);
|
||||
}
|
||||
}
|
||||
|
||||
void jsB_initstring(js_State *J)
|
||||
{
|
||||
J->String_prototype->u.s.string = "";
|
||||
J->String_prototype->u.s.length = 0;
|
||||
|
||||
js_pushobject(J, J->String_prototype);
|
||||
{
|
||||
jsB_propf(J, "String.prototype.toString", Sp_toString, 0);
|
||||
jsB_propf(J, "String.prototype.valueOf", Sp_valueOf, 0);
|
||||
jsB_propf(J, "String.prototype.charAt", Sp_charAt, 1);
|
||||
jsB_propf(J, "String.prototype.charCodeAt", Sp_charCodeAt, 1);
|
||||
jsB_propf(J, "String.prototype.concat", Sp_concat, 0); /* 1 */
|
||||
jsB_propf(J, "String.prototype.indexOf", Sp_indexOf, 1);
|
||||
jsB_propf(J, "String.prototype.lastIndexOf", Sp_lastIndexOf, 1);
|
||||
jsB_propf(J, "String.prototype.localeCompare", Sp_localeCompare, 1);
|
||||
jsB_propf(J, "String.prototype.match", Sp_match, 1);
|
||||
jsB_propf(J, "String.prototype.replace", Sp_replace, 2);
|
||||
jsB_propf(J, "String.prototype.search", Sp_search, 1);
|
||||
jsB_propf(J, "String.prototype.slice", Sp_slice, 2);
|
||||
jsB_propf(J, "String.prototype.split", Sp_split, 2);
|
||||
jsB_propf(J, "String.prototype.substring", Sp_substring, 2);
|
||||
jsB_propf(J, "String.prototype.toLowerCase", Sp_toLowerCase, 0);
|
||||
jsB_propf(J, "String.prototype.toLocaleLowerCase", Sp_toLowerCase, 0);
|
||||
jsB_propf(J, "String.prototype.toUpperCase", Sp_toUpperCase, 0);
|
||||
jsB_propf(J, "String.prototype.toLocaleUpperCase", Sp_toUpperCase, 0);
|
||||
|
||||
/* ES5 */
|
||||
jsB_propf(J, "String.prototype.trim", Sp_trim, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_String, jsB_new_String, "String", 0); /* 1 */
|
||||
{
|
||||
jsB_propf(J, "String.fromCharCode", S_fromCharCode, 0); /* 1 */
|
||||
}
|
||||
js_defglobal(J, "String", JS_DONTENUM);
|
||||
}
|
@ -1,630 +0,0 @@
|
||||
#include "jsi.h"
|
||||
#include "jslex.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
#include "utf.h"
|
||||
|
||||
#define JSV_ISSTRING(v) (v->type==JS_TSHRSTR || v->type==JS_TMEMSTR || v->type==JS_TLITSTR)
|
||||
#define JSV_TOSTRING(v) (v->type==JS_TSHRSTR ? v->u.shrstr : v->type==JS_TLITSTR ? v->u.litstr : v->type==JS_TMEMSTR ? v->u.memstr->p : "")
|
||||
|
||||
int jsV_numbertointeger(double n)
|
||||
{
|
||||
if (n == 0) return 0;
|
||||
if (isnan(n)) return 0;
|
||||
n = (n < 0) ? -floor(-n) : floor(n);
|
||||
if (n < INT_MIN) return INT_MIN;
|
||||
if (n > INT_MAX) return INT_MAX;
|
||||
return (int)n;
|
||||
}
|
||||
|
||||
int jsV_numbertoint32(double n)
|
||||
{
|
||||
double two32 = 4294967296.0;
|
||||
double two31 = 2147483648.0;
|
||||
|
||||
if (!isfinite(n) || n == 0)
|
||||
return 0;
|
||||
|
||||
n = fmod(n, two32);
|
||||
n = n >= 0 ? floor(n) : ceil(n) + two32;
|
||||
if (n >= two31)
|
||||
return n - two32;
|
||||
else
|
||||
return n;
|
||||
}
|
||||
|
||||
unsigned int jsV_numbertouint32(double n)
|
||||
{
|
||||
return (unsigned int)jsV_numbertoint32(n);
|
||||
}
|
||||
|
||||
short jsV_numbertoint16(double n)
|
||||
{
|
||||
return jsV_numbertoint32(n);
|
||||
}
|
||||
|
||||
unsigned short jsV_numbertouint16(double n)
|
||||
{
|
||||
return jsV_numbertoint32(n);
|
||||
}
|
||||
|
||||
/* obj.toString() */
|
||||
static int jsV_toString(js_State *J, js_Object *obj)
|
||||
{
|
||||
js_pushobject(J, obj);
|
||||
js_getproperty(J, -1, "toString");
|
||||
if (js_iscallable(J, -1)) {
|
||||
js_rot2(J);
|
||||
js_call(J, 0);
|
||||
if (js_isprimitive(J, -1))
|
||||
return 1;
|
||||
js_pop(J, 1);
|
||||
return 0;
|
||||
}
|
||||
js_pop(J, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* obj.valueOf() */
|
||||
static int jsV_valueOf(js_State *J, js_Object *obj)
|
||||
{
|
||||
js_pushobject(J, obj);
|
||||
js_getproperty(J, -1, "valueOf");
|
||||
if (js_iscallable(J, -1)) {
|
||||
js_rot2(J);
|
||||
js_call(J, 0);
|
||||
if (js_isprimitive(J, -1))
|
||||
return 1;
|
||||
js_pop(J, 1);
|
||||
return 0;
|
||||
}
|
||||
js_pop(J, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ToPrimitive() on a value */
|
||||
void jsV_toprimitive(js_State *J, js_Value *v, int preferred)
|
||||
{
|
||||
js_Object *obj;
|
||||
|
||||
if (v->type != JS_TOBJECT)
|
||||
return;
|
||||
|
||||
obj = v->u.object;
|
||||
|
||||
if (preferred == JS_HNONE)
|
||||
preferred = obj->type == JS_CDATE ? JS_HSTRING : JS_HNUMBER;
|
||||
|
||||
if (preferred == JS_HSTRING) {
|
||||
if (jsV_toString(J, obj) || jsV_valueOf(J, obj)) {
|
||||
*v = *js_tovalue(J, -1);
|
||||
js_pop(J, 1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (jsV_valueOf(J, obj) || jsV_toString(J, obj)) {
|
||||
*v = *js_tovalue(J, -1);
|
||||
js_pop(J, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (J->strict)
|
||||
js_typeerror(J, "cannot convert object to primitive");
|
||||
|
||||
v->type = JS_TLITSTR;
|
||||
v->u.litstr = "[object]";
|
||||
return;
|
||||
}
|
||||
|
||||
/* ToBoolean() on a value */
|
||||
int jsV_toboolean(js_State *J, js_Value *v)
|
||||
{
|
||||
switch (v->type) {
|
||||
default:
|
||||
case JS_TSHRSTR: return v->u.shrstr[0] != 0;
|
||||
case JS_TUNDEFINED: return 0;
|
||||
case JS_TNULL: return 0;
|
||||
case JS_TBOOLEAN: return v->u.boolean;
|
||||
case JS_TNUMBER: return v->u.number != 0 && !isnan(v->u.number);
|
||||
case JS_TLITSTR: return v->u.litstr[0] != 0;
|
||||
case JS_TMEMSTR: return v->u.memstr->p[0] != 0;
|
||||
case JS_TOBJECT: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *js_itoa(char *out, int v)
|
||||
{
|
||||
char buf[32], *s = out;
|
||||
unsigned int a;
|
||||
int i = 0;
|
||||
if (v < 0) {
|
||||
a = -v;
|
||||
*s++ = '-';
|
||||
} else {
|
||||
a = v;
|
||||
}
|
||||
while (a) {
|
||||
buf[i++] = (a % 10) + '0';
|
||||
a /= 10;
|
||||
}
|
||||
if (i == 0)
|
||||
buf[i++] = '0';
|
||||
while (i > 0)
|
||||
*s++ = buf[--i];
|
||||
*s = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
double js_stringtofloat(const char *s, char **ep)
|
||||
{
|
||||
char *end;
|
||||
double n;
|
||||
const char *e = s;
|
||||
int isflt = 0;
|
||||
if (*e == '+' || *e == '-') ++e;
|
||||
while (*e >= '0' && *e <= '9') ++e;
|
||||
if (*e == '.') { ++e; isflt = 1; }
|
||||
while (*e >= '0' && *e <= '9') ++e;
|
||||
if (*e == 'e' || *e == 'E') {
|
||||
++e;
|
||||
if (*e == '+' || *e == '-') ++e;
|
||||
while (*e >= '0' && *e <= '9') ++e;
|
||||
isflt = 1;
|
||||
}
|
||||
if (isflt || e - s > 9)
|
||||
n = js_strtod(s, &end);
|
||||
else
|
||||
n = strtol(s, &end, 10);
|
||||
if (end == e) {
|
||||
*ep = (char*)e;
|
||||
return n;
|
||||
}
|
||||
*ep = (char*)s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ToNumber() on a string */
|
||||
double jsV_stringtonumber(js_State *J, const char *s)
|
||||
{
|
||||
char *e;
|
||||
double n;
|
||||
while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
|
||||
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && s[2] != 0)
|
||||
n = strtol(s + 2, &e, 16);
|
||||
else if (!strncmp(s, "Infinity", 8))
|
||||
n = INFINITY, e = (char*)s + 8;
|
||||
else if (!strncmp(s, "+Infinity", 9))
|
||||
n = INFINITY, e = (char*)s + 9;
|
||||
else if (!strncmp(s, "-Infinity", 9))
|
||||
n = -INFINITY, e = (char*)s + 9;
|
||||
else
|
||||
n = js_stringtofloat(s, &e);
|
||||
while (jsY_iswhite(*e) || jsY_isnewline(*e)) ++e;
|
||||
if (*e) return NAN;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* ToNumber() on a value */
|
||||
double jsV_tonumber(js_State *J, js_Value *v)
|
||||
{
|
||||
switch (v->type) {
|
||||
default:
|
||||
case JS_TSHRSTR: return jsV_stringtonumber(J, v->u.shrstr);
|
||||
case JS_TUNDEFINED: return NAN;
|
||||
case JS_TNULL: return 0;
|
||||
case JS_TBOOLEAN: return v->u.boolean;
|
||||
case JS_TNUMBER: return v->u.number;
|
||||
case JS_TLITSTR: return jsV_stringtonumber(J, v->u.litstr);
|
||||
case JS_TMEMSTR: return jsV_stringtonumber(J, v->u.memstr->p);
|
||||
case JS_TOBJECT:
|
||||
jsV_toprimitive(J, v, JS_HNUMBER);
|
||||
return jsV_tonumber(J, v);
|
||||
}
|
||||
}
|
||||
|
||||
double jsV_tointeger(js_State *J, js_Value *v)
|
||||
{
|
||||
return jsV_numbertointeger(jsV_tonumber(J, v));
|
||||
}
|
||||
|
||||
/* ToString() on a number */
|
||||
const char *jsV_numbertostring(js_State *J, char buf[32], double f)
|
||||
{
|
||||
char digits[32], *p = buf, *s = digits;
|
||||
int exp, ndigits, point;
|
||||
|
||||
if (f == 0) return "0";
|
||||
if (isnan(f)) return "NaN";
|
||||
if (isinf(f)) return f < 0 ? "-Infinity" : "Infinity";
|
||||
|
||||
/* Fast case for integers. This only works assuming all integers can be
|
||||
* exactly represented by a float. This is true for 32-bit integers and
|
||||
* 64-bit floats. */
|
||||
if (f >= INT_MIN && f <= INT_MAX) {
|
||||
int i = (int)f;
|
||||
if ((double)i == f)
|
||||
return js_itoa(buf, i);
|
||||
}
|
||||
|
||||
ndigits = js_grisu2(f, digits, &exp);
|
||||
point = ndigits + exp;
|
||||
|
||||
if (signbit(f))
|
||||
*p++ = '-';
|
||||
|
||||
if (point < -5 || point > 21) {
|
||||
*p++ = *s++;
|
||||
if (ndigits > 1) {
|
||||
int n = ndigits - 1;
|
||||
*p++ = '.';
|
||||
while (n--)
|
||||
*p++ = *s++;
|
||||
}
|
||||
js_fmtexp(p, point - 1);
|
||||
}
|
||||
|
||||
else if (point <= 0) {
|
||||
*p++ = '0';
|
||||
*p++ = '.';
|
||||
while (point++ < 0)
|
||||
*p++ = '0';
|
||||
while (ndigits-- > 0)
|
||||
*p++ = *s++;
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
else {
|
||||
while (ndigits-- > 0) {
|
||||
*p++ = *s++;
|
||||
if (--point == 0 && ndigits > 0)
|
||||
*p++ = '.';
|
||||
}
|
||||
while (point-- > 0)
|
||||
*p++ = '0';
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* ToString() on a value */
|
||||
const char *jsV_tostring(js_State *J, js_Value *v)
|
||||
{
|
||||
char buf[32];
|
||||
const char *p;
|
||||
switch (v->type) {
|
||||
default:
|
||||
case JS_TSHRSTR: return v->u.shrstr;
|
||||
case JS_TUNDEFINED: return "undefined";
|
||||
case JS_TNULL: return "null";
|
||||
case JS_TBOOLEAN: return v->u.boolean ? "true" : "false";
|
||||
case JS_TLITSTR: return v->u.litstr;
|
||||
case JS_TMEMSTR: return v->u.memstr->p;
|
||||
case JS_TNUMBER:
|
||||
p = jsV_numbertostring(J, buf, v->u.number);
|
||||
if (p == buf) {
|
||||
int n = strlen(p);
|
||||
if (n <= soffsetof(js_Value, type)) {
|
||||
char *s = v->u.shrstr;
|
||||
while (n--) *s++ = *p++;
|
||||
*s = 0;
|
||||
v->type = JS_TSHRSTR;
|
||||
return v->u.shrstr;
|
||||
} else {
|
||||
v->u.memstr = jsV_newmemstring(J, p, n);
|
||||
v->type = JS_TMEMSTR;
|
||||
return v->u.memstr->p;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
case JS_TOBJECT:
|
||||
jsV_toprimitive(J, v, JS_HSTRING);
|
||||
return jsV_tostring(J, v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Objects */
|
||||
|
||||
static js_Object *jsV_newboolean(js_State *J, int v)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CBOOLEAN, J->Boolean_prototype);
|
||||
obj->u.boolean = v;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static js_Object *jsV_newnumber(js_State *J, double v)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CNUMBER, J->Number_prototype);
|
||||
obj->u.number = v;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static js_Object *jsV_newstring(js_State *J, const char *v)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CSTRING, J->String_prototype);
|
||||
obj->u.s.string = js_intern(J, v); /* TODO: js_String */
|
||||
obj->u.s.length = utflen(v);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* ToObject() on a value */
|
||||
js_Object *jsV_toobject(js_State *J, js_Value *v)
|
||||
{
|
||||
switch (v->type) {
|
||||
default:
|
||||
case JS_TSHRSTR: return jsV_newstring(J, v->u.shrstr);
|
||||
case JS_TUNDEFINED: js_typeerror(J, "cannot convert undefined to object");
|
||||
case JS_TNULL: js_typeerror(J, "cannot convert null to object");
|
||||
case JS_TBOOLEAN: return jsV_newboolean(J, v->u.boolean);
|
||||
case JS_TNUMBER: return jsV_newnumber(J, v->u.number);
|
||||
case JS_TLITSTR: return jsV_newstring(J, v->u.litstr);
|
||||
case JS_TMEMSTR: return jsV_newstring(J, v->u.memstr->p);
|
||||
case JS_TOBJECT: return v->u.object;
|
||||
}
|
||||
}
|
||||
|
||||
void js_newobjectx(js_State *J)
|
||||
{
|
||||
js_Object *prototype = NULL;
|
||||
if (js_isobject(J, -1))
|
||||
prototype = js_toobject(J, -1);
|
||||
js_pop(J, 1);
|
||||
js_pushobject(J, jsV_newobject(J, JS_COBJECT, prototype));
|
||||
}
|
||||
|
||||
void js_newobject(js_State *J)
|
||||
{
|
||||
js_pushobject(J, jsV_newobject(J, JS_COBJECT, J->Object_prototype));
|
||||
}
|
||||
|
||||
void js_newarguments(js_State *J)
|
||||
{
|
||||
js_pushobject(J, jsV_newobject(J, JS_CARGUMENTS, J->Object_prototype));
|
||||
}
|
||||
|
||||
void js_newarray(js_State *J)
|
||||
{
|
||||
js_pushobject(J, jsV_newobject(J, JS_CARRAY, J->Array_prototype));
|
||||
}
|
||||
|
||||
void js_newboolean(js_State *J, int v)
|
||||
{
|
||||
js_pushobject(J, jsV_newboolean(J, v));
|
||||
}
|
||||
|
||||
void js_newnumber(js_State *J, double v)
|
||||
{
|
||||
js_pushobject(J, jsV_newnumber(J, v));
|
||||
}
|
||||
|
||||
void js_newstring(js_State *J, const char *v)
|
||||
{
|
||||
js_pushobject(J, jsV_newstring(J, v));
|
||||
}
|
||||
|
||||
void js_newfunction(js_State *J, js_Function *fun, js_Environment *scope)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CFUNCTION, J->Function_prototype);
|
||||
obj->u.f.function = fun;
|
||||
obj->u.f.scope = scope;
|
||||
js_pushobject(J, obj);
|
||||
{
|
||||
js_pushnumber(J, fun->numparams);
|
||||
js_defproperty(J, -2, "length", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
js_newobject(J);
|
||||
{
|
||||
js_copy(J, -2);
|
||||
js_defproperty(J, -2, "constructor", JS_DONTENUM);
|
||||
}
|
||||
js_defproperty(J, -2, "prototype", JS_DONTENUM | JS_DONTCONF);
|
||||
}
|
||||
}
|
||||
|
||||
void js_newscript(js_State *J, js_Function *fun, js_Environment *scope, int type)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, type, NULL);
|
||||
obj->u.f.function = fun;
|
||||
obj->u.f.scope = scope;
|
||||
js_pushobject(J, obj);
|
||||
}
|
||||
|
||||
void js_newcfunction(js_State *J, js_CFunction cfun, const char *name, int length)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CCFUNCTION, J->Function_prototype);
|
||||
obj->u.c.name = name;
|
||||
obj->u.c.function = cfun;
|
||||
obj->u.c.constructor = NULL;
|
||||
obj->u.c.length = length;
|
||||
js_pushobject(J, obj);
|
||||
{
|
||||
js_pushnumber(J, length);
|
||||
js_defproperty(J, -2, "length", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
js_newobject(J);
|
||||
{
|
||||
js_copy(J, -2);
|
||||
js_defproperty(J, -2, "constructor", JS_DONTENUM);
|
||||
}
|
||||
js_defproperty(J, -2, "prototype", JS_DONTENUM | JS_DONTCONF);
|
||||
}
|
||||
}
|
||||
|
||||
/* prototype -- constructor */
|
||||
void js_newcconstructor(js_State *J, js_CFunction cfun, js_CFunction ccon, const char *name, int length)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CCFUNCTION, J->Function_prototype);
|
||||
obj->u.c.name = name;
|
||||
obj->u.c.function = cfun;
|
||||
obj->u.c.constructor = ccon;
|
||||
obj->u.c.length = length;
|
||||
js_pushobject(J, obj); /* proto obj */
|
||||
{
|
||||
js_pushnumber(J, length);
|
||||
js_defproperty(J, -2, "length", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
||||
js_rot2(J); /* obj proto */
|
||||
js_copy(J, -2); /* obj proto obj */
|
||||
js_defproperty(J, -2, "constructor", JS_DONTENUM);
|
||||
js_defproperty(J, -2, "prototype", JS_DONTENUM | JS_DONTCONF);
|
||||
}
|
||||
}
|
||||
|
||||
void js_newuserdatax(js_State *J, const char *tag, void *data, js_HasProperty has, js_Put put, js_Delete delete, js_Finalize finalize)
|
||||
{
|
||||
js_Object *prototype = NULL;
|
||||
js_Object *obj;
|
||||
|
||||
if (js_isobject(J, -1))
|
||||
prototype = js_toobject(J, -1);
|
||||
js_pop(J, 1);
|
||||
|
||||
obj = jsV_newobject(J, JS_CUSERDATA, prototype);
|
||||
obj->u.user.tag = tag;
|
||||
obj->u.user.data = data;
|
||||
obj->u.user.has = has;
|
||||
obj->u.user.put = put;
|
||||
obj->u.user.delete = delete;
|
||||
obj->u.user.finalize = finalize;
|
||||
js_pushobject(J, obj);
|
||||
}
|
||||
|
||||
void js_newuserdata(js_State *J, const char *tag, void *data, js_Finalize finalize)
|
||||
{
|
||||
js_newuserdatax(J, tag, data, NULL, NULL, NULL, finalize);
|
||||
}
|
||||
|
||||
/* Non-trivial operations on values. These are implemented using the stack. */
|
||||
|
||||
int js_instanceof(js_State *J)
|
||||
{
|
||||
js_Object *O, *V;
|
||||
|
||||
if (!js_iscallable(J, -1))
|
||||
js_typeerror(J, "instanceof: invalid operand");
|
||||
|
||||
if (!js_isobject(J, -2))
|
||||
return 0;
|
||||
|
||||
js_getproperty(J, -1, "prototype");
|
||||
if (!js_isobject(J, -1))
|
||||
js_typeerror(J, "instanceof: 'prototype' property is not an object");
|
||||
O = js_toobject(J, -1);
|
||||
js_pop(J, 1);
|
||||
|
||||
V = js_toobject(J, -2);
|
||||
while (V) {
|
||||
V = V->prototype;
|
||||
if (O == V)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void js_concat(js_State *J)
|
||||
{
|
||||
js_toprimitive(J, -2, JS_HNONE);
|
||||
js_toprimitive(J, -1, JS_HNONE);
|
||||
|
||||
if (js_isstring(J, -2) || js_isstring(J, -1)) {
|
||||
const char *sa = js_tostring(J, -2);
|
||||
const char *sb = js_tostring(J, -1);
|
||||
/* TODO: create js_String directly */
|
||||
char *sab = js_malloc(J, strlen(sa) + strlen(sb) + 1);
|
||||
strcpy(sab, sa);
|
||||
strcat(sab, sb);
|
||||
if (js_try(J)) {
|
||||
js_free(J, sab);
|
||||
js_throw(J);
|
||||
}
|
||||
js_pop(J, 2);
|
||||
js_pushstring(J, sab);
|
||||
js_endtry(J);
|
||||
js_free(J, sab);
|
||||
} else {
|
||||
double x = js_tonumber(J, -2);
|
||||
double y = js_tonumber(J, -1);
|
||||
js_pop(J, 2);
|
||||
js_pushnumber(J, x + y);
|
||||
}
|
||||
}
|
||||
|
||||
int js_compare(js_State *J, int *okay)
|
||||
{
|
||||
js_toprimitive(J, -2, JS_HNUMBER);
|
||||
js_toprimitive(J, -1, JS_HNUMBER);
|
||||
|
||||
*okay = 1;
|
||||
if (js_isstring(J, -2) && js_isstring(J, -1)) {
|
||||
return strcmp(js_tostring(J, -2), js_tostring(J, -1));
|
||||
} else {
|
||||
double x = js_tonumber(J, -2);
|
||||
double y = js_tonumber(J, -1);
|
||||
if (isnan(x) || isnan(y))
|
||||
*okay = 0;
|
||||
return x < y ? -1 : x > y ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
int js_equal(js_State *J)
|
||||
{
|
||||
js_Value *x = js_tovalue(J, -2);
|
||||
js_Value *y = js_tovalue(J, -1);
|
||||
|
||||
retry:
|
||||
if (JSV_ISSTRING(x) && JSV_ISSTRING(y))
|
||||
return !strcmp(JSV_TOSTRING(x), JSV_TOSTRING(y));
|
||||
if (x->type == y->type) {
|
||||
if (x->type == JS_TUNDEFINED) return 1;
|
||||
if (x->type == JS_TNULL) return 1;
|
||||
if (x->type == JS_TNUMBER) return x->u.number == y->u.number;
|
||||
if (x->type == JS_TBOOLEAN) return x->u.boolean == y->u.boolean;
|
||||
if (x->type == JS_TOBJECT) return x->u.object == y->u.object;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x->type == JS_TNULL && y->type == JS_TUNDEFINED) return 1;
|
||||
if (x->type == JS_TUNDEFINED && y->type == JS_TNULL) return 1;
|
||||
|
||||
if (x->type == JS_TNUMBER && JSV_ISSTRING(y))
|
||||
return x->u.number == jsV_tonumber(J, y);
|
||||
if (JSV_ISSTRING(x) && y->type == JS_TNUMBER)
|
||||
return jsV_tonumber(J, x) == y->u.number;
|
||||
|
||||
if (x->type == JS_TBOOLEAN) {
|
||||
x->type = JS_TNUMBER;
|
||||
x->u.number = x->u.boolean ? 1 : 0;
|
||||
goto retry;
|
||||
}
|
||||
if (y->type == JS_TBOOLEAN) {
|
||||
y->type = JS_TNUMBER;
|
||||
y->u.number = y->u.boolean ? 1 : 0;
|
||||
goto retry;
|
||||
}
|
||||
if ((JSV_ISSTRING(x) || x->type == JS_TNUMBER) && y->type == JS_TOBJECT) {
|
||||
jsV_toprimitive(J, y, JS_HNONE);
|
||||
goto retry;
|
||||
}
|
||||
if (x->type == JS_TOBJECT && (JSV_ISSTRING(y) || y->type == JS_TNUMBER)) {
|
||||
jsV_toprimitive(J, x, JS_HNONE);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int js_strictequal(js_State *J)
|
||||
{
|
||||
js_Value *x = js_tovalue(J, -2);
|
||||
js_Value *y = js_tovalue(J, -1);
|
||||
|
||||
if (JSV_ISSTRING(x) && JSV_ISSTRING(y))
|
||||
return !strcmp(JSV_TOSTRING(x), JSV_TOSTRING(y));
|
||||
|
||||
if (x->type != y->type) return 0;
|
||||
if (x->type == JS_TUNDEFINED) return 1;
|
||||
if (x->type == JS_TNULL) return 1;
|
||||
if (x->type == JS_TNUMBER) return x->u.number == y->u.number;
|
||||
if (x->type == JS_TBOOLEAN) return x->u.boolean == y->u.boolean;
|
||||
if (x->type == JS_TOBJECT) return x->u.object == y->u.object;
|
||||
return 0;
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
#ifndef js_value_h
|
||||
#define js_value_h
|
||||
|
||||
typedef struct js_Property js_Property;
|
||||
typedef struct js_Iterator js_Iterator;
|
||||
|
||||
/* Hint to ToPrimitive() */
|
||||
enum {
|
||||
JS_HNONE,
|
||||
JS_HNUMBER,
|
||||
JS_HSTRING
|
||||
};
|
||||
|
||||
enum js_Type {
|
||||
JS_TSHRSTR, /* type tag doubles as string zero-terminator */
|
||||
JS_TUNDEFINED,
|
||||
JS_TNULL,
|
||||
JS_TBOOLEAN,
|
||||
JS_TNUMBER,
|
||||
JS_TLITSTR,
|
||||
JS_TMEMSTR,
|
||||
JS_TOBJECT,
|
||||
};
|
||||
|
||||
enum js_Class {
|
||||
JS_COBJECT,
|
||||
JS_CARRAY,
|
||||
JS_CFUNCTION,
|
||||
JS_CSCRIPT, /* function created from global code */
|
||||
JS_CEVAL, /* function created from eval code */
|
||||
JS_CCFUNCTION, /* built-in function */
|
||||
JS_CERROR,
|
||||
JS_CBOOLEAN,
|
||||
JS_CNUMBER,
|
||||
JS_CSTRING,
|
||||
JS_CREGEXP,
|
||||
JS_CDATE,
|
||||
JS_CMATH,
|
||||
JS_CJSON,
|
||||
JS_CARGUMENTS,
|
||||
JS_CITERATOR,
|
||||
JS_CUSERDATA,
|
||||
};
|
||||
|
||||
/*
|
||||
Short strings abuse the js_Value struct. By putting the type tag in the
|
||||
last byte, and using 0 as the tag for short strings, we can use the
|
||||
entire js_Value as string storage by letting the type tag serve double
|
||||
purpose as the string zero terminator.
|
||||
*/
|
||||
|
||||
struct js_Value
|
||||
{
|
||||
union {
|
||||
int boolean;
|
||||
double number;
|
||||
char shrstr[8];
|
||||
const char *litstr;
|
||||
js_String *memstr;
|
||||
js_Object *object;
|
||||
} u;
|
||||
char pad[7]; /* extra storage for shrstr */
|
||||
char type; /* type tag and zero terminator for shrstr */
|
||||
};
|
||||
|
||||
struct js_String
|
||||
{
|
||||
js_String *gcnext;
|
||||
char gcmark;
|
||||
char p[1];
|
||||
};
|
||||
|
||||
struct js_Regexp
|
||||
{
|
||||
void *prog;
|
||||
char *source;
|
||||
unsigned short flags;
|
||||
unsigned short last;
|
||||
};
|
||||
|
||||
struct js_Object
|
||||
{
|
||||
enum js_Class type;
|
||||
int extensible;
|
||||
js_Property *properties;
|
||||
int count; /* number of properties, for array sparseness check */
|
||||
js_Object *prototype;
|
||||
union {
|
||||
int boolean;
|
||||
double number;
|
||||
struct {
|
||||
const char *string;
|
||||
int length;
|
||||
} s;
|
||||
struct {
|
||||
int length;
|
||||
} a;
|
||||
struct {
|
||||
js_Function *function;
|
||||
js_Environment *scope;
|
||||
} f;
|
||||
struct {
|
||||
const char *name;
|
||||
js_CFunction function;
|
||||
js_CFunction constructor;
|
||||
int length;
|
||||
} c;
|
||||
js_Regexp r;
|
||||
struct {
|
||||
js_Object *target;
|
||||
js_Iterator *head;
|
||||
} iter;
|
||||
struct {
|
||||
const char *tag;
|
||||
void *data;
|
||||
js_HasProperty has;
|
||||
js_Put put;
|
||||
js_Delete delete;
|
||||
js_Finalize finalize;
|
||||
} user;
|
||||
} u;
|
||||
js_Object *gcnext; /* allocation list */
|
||||
js_Object *gcroot; /* scan list */
|
||||
int gcmark;
|
||||
};
|
||||
|
||||
struct js_Property
|
||||
{
|
||||
const char *name;
|
||||
js_Property *left, *right;
|
||||
int level;
|
||||
int atts;
|
||||
js_Value value;
|
||||
js_Object *getter;
|
||||
js_Object *setter;
|
||||
};
|
||||
|
||||
struct js_Iterator
|
||||
{
|
||||
const char *name;
|
||||
js_Iterator *next;
|
||||
};
|
||||
|
||||
/* jsrun.c */
|
||||
js_String *jsV_newmemstring(js_State *J, const char *s, int n);
|
||||
js_Value *js_tovalue(js_State *J, int idx);
|
||||
void js_toprimitive(js_State *J, int idx, int hint);
|
||||
js_Object *js_toobject(js_State *J, int idx);
|
||||
void js_pushvalue(js_State *J, js_Value v);
|
||||
void js_pushobject(js_State *J, js_Object *v);
|
||||
|
||||
/* jsvalue.c */
|
||||
int jsV_toboolean(js_State *J, js_Value *v);
|
||||
double jsV_tonumber(js_State *J, js_Value *v);
|
||||
double jsV_tointeger(js_State *J, js_Value *v);
|
||||
const char *jsV_tostring(js_State *J, js_Value *v);
|
||||
js_Object *jsV_toobject(js_State *J, js_Value *v);
|
||||
void jsV_toprimitive(js_State *J, js_Value *v, int preferred);
|
||||
|
||||
const char *js_itoa(char buf[32], int a);
|
||||
double js_stringtofloat(const char *s, char **ep);
|
||||
int jsV_numbertointeger(double n);
|
||||
int jsV_numbertoint32(double n);
|
||||
unsigned int jsV_numbertouint32(double n);
|
||||
short jsV_numbertoint16(double n);
|
||||
unsigned short jsV_numbertouint16(double n);
|
||||
const char *jsV_numbertostring(js_State *J, char buf[32], double number);
|
||||
double jsV_stringtonumber(js_State *J, const char *string);
|
||||
|
||||
/* jsproperty.c */
|
||||
js_Object *jsV_newobject(js_State *J, enum js_Class type, js_Object *prototype);
|
||||
js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name);
|
||||
js_Property *jsV_getpropertyx(js_State *J, js_Object *obj, const char *name, int *own);
|
||||
js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name);
|
||||
js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name);
|
||||
js_Property *jsV_nextproperty(js_State *J, js_Object *obj, const char *name);
|
||||
void jsV_delproperty(js_State *J, js_Object *obj, const char *name);
|
||||
|
||||
js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own);
|
||||
const char *jsV_nextiterator(js_State *J, js_Object *iter);
|
||||
|
||||
void jsV_resizearray(js_State *J, js_Object *obj, int newlen);
|
||||
|
||||
/* jsdump.c */
|
||||
void js_dumpobject(js_State *J, js_Object *obj);
|
||||
void js_dumpvalue(js_State *J, js_Value v);
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user