Compare commits

...
18 Commits
Author SHA1 Message Date
hyung-hwan c89df44d20 added sys::tempname() 2026-09-14 15:57:54 +09:00
hyung-hwan a7dff29ad9 adjusted t-011.c for haikuos 2026-09-14 07:37:09 +09:00
hyung-hwan 16ce1fd923 updated h-027.hawk to cater for 32-bit systems 2026-09-13 23:27:39 +09:00
hyung-hwan 5a9958229e updated the probe for haiku's get_thread_info 2026-09-13 23:12:26 +09:00
hyung-hwan e90130abf5 implemented native cstack checker to prevent stack overflow - 100% accuracty not guaranteed yet 2026-09-13 22:46:29 +09:00
hyung-hwan ef9d88359d added two more test files 2026-09-12 12:07:06 +09:00
hyung-hwan aebeb66a57 removed the dispatch table for binops and switched to use the plain "switch .. case" statements 2026-09-12 11:26:08 +09:00
hyung-hwan 8593335d89 added a new test 2026-09-11 22:50:02 +09:00
hyung-hwan 1f42676e6e updated hawk_rtx_makeintval_inline macro to fallback to hawk_rtx_makeintval function if inline isn't available 2026-09-03 01:06:57 +09:00
hyung-hwan d8a3cbcad5 fixed the wrong parameter usage to macros that have side-effects 2026-09-03 00:23:19 +09:00
hyung-hwan a0b6e3b12b updated hawk_rtx_refupval_inline()/hawk_rtx_refdownval_inline() macros to use temporary variables for the compilers that don't support inline
the caller-side also assigns the value to a temporary variable before passing it to the above macros for safety
2026-09-02 21:23:19 +09:00
hyung-hwan ac5c9fecea minor naming update in pkgs/hawk.spec.in 2026-08-26 10:24:05 +09:00
hyung-hwan ae34dfdb71 fixed a inverted condition check bug in lib/idmap-imp.h 2026-08-25 23:46:46 +09:00
hyung-hwan 9e5afd66a1 updated the build files to cater for go files 2026-08-25 20:08:33 +09:00
hyung-hwan 0834275306 updated hawk.go with wrapper in dealing with hawk_val_t* since type casting using unsafe.Pointer didn't resolve the problem in full 2026-08-23 00:56:51 +09:00
hyung-hwan dce517bb2f enforcing runtime expression evaluation depth 2026-08-21 18:36:50 +09:00
hyung-hwan e2d648fbba updated further to exclude tagged pointers from the go memory 2026-08-20 16:08:19 +09:00
hyung-hwan ef1c667ec9 converted the raw c pointer of hawk_val_t* to uintptr(as CPtrVal) since hawk_val_t* contains a tagged pointer for immediate values. go runtime fails the pointer check during GC 2026-08-20 14:09:15 +09:00
42 changed files with 2877 additions and 524 deletions
+4 -1
View File
@@ -1,7 +1,10 @@
AUTOMAKE_OPTION = foreign
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = go.mod
gosrcdir = $(datadir)/hawk/go
gosrc_DATA = go.mod hawk.go hawk-inst.go
EXTRA_DIST = $(gosrc_DATA) hawk_test.go
SUBDIRS =
+67 -11
View File
@@ -13,6 +13,7 @@
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
@@ -137,6 +138,34 @@ am__can_run_installinfo = \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
{ test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
am__installdirs = "$(DESTDIR)$(gosrcdir)"
DATA = $(gosrc_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
@@ -377,7 +406,9 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTION = foreign
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = go.mod
gosrcdir = $(datadir)/hawk/go
gosrc_DATA = go.mod hawk.go hawk-inst.go
EXTRA_DIST = $(gosrc_DATA) hawk_test.go
SUBDIRS = tools lib mod bin samples t
#if ENABLE_STATIC_MODULE
#SUBDIRS += tools mod lib bin samples t
@@ -438,6 +469,27 @@ clean-libtool:
distclean-libtool:
-rm -f libtool config.lt
install-gosrcDATA: $(gosrc_DATA)
@$(NORMAL_INSTALL)
@list='$(gosrc_DATA)'; test -n "$(gosrcdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(gosrcdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(gosrcdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gosrcdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(gosrcdir)" || exit $$?; \
done
uninstall-gosrcDATA:
@$(NORMAL_UNINSTALL)
@list='$(gosrc_DATA)'; test -n "$(gosrcdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(gosrcdir)'; $(am__uninstall_files_from_dir)
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
@@ -750,9 +802,12 @@ distcleancheck: distclean
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile
all-am: Makefile $(DATA)
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(gosrcdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
@@ -805,7 +860,7 @@ info: info-recursive
info-am:
install-data-am:
install-data-am: install-gosrcDATA
install-dvi: install-dvi-recursive
@@ -851,7 +906,7 @@ ps: ps-recursive
ps-am:
uninstall-am:
uninstall-am: uninstall-gosrcDATA
.MAKE: $(am__recursive_targets) install-am install-strip
@@ -864,13 +919,14 @@ uninstall-am:
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs installdirs-am \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
install-exec install-exec-am install-gosrcDATA install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags tags-am uninstall uninstall-am \
uninstall-gosrcDATA
.PRECIOUS: Makefile
+23
View File
@@ -782,6 +782,22 @@ BEGIN { print length("hawk"), substr("hawk", 2, 2) }
| stack_limit | global | number | 5120 | specify the runtime stack size measured in the number of values |
| xcall | file | on, off | off | allow one-level function call after dot or bracket index access (e.g. `m.f(...)`, `m["f"](...)`) |
`stack_limit` sizes the heap-based value stack; it does not size the native C
stack. When the required stack-bound APIs are detected on Linux, macOS, FreeBSD,
NetBSD, OpenBSD, Haiku, or Windows, the runtime also checks native stack bounds
automatically, independently of this pragma and the logical recursion limit.
It leaves 64 KiB of headroom and returns `HAWK_ESTACK` (`native C stack
limit reached`) before recursive evaluation exhausts that space. Bounds are
refreshed at host execution entry, including callback reentry and sequential use
of a runtime context on different threads. Failure to obtain valid bounds after
the feature has been enabled is a runtime error.
These checks protect recursive runtime evaluation, not parsing or arbitrary
stack use inside native extensions, host callbacks, or library routines. Hosts
must enter Hawk with sufficient stack space for entry and error handling and
must not change the active stack limits during execution. Builds without the
required interfaces retain the value-stack and logical recursion limits.
### @pragma entry
Sets a custom entry function instead of the default `BEGIN`/pattern/`END` flow.
@@ -1165,10 +1181,17 @@ The `sys` module provides various functions concerning the underlying operation
- sys::sleep
- sys::strftime
- sys::system
- sys::tempname
- sys::unlink
- sys::wait
- sys::write
`sys::tempname([prefix])` atomically creates an empty file in the system
temporary directory, closes it, and returns its full path. It returns an empty
string on failure; call `sys::errmsg()` for the error text. The optional prefix
must not contain a path separator. Remove the file with `sys::unlink()` when it
is no longer needed.
#### Signals
Use these to register handlers and raise signals from Hawk.
+13 -5
View File
@@ -82,11 +82,19 @@ hawkgo_SOURCES = \
hawkgo_LINK =
if ENABLE_STATIC
CGO_CFLAGS_ADD="-static"
CGO_LDFLAGS_ADD="-static"
CGO_CFLAGS_ADD=-static
CGO_LDFLAGS_ADD=-static
else
CGO_CFLAGS_ADD=""
CGO_LDFLAGS_ADD=""
CGO_CFLAGS_ADD=
CGO_LDFLAGS_ADD=
endif
if ENABLE_DEBUG
##GO_BUILD_OPTS=-msan -asan -x
##GO_BUILD_OPTS=-race -gcflags="-m=3" -x
GO_BUILD_OPTS=-race -gcflags="-m"
else
GO_BUILD_OPTS=
endif
hawkgo$(EXEEXT): ../lib/libhawk.la $(hawkgo_OBJECTS)
@@ -97,7 +105,7 @@ hawkgo$(EXEEXT): ../lib/libhawk.la $(hawkgo_OBJECTS)
CC=$(CC) \
CGO_CFLAGS="-I$(abs_top_srcdir)/lib -I$(abs_top_builddir)/lib $(CFLAGS) $(CGO_CFLAGS_EXTRA) $(CGO_CFLAGS_ADD)" \
CGO_LDFLAGS="-L$(abs_top_builddir)/lib -L$(abs_top_builddir)/lib/.libs -lhawk -ldl $(LIBM) $(CGO_LDFLAGS_EXTRA) $(CGO_LDFLAGS_ADD)" \
go build -C $(srcdir) -ldflags "-X 'main.BINDIR=$(bindir)' -X 'main.SBINDIR=$(sbindir)' -X 'main.LIBDIR=$(libdir)' -X 'main.SYSCONFDIR=$(sysconfdir)'" -x -o $(abs_builddir)/$@ -modfile $(abs_top_srcdir)/go.mod $(abs_srcdir)/hawkgo.go $(abs_srcdir)/getopt.go
go build -C $(srcdir) -ldflags "-X 'main.BINDIR=$(bindir)' -X 'main.SBINDIR=$(sbindir)' -X 'main.LIBDIR=$(libdir)' -X 'main.SYSCONFDIR=$(sysconfdir)'" $(GO_BUILD_OPTS) -o $(abs_builddir)/$@ -modfile $(abs_top_srcdir)/go.mod $(abs_srcdir)/hawkgo.go $(abs_srcdir)/getopt.go
## ---------------------------------------------------------------
go clean -C $(srcdir) -x -modfile $(abs_top_srcdir)/go.mod
+7 -5
View File
@@ -415,10 +415,12 @@ hawk_DEPENDENCIES = $(srcdir)/hawk.pot $(srcdir)/hawk-ko.po $(srcdir)/hawk-zh_CN
@ENABLE_HAWKGO_TRUE@ hawkgo.go
@ENABLE_HAWKGO_TRUE@hawkgo_LINK =
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_FALSE@CGO_CFLAGS_ADD = ""
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_TRUE@CGO_CFLAGS_ADD = "-static"
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_FALSE@CGO_LDFLAGS_ADD = ""
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_TRUE@CGO_LDFLAGS_ADD = "-static"
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_FALSE@CGO_CFLAGS_ADD =
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_TRUE@CGO_CFLAGS_ADD = -static
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_FALSE@CGO_LDFLAGS_ADD =
@ENABLE_HAWKGO_TRUE@@ENABLE_STATIC_TRUE@CGO_LDFLAGS_ADD = -static
@ENABLE_DEBUG_FALSE@@ENABLE_HAWKGO_TRUE@GO_BUILD_OPTS =
@ENABLE_DEBUG_TRUE@@ENABLE_HAWKGO_TRUE@GO_BUILD_OPTS = -race -gcflags="-m"
all: all-am
.SUFFIXES:
@@ -874,7 +876,7 @@ $(srcdir)/hawk-zh_CN.po: $(srcdir)/hawk.pot
@ENABLE_HAWKGO_TRUE@ CC=$(CC) \
@ENABLE_HAWKGO_TRUE@ CGO_CFLAGS="-I$(abs_top_srcdir)/lib -I$(abs_top_builddir)/lib $(CFLAGS) $(CGO_CFLAGS_EXTRA) $(CGO_CFLAGS_ADD)" \
@ENABLE_HAWKGO_TRUE@ CGO_LDFLAGS="-L$(abs_top_builddir)/lib -L$(abs_top_builddir)/lib/.libs -lhawk -ldl $(LIBM) $(CGO_LDFLAGS_EXTRA) $(CGO_LDFLAGS_ADD)" \
@ENABLE_HAWKGO_TRUE@ go build -C $(srcdir) -ldflags "-X 'main.BINDIR=$(bindir)' -X 'main.SBINDIR=$(sbindir)' -X 'main.LIBDIR=$(libdir)' -X 'main.SYSCONFDIR=$(sysconfdir)'" -x -o $(abs_builddir)/$@ -modfile $(abs_top_srcdir)/go.mod $(abs_srcdir)/hawkgo.go $(abs_srcdir)/getopt.go
@ENABLE_HAWKGO_TRUE@ go build -C $(srcdir) -ldflags "-X 'main.BINDIR=$(bindir)' -X 'main.SBINDIR=$(sbindir)' -X 'main.LIBDIR=$(libdir)' -X 'main.SYSCONFDIR=$(sysconfdir)'" $(GO_BUILD_OPTS) -o $(abs_builddir)/$@ -modfile $(abs_top_srcdir)/go.mod $(abs_srcdir)/hawkgo.go $(abs_srcdir)/getopt.go
@ENABLE_HAWKGO_TRUE@ go clean -C $(srcdir) -x -modfile $(abs_top_srcdir)/go.mod
@ENABLE_HAWKGO_TRUE@.go.o:
+7 -3
View File
@@ -919,9 +919,13 @@ int main_hawk(int argc, hawk_bch_t* argv[], const hawk_bch_t* real_argv0)
tmp = 50;
hawk_setopt(hawk, HAWK_OPT_DEPTH_BLOCK_PARSE, &tmp);
hawk_setopt(hawk, HAWK_OPT_DEPTH_EXPR_PARSE, &tmp);
tmp = 1000;
hawk_setopt(hawk, HAWK_OPT_DEPTH_BLOCK_RUN, &tmp);
hawk_setopt(hawk, HAWK_OPT_DEPTH_EXPR_RUN, &tmp);
/* [NOTE]
* if the native cstack info is available,
* HAWK_OPT_DEPTH_RECURS_RUN is ignored */
tmp = 1200;
hawk_setopt(hawk, HAWK_OPT_DEPTH_RECURS_RUN, &tmp);
tmp = 64;
hawk_setopt(hawk, HAWK_OPT_DEPTH_INCLUDE, &tmp);
}
+6
View File
@@ -349,8 +349,14 @@ func run_script(h *hawk.Hawk, fs_idx int, data_idx int, cfg *Config, rtx_chan ch
if cfg.show_extra_info {
dprint_return(rtx, retv)
}
// if i don't call retv.Close(), it won't be reclaimed until
// rtx.Close() is called regardless of GC invocation.
retv.Close()
retv = nil
}
// let's not care about closing args or return values
// because rtx.Close() will close them automatically
if rtx != nil {
Vendored
+111 -79
View File
@@ -705,6 +705,8 @@ ENABLE_LIBLTDL_FALSE
ENABLE_LIBLTDL_TRUE
ENABLE_CXX_FALSE
ENABLE_CXX_TRUE
ENABLE_DEBUG_FALSE
ENABLE_DEBUG_TRUE
BUILD_MODE
PACKAGE_VERSION_PATCH
PACKAGE_VERSION_MINOR
@@ -21485,6 +21487,7 @@ printf "%s\n" "#define HAWK_ENABLE_WIDE_CHAR 1" >>confdefs.h
CFLAGS="$CFLAGS -fno-short-wchar"
CXXFLAGS="$CXXFLAGS -fno-short-wchar"
fi
if test "${enable_wide_char}" != "yes:4"
then
@@ -24360,111 +24363,128 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
## check other pthread functions
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_timedlock in -lpthread" >&5
printf %s "checking for pthread_mutex_timedlock in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread_pthread_mutex_timedlock+y}
## Check the non-portable pthread interfaces used to obtain the active
## thread's native stack bounds. AX_PTHREAD keeps its flags separate until
## near the end of this script, so apply them temporarily for these checks.
hawk_saved_CFLAGS="$CFLAGS"
hawk_saved_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$LIBS $PTHREAD_LIBS"
ac_fn_c_check_func "$LINENO" "pthread_getattr_np" "ac_cv_func_pthread_getattr_np"
if test "x$ac_cv_func_pthread_getattr_np" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_GETATTR_NP 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_attr_get_np" "ac_cv_func_pthread_attr_get_np"
if test "x$ac_cv_func_pthread_attr_get_np" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_ATTR_GET_NP 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_attr_getstack" "ac_cv_func_pthread_attr_getstack"
if test "x$ac_cv_func_pthread_attr_getstack" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_ATTR_GETSTACK 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_attr_getguardsize" "ac_cv_func_pthread_attr_getguardsize"
if test "x$ac_cv_func_pthread_attr_getguardsize" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_ATTR_GETGUARDSIZE 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_get_stackaddr_np" "ac_cv_func_pthread_get_stackaddr_np"
if test "x$ac_cv_func_pthread_get_stackaddr_np" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_GET_STACKADDR_NP 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_get_stacksize_np" "ac_cv_func_pthread_get_stacksize_np"
if test "x$ac_cv_func_pthread_get_stacksize_np" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_GET_STACKSIZE_NP 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_stackseg_np" "ac_cv_func_pthread_stackseg_np"
if test "x$ac_cv_func_pthread_stackseg_np" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_STACKSEG_NP 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_mutex_timedlock" "ac_cv_func_pthread_mutex_timedlock"
if test "x$ac_cv_func_pthread_mutex_timedlock" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_MUTEX_TIMEDLOCK 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "pthread_mutex_trylock" "ac_cv_func_pthread_mutex_trylock"
if test "x$ac_cv_func_pthread_mutex_trylock" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_MUTEX_TRYLOCK 1" >>confdefs.h
fi
CFLAGS="$hawk_saved_CFLAGS"
LIBS="$hawk_saved_LIBS"
## Haiku uses Kernel Kit functions instead of pthread stack-bound functions.
ac_fn_c_check_func "$LINENO" "find_thread" "ac_cv_func_find_thread"
if test "x$ac_cv_func_find_thread" = xyes
then :
printf "%s\n" "#define HAVE_FIND_THREAD 1" >>confdefs.h
fi
case "$host_os" in
haiku*)
## get_thread_info() is a public macro wrapping _get_thread_info(), so
## AC_CHECK_FUNCS cannot detect it by looking for a symbol of that name.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether get_thread_info is available" >&5
printf %s "checking whether get_thread_info is available... " >&6; }
if test ${hawk_cv_func_get_thread_info+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
e)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_timedlock (void);
#include <OS.h>
int
main (void)
{
return pthread_mutex_timedlock ();
thread_info info;
return get_thread_info((thread_id)0, &info);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_pthread_pthread_mutex_timedlock=yes
hawk_cv_func_get_thread_info=yes
else case e in #(
e) ac_cv_lib_pthread_pthread_mutex_timedlock=no ;;
e) hawk_cv_func_get_thread_info=no
;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_timedlock" >&5
printf "%s\n" "$ac_cv_lib_pthread_pthread_mutex_timedlock" >&6; }
if test "x$ac_cv_lib_pthread_pthread_mutex_timedlock" = xyes
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hawk_cv_func_get_thread_info" >&5
printf "%s\n" "$hawk_cv_func_get_thread_info" >&6; }
if test "x$hawk_cv_func_get_thread_info" = "xyes"
then :
printf "%s\n" "#define HAVE_PTHREAD_MUTEX_TIMEDLOCK 1" >>confdefs.h
printf "%s\n" "#define HAVE_GET_THREAD_INFO 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_trylock in -lpthread" >&5
printf %s "checking for pthread_mutex_trylock in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread_pthread_mutex_trylock+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_trylock (void);
int
main (void)
{
return pthread_mutex_trylock ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_pthread_pthread_mutex_trylock=yes
else case e in #(
e) ac_cv_lib_pthread_pthread_mutex_trylock=no ;;
;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_trylock" >&5
printf "%s\n" "$ac_cv_lib_pthread_pthread_mutex_trylock" >&6; }
if test "x$ac_cv_lib_pthread_pthread_mutex_trylock" = xyes
then :
printf "%s\n" "#define HAVE_PTHREAD_MUTEX_TRYLOCK 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lunicows" >&5
printf %s "checking for main in -lunicows... " >&6; }
@@ -28200,6 +28220,14 @@ printf "%s\n" "#define HAWK_BUILD_RELEASE 1" >>confdefs.h
BUILD_MODE="release"
fi
if test "${enable_debug_is}" = "yes" ; then
ENABLE_DEBUG_TRUE=
ENABLE_DEBUG_FALSE='#'
else
ENABLE_DEBUG_TRUE='#'
ENABLE_DEBUG_FALSE=
fi
# Check whether --enable-intmax was given.
if test ${enable_intmax+y}
@@ -29678,6 +29706,10 @@ if test -z "${HAVE_LIBUCI_TRUE}" && test -z "${HAVE_LIBUCI_FALSE}"; then
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${ENABLE_DEBUG_TRUE}" && test -z "${ENABLE_DEBUG_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_DEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${ENABLE_CXX_TRUE}" && test -z "${ENABLE_CXX_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_CXX\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
+52 -6
View File
@@ -445,13 +445,58 @@ AC_SUBST(SOCKET_LIBS)
## check pthread
AX_PTHREAD
## check other pthread functions
AC_CHECK_LIB([pthread], [pthread_mutex_timedlock], [
AC_DEFINE([HAVE_PTHREAD_MUTEX_TIMEDLOCK],1,[pthreads has pthread_mutex_timedlock()])
])
AC_CHECK_LIB([pthread], [pthread_mutex_trylock], [
AC_DEFINE([HAVE_PTHREAD_MUTEX_TRYLOCK],1,[pthreads has pthread_mutex_trylock()])
## Check the non-portable pthread interfaces used to obtain the active
## thread's native stack bounds. AX_PTHREAD keeps its flags separate until
## near the end of this script, so apply them temporarily for these checks.
hawk_saved_CFLAGS="$CFLAGS"
hawk_saved_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$LIBS $PTHREAD_LIBS"
AC_CHECK_FUNCS([
pthread_getattr_np
pthread_attr_get_np
pthread_attr_getstack
pthread_attr_getguardsize
pthread_get_stackaddr_np
pthread_get_stacksize_np
pthread_stackseg_np
pthread_mutex_timedlock
pthread_mutex_trylock
])
CFLAGS="$hawk_saved_CFLAGS"
LIBS="$hawk_saved_LIBS"
## Haiku uses Kernel Kit functions instead of pthread stack-bound functions.
AC_CHECK_FUNCS([find_thread])
case "$host_os" in
haiku*)
## get_thread_info() is a public macro wrapping _get_thread_info(), so
## AC_CHECK_FUNCS cannot detect it by looking for a symbol of that name.
AC_CACHE_CHECK(
[whether get_thread_info is available],
[hawk_cv_func_get_thread_info],
[
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <OS.h>]],
[[thread_info info;
return get_thread_info((thread_id)0, &info);]]
)],
[hawk_cv_func_get_thread_info=yes],
[hawk_cv_func_get_thread_info=no]
)
]
)
AS_IF(
[test "x$hawk_cv_func_get_thread_info" = "xyes"],
[AC_DEFINE(
[HAVE_GET_THREAD_INFO],
[1],
[Define if Haiku get_thread_info() is available]
)]
)
;;
esac
dnl check is the import library for unicows.dll exists
dnl this check doesn't look for a particular symbol
@@ -956,6 +1001,7 @@ else
AC_DEFINE([HAWK_BUILD_RELEASE],[1],[build release/debug])
AC_SUBST(BUILD_MODE, "release")
fi
AM_CONDITIONAL(ENABLE_DEBUG, test "${enable_debug_is}" = "yes" )
dnl ===== enable-intmax ======
AC_ARG_ENABLE([intmax],
+347 -158
View File
@@ -5,8 +5,6 @@ package hawk
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct rtx_xtn_t
{
hawk_oow_t inst_no;
@@ -30,23 +28,125 @@ static void init_parsestd_for_file_in(hawk_parsestd_t* in, hawk_bch_t* path)
in[0].u.fileb.cmgr = HAWK_NULL;
}
// -----------------------------------------------
static int is_imm_or_static_val(hawk_rtx_t* rtx, hawk_uintptr_t cptr)
{
return hawk_rtx_isimmorstaticval(rtx, (hawk_val_t*)cptr);
}
static int get_val_type(hawk_rtx_t* rtx, hawk_uintptr_t cptr)
{
return hawk_rtx_getvaltype(rtx, (hawk_val_t*)cptr);
}
static void ref_up_val(hawk_rtx_t* rtx, hawk_uintptr_t cptr)
{
return hawk_rtx_refupval(rtx, (hawk_val_t*)cptr);
}
static void ref_down_val(hawk_rtx_t* rtx, hawk_uintptr_t cptr)
{
return hawk_rtx_refdownval(rtx, (hawk_val_t*)cptr);
}
static int set_gbl(hawk_rtx_t* rtx, int id, hawk_uintptr_t cptr)
{
return hawk_rtx_setgbl(rtx, id, (hawk_val_t*)cptr);
}
static void set_ret_val(hawk_rtx_t* rtx, hawk_uintptr_t cptr)
{
hawk_rtx_setretval(rtx, (hawk_val_t*)cptr);
}
static hawk_ooch_t* valtostr_out_cpldup(hawk_rtx_valtostr_out_t* out, hawk_oow_t* len)
{
*len = out->u.cpldup.len;
return out->u.cpldup.ptr;
}
static hawk_val_t* make_flt_val(hawk_rtx_t* rtx, double v) {
return hawk_rtx_makefltval(rtx, (hawk_flt_t)v);
static hawk_bch_t* val_to_bcstr_dup_with_cmgr(hawk_rtx_t* rtx, hawk_uintptr_t cptr, hawk_oow_t* len, hawk_cmgr_t* cmgr)
{
return hawk_rtx_valtobcstrdupwithcmgr(rtx, (hawk_val_t*)cptr, len, cmgr);
}
static int val_to_flt(hawk_rtx_t* rtx, hawk_val_t* v, double* ret) {
static hawk_uintptr_t make_bchr_val(hawk_rtx_t* rtx, hawk_bch_t v) {
return (hawk_uintptr_t)hawk_rtx_makebchrval(rtx, v);
}
static hawk_uintptr_t make_char_val(hawk_rtx_t* rtx, hawk_ooch_t v) {
return (hawk_uintptr_t)hawk_rtx_makecharval(rtx, v);
}
static hawk_uintptr_t make_int_val(hawk_rtx_t* rtx, hawk_int_t v) {
return (hawk_uintptr_t)hawk_rtx_makeintval(rtx, v);
}
static hawk_uintptr_t make_flt_val(hawk_rtx_t* rtx, double v) {
return (hawk_uintptr_t)hawk_rtx_makefltval(rtx, (hawk_flt_t)v);
}
static int val_to_str(hawk_rtx_t* rtx, hawk_uintptr_t cptr, hawk_rtx_valtostr_out_t* ret) {
return hawk_rtx_valtostr(rtx, (hawk_val_t*)cptr, ret);
}
static int val_to_int(hawk_rtx_t* rtx, hawk_uintptr_t cptr, hawk_int_t* ret) {
return hawk_rtx_valtoint(rtx, (hawk_val_t*)cptr, ret);
}
static int val_to_flt(hawk_rtx_t* rtx, hawk_uintptr_t cptr, double* ret) {
hawk_flt_t fv;
if (hawk_rtx_valtoflt(rtx, v, &fv) <= -1) return -1;
if (hawk_rtx_valtoflt(rtx, (hawk_val_t*)cptr, &fv) <= -1) return -1;
*ret = (double)fv;
return 0;
}
static hawk_val_arr_itr_t* get_first_arr_val_itr(hawk_rtx_t* rtx, hawk_uintptr_t map, hawk_val_arr_itr_t* itr)
{
return hawk_rtx_getfirstarrvalitr(rtx, (hawk_val_t*)map, itr);
}
static hawk_val_arr_itr_t* get_next_arr_val_itr(hawk_rtx_t* rtx, hawk_uintptr_t map, hawk_val_arr_itr_t* itr)
{
return hawk_rtx_getnextarrvalitr(rtx, (hawk_val_t*)map, itr);
}
static hawk_ooi_t get_arr_val_tally(hawk_rtx_t* rtx, hawk_uintptr_t arr)
{
return hawk_rtx_getarrvaltally(rtx, (hawk_val_t*)arr);
}
static hawk_uintptr_t get_arr_val_fld(hawk_rtx_t* rtx, hawk_uintptr_t arr, hawk_ooi_t index)
{
return (hawk_uintptr_t)hawk_rtx_getarrvalfld(rtx, (hawk_val_t*)arr, index);
}
static hawk_uintptr_t set_arr_val_fld(hawk_rtx_t* rtx, hawk_uintptr_t arr, hawk_ooi_t index, hawk_uintptr_t val)
{
return (hawk_uintptr_t)hawk_rtx_setarrvalfld(rtx, (hawk_val_t*)arr, index, (hawk_val_t*)val);
}
static hawk_val_map_itr_t* get_first_map_val_itr(hawk_rtx_t* rtx, hawk_uintptr_t map, hawk_val_map_itr_t* itr)
{
return hawk_rtx_getfirstmapvalitr(rtx, (hawk_val_t*)map, itr);
}
static hawk_val_map_itr_t* get_next_map_val_itr(hawk_rtx_t* rtx, hawk_uintptr_t map, hawk_val_map_itr_t* itr)
{
return hawk_rtx_getnextmapvalitr(rtx, (hawk_val_t*)map, itr);
}
static hawk_uintptr_t get_map_val_fld(hawk_rtx_t* rtx, hawk_uintptr_t map, const hawk_ooch_t* kptr, hawk_oow_t klen)
{
return (hawk_uintptr_t)hawk_rtx_getmapvalfld(rtx, (hawk_val_t*)map, kptr, klen);
}
static hawk_uintptr_t set_map_val_fld(hawk_rtx_t* rtx, hawk_uintptr_t map, const hawk_ooch_t* kptr, hawk_oow_t klen, hawk_uintptr_t val)
{
return (hawk_uintptr_t)hawk_rtx_setmapvalfld(rtx, (hawk_val_t*)map, kptr, klen, (hawk_val_t*)val);
}
// -----------------------------------------------
extern int hawk_go_fnc_handler(rtx_xtn_t* rtx_xtn, hawk_bch_t* name, hawk_oow_t len);
static int hawk_fnc_handler_for_go(hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
@@ -103,6 +203,18 @@ static void init_rtx_xtn_ecb (rtx_xtn_t* xtn)
// -----------------------------------------------
static hawk_uintptr_t val_arr_itr_elem(hawk_val_arr_itr_t* itr)
{
return (hawk_uintptr_t)itr->elem;
}
static hawk_uintptr_t val_map_itr_val(hawk_val_map_itr_t* itr)
{
return (hawk_uintptr_t)HAWK_VAL_MAP_ITR_VAL(itr);
}
// -----------------------------------------------
extern int hawk_mod_go_fnc_gc(rtx_xtn_t* rtx_xtn);
static int fnc_gc(hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
@@ -228,8 +340,14 @@ type Rtx struct {
val_tail *Val
}
type CPtrVal uintptr
type Val struct {
c *C.hawk_val_t
// storing a raw C pointer in the go memory is usually OK.
// but the hawk encodes immediate values using tag in a pointer.
// such values are not valid C pointers and go GC triggered pointer check error.
//c *C.hawk_val_t
c CPtrVal // use a numeric type that can store the pointer
rtx *Rtx
next *Val
prev *Val
@@ -253,7 +371,9 @@ const (
)
type ValArrayItr struct {
c C.hawk_val_arr_itr_t
//c C.hawk_val_arr_itr_t
_ [0]uintptr // for alignment
c [C.sizeof_hawk_val_arr_itr_t]byte
}
type ValMapItr struct {
@@ -654,7 +774,7 @@ func (rtx *Rtx) GetErrInfo() *Err {
}
func (rtx *Rtx) SetGlobal(idx int, val *Val) error {
if C.hawk_rtx_setgbl(rtx.c, C.int(idx), val.c) <= -1 {
if C.set_gbl(rtx.c, C.int(idx), C.hawk_uintptr_t(val.c)) <= -1 {
return rtx.make_errinfo()
}
return nil
@@ -676,7 +796,7 @@ func (rtx *Rtx) OnSigset(f RtxSigsetHandler) {
}
func (rtx *Rtx) Exec(args []string) (*Val, error) {
var val *C.hawk_val_t
var val CPtrVal
var cargs []*C.hawk_bch_t
var idx int
var count int
@@ -688,26 +808,26 @@ func (rtx *Rtx) Exec(args []string) (*Val, error) {
}
if count > 0 {
val = C.hawk_rtx_execwithbcstrarr(rtx.c, &cargs[0], C.hawk_oow_t(count))
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_execwithbcstrarr(rtx.c, &cargs[0], C.hawk_oow_t(count))))
} else {
val = C.hawk_rtx_execwithbcstrarr(rtx.c, (**C.hawk_bch_t)(nil), C.hawk_oow_t(count))
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_execwithbcstrarr(rtx.c, (**C.hawk_bch_t)(nil), C.hawk_oow_t(count))))
}
for idx = 0; idx < count; idx++ {
C.free(unsafe.Pointer(cargs[idx]))
}
if val == nil { return nil, rtx.make_errinfo() }
if val == 0 { return nil, rtx.make_errinfo() }
// hawk_rtx_exec...() returns a value with the reference count incremented.
// create a value without going through rtx.make_val()
return rtx.fix_val_with_raw(val), nil
//return rtx.make_val(func() *C.hawk_val_t { return val })
//return rtx.make_val(func() CPtrVal { return val })
}
func (rtx *Rtx) Loop() (*Val, error) {
var val *C.hawk_val_t
val = C.hawk_rtx_loop(rtx.c)
if val == nil { return nil, rtx.make_errinfo() }
var val CPtrVal
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_loop(rtx.c)))
if val == 0 { return nil, rtx.make_errinfo() }
// hawk_rtx_loop() returns a value with the reference count incremented.
// create a value without going through rtx.make_val()
return rtx.fix_val_with_raw(val), nil
@@ -716,7 +836,7 @@ func (rtx *Rtx) Loop() (*Val, error) {
func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
var fun *C.hawk_fun_t
var val *C.hawk_val_t
var val CPtrVal
var cv *C.hawk_bch_t
var nargs int
@@ -727,21 +847,21 @@ func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
nargs = len(args)
if nargs > 0 {
var argv []*C.hawk_val_t
var argv []CPtrVal
var v *Val
var i int
argv = make([]*C.hawk_val_t, nargs)
argv = make([]CPtrVal, nargs)
for i, v = range args { argv[i] = v.c }
val = C.hawk_rtx_callfun(rtx.c, fun, &argv[0], C.hawk_oow_t(nargs))
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_callfun(rtx.c, fun, (**C.hawk_val_t)(unsafe.Pointer(&argv[0])), C.hawk_oow_t(nargs))))
} else {
val = C.hawk_rtx_callfun(rtx.c, fun, nil, 0)
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_callfun(rtx.c, fun, nil, 0)))
}
if val == nil { return nil, rtx.make_errinfo() }
if val == 0 { return nil, rtx.make_errinfo() }
// hawk_rtx_callfun() returns a value with the reference count incremented.
// i create a Val object without incrementing the reference count of val.
return rtx.fix_val_with_raw(val), nil
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
//return rtx.make_val(func() CPtrVal { return val })
}
func (rtx *Rtx) ValCount() int {
@@ -795,63 +915,65 @@ func (rtx *Rtx) GetFuncArgCount() int {
}
func (rtx *Rtx) GetFuncArg(idx int) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_getarg(rtx.c, C.hawk_oow_t(idx))
return rtx.make_val(func() CPtrVal {
return CPtrVal(unsafe.Pointer(C.hawk_rtx_getarg(rtx.c, C.hawk_oow_t(idx))))
})
}
func (rtx *Rtx) SetFuncRet(v *Val) {
C.hawk_rtx_setretval(rtx.c, v.c)
C.set_ret_val(rtx.c, C.hawk_uintptr_t(v.c))
}
func (rtx *Rtx) SetFuncRetWithInt(v int) error {
var vv *C.hawk_val_t
vv = C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))
if vv == nil { return rtx.make_errinfo() }
C.hawk_rtx_refupval(rtx.c, vv)
C.hawk_rtx_setretval(rtx.c, vv)
C.hawk_rtx_refdownval(rtx.c, vv)
var vv CPtrVal
vv = CPtrVal(C.make_int_val(rtx.c, C.hawk_int_t(v)))
if vv == 0 { return rtx.make_errinfo() }
C.ref_up_val(rtx.c, C.hawk_uintptr_t(vv))
C.set_ret_val(rtx.c, C.hawk_uintptr_t(vv))
C.ref_down_val(rtx.c, C.hawk_uintptr_t(vv))
return nil
}
func (rtx *Rtx) SetFuncRetWithFlt(v float64) error {
var vv *C.hawk_val_t
vv = C.make_flt_val(rtx.c, C.double(v))
if vv == nil { return rtx.make_errinfo() }
C.hawk_rtx_refupval(rtx.c, vv)
C.hawk_rtx_setretval(rtx.c, vv)
C.hawk_rtx_refdownval(rtx.c, vv)
var vv CPtrVal
vv = CPtrVal(C.make_flt_val(rtx.c, C.double(v)))
if vv == 0 { return rtx.make_errinfo() }
C.ref_up_val(rtx.c, C.hawk_uintptr_t(vv))
C.set_ret_val(rtx.c, C.hawk_uintptr_t(vv))
C.ref_down_val(rtx.c, C.hawk_uintptr_t(vv))
return nil
}
func (rtx *Rtx) SetFuncRetWithStr(v string) error {
var vv *C.hawk_val_t
var vv CPtrVal
var cv *C.hawk_bch_t
cv = C.CString(v)
vv = C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))))
C.free(unsafe.Pointer(cv))
if vv == nil { return rtx.make_errinfo() }
C.hawk_rtx_refupval(rtx.c, vv)
C.hawk_rtx_setretval(rtx.c, vv)
C.hawk_rtx_refdownval(rtx.c, vv)
if vv == 0 { return rtx.make_errinfo() }
C.ref_up_val(rtx.c, C.hawk_uintptr_t(vv))
C.set_ret_val(rtx.c, C.hawk_uintptr_t(vv))
C.ref_down_val(rtx.c, C.hawk_uintptr_t(vv))
return nil
}
func (rtx *Rtx) GetNamedVars(vars map[string]*Val) {
var itr C.hawk_rtx_nv_itr_t
var val *C.hawk_val_t
var val CPtrVal
var k string
var err error
C.hawk_init_rtx_nv_itr(&itr)
val = C.hawk_rtx_getfirstnv(rtx.c, &itr)
for val != nil {
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_getfirstnv(rtx.c, &itr)))
for val != 0 {
k = string(uchars_to_rune_slice((*C.hawk_uch_t)(itr.name.ptr), uintptr(itr.name.len)))
vars[k], err = rtx.make_val(func() *C.hawk_val_t { return val })
if err != nil {
return
}
val = C.hawk_rtx_getnextnv(rtx.c, &itr)
vars[k], err = rtx.make_val(func() CPtrVal { return val })
if err != nil { return }
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_getnextnv(rtx.c, &itr)))
}
}
@@ -1036,97 +1158,97 @@ func (rtx *Rtx) NewVal(v interface{}) (*Val, error) {
}
}
func (rtx* Rtx) make_val(vmaker func() *C.hawk_val_t) (*Val, error) {
var c *C.hawk_val_t
func (rtx* Rtx) make_val(vmaker func() CPtrVal) (*Val, error) {
var c CPtrVal
var vv *Val
c = vmaker()
if c == nil { return nil, rtx.make_errinfo() }
if c == 0 { return nil, rtx.make_errinfo() }
C.hawk_rtx_refupval(rtx.c, c)
C.ref_up_val(rtx.c, C.hawk_uintptr_t(c))
vv = &Val{rtx: rtx, c: c}
rtx.chain_val(vv)
return vv, nil
}
func (rtx* Rtx) fix_val_with_raw(val *C.hawk_val_t) *Val {
func (rtx* Rtx) fix_val_with_raw(val CPtrVal) *Val {
// this function assumes val has the non-zero reference count
// the caller must ensure that the reference count has been incremented properly
var vv *Val
// immediate values or static pointer values must no check the reference count.
if C.hawk_rtx_isimmorstaticval(rtx.c, val) == 0 && val.v_refs <= 0 { panic("invalid reference count") }
if C.is_imm_or_static_val(rtx.c, C.hawk_uintptr_t(val)) == 0 && ((*C.hawk_val_t)(unsafe.Pointer(val))).v_refs <= 0 { panic("invalid reference count") }
vv = &Val{rtx: rtx, c: val}
rtx.chain_val(vv)
return vv
}
func (rtx *Rtx) NewByteVal(v byte) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makebchrval(rtx.c, C.hawk_bch_t(v))
return rtx.make_val(func() CPtrVal {
return CPtrVal(C.make_bchr_val(rtx.c, C.hawk_bch_t(v)))
})
}
func (rtx *Rtx) NewCharVal(v rune) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makecharval(rtx.c, C.hawk_ooch_t(v))
return rtx.make_val(func() CPtrVal {
return CPtrVal(C.make_char_val(rtx.c, C.hawk_ooch_t(v)))
})
}
func (rtx *Rtx) NewIntVal(v int) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))
return rtx.make_val(func() CPtrVal {
return CPtrVal(C.make_int_val(rtx.c, C.hawk_int_t(v)))
})
}
func (rtx *Rtx) NewFltVal(v float64) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.make_flt_val(rtx.c, C.double(v))
return rtx.make_val(func() CPtrVal {
return CPtrVal(C.make_flt_val(rtx.c, C.double(v)))
})
}
func (rtx *Rtx) NewStrVal(v string) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
var vv *C.hawk_val_t
return rtx.make_val(func() CPtrVal {
var vv CPtrVal
var cv *C.hawk_bch_t
cv = C.CString(v)
vv = C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))))
C.free(unsafe.Pointer(cv))
return vv
})
}
func (rtx *Rtx) NewNumOrStrVal(v string, mode int) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
var vv *C.hawk_val_t
return rtx.make_val(func() CPtrVal {
var vv CPtrVal
var cv *C.hawk_bch_t
cv = C.CString(v)
vv = C.hawk_rtx_makenumorstrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)), C.int(mode))
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makenumorstrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)), C.int(mode))))
C.free(unsafe.Pointer(cv))
return vv
})
}
func (rtx *Rtx) NewByteArrVal(v []byte) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makembsvalwithbchars(rtx.c, (*C.hawk_bch_t)(unsafe.Pointer(&v[0])), C.hawk_oow_t(len(v)))
return rtx.make_val(func() CPtrVal {
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makembsvalwithbchars(rtx.c, (*C.hawk_bch_t)(unsafe.Pointer(&v[0])), C.hawk_oow_t(len(v)))))
})
}
func (rtx *Rtx) NewBobVal(v []byte) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makebobval(rtx.c, unsafe.Pointer(&v[0]), C.hawk_oow_t(len(v)))
return rtx.make_val(func() CPtrVal {
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makebobval(rtx.c, unsafe.Pointer(&v[0]), C.hawk_oow_t(len(v)))))
})
}
func (rtx *Rtx) NewMapVal() (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makemapval(rtx.c)
return rtx.make_val(func() CPtrVal {
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makemapval(rtx.c)))
})
}
func (rtx *Rtx) NewArrVal(init_capa int) (*Val, error) {
return rtx.make_val(func() *C.hawk_val_t {
return C.hawk_rtx_makearrval(rtx.c, C.hawk_ooi_t(init_capa))
return rtx.make_val(func() CPtrVal {
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makearrval(rtx.c, C.hawk_ooi_t(init_capa))))
})
}
@@ -1137,13 +1259,13 @@ func (val *Val) Close() {
var rtx *C.hawk_rtx_t
rtx = val.rtx.c // store this field as unchain_val() resets it to nil
val.rtx.unchain_val(val)
C.hawk_rtx_refdownval(rtx, val.c)
C.ref_down_val(rtx, C.hawk_uintptr_t(val.c))
}
}
func (val *Val) Type() ValType {
var x C.int
x = C.hawk_rtx_getvaltype(val.rtx.c, val.c)
x = C.get_val_type(val.rtx.c, C.hawk_uintptr_t(val.c))
return ValType(x)
}
@@ -1157,7 +1279,8 @@ func (val *Val) ToInt() (int, error) {
var v C.hawk_int_t
var x C.int
x = C.hawk_rtx_valtoint(val.rtx.c, val.c, &v)
//x = C.hawk_rtx_valtoint(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &v)
x = C.val_to_int(val.rtx.c, C.hawk_uintptr_t(val.c), &v)
if x <= -1 { return 0, val.rtx.make_errinfo() }
return int(v), nil
@@ -1168,7 +1291,7 @@ func (val *Val) ToFlt() (float64, error) {
var x C.int
//x = C.hawk_rtx_valtoflt(val.rtx.c, val.c, &v)
x = C.val_to_flt(val.rtx.c, val.c, (*C.double)(&v))
x = C.val_to_flt(val.rtx.c, C.hawk_uintptr_t(val.c), (*C.double)(&v))
if x <= -1 { return 0, val.rtx.make_errinfo() }
return v, nil
@@ -1182,7 +1305,8 @@ func (val *Val) ToStr() (string, error) {
var x C.int
out._type = C.HAWK_RTX_VALTOSTR_CPLDUP
x = C.hawk_rtx_valtostr(val.rtx.c, val.c, &out)
//x = C.hawk_rtx_valtostr(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &out)
x = C.val_to_str(val.rtx.c, C.hawk_uintptr_t(val.c), &out)
if x <= -1 { return "", val.rtx.make_errinfo() }
ptr = C.valtostr_out_cpldup(&out, &len)
@@ -1197,7 +1321,7 @@ func (val *Val) ToByteArr() ([]byte, error) {
var len C.hawk_oow_t
var v []byte
ptr = C.hawk_rtx_valtobcstrdupwithcmgr(val.rtx.c, val.c, &len, C.hawk_rtx_getcmgr(val.rtx.c))
ptr = C.val_to_bcstr_dup_with_cmgr(val.rtx.c, C.hawk_uintptr_t(val.c), &len, C.hawk_rtx_getcmgr(val.rtx.c))
if ptr == nil { return nil, val.rtx.make_errinfo() }
v = C.GoBytes(unsafe.Pointer(ptr), C.int(len))
@@ -1209,149 +1333,206 @@ func (val *Val) ToByteArr() ([]byte, error) {
func (val *Val) ArrayTally() int {
var v C.hawk_ooi_t
// TODO: if not array .. panic or return -1 or 0?
v = C.hawk_rtx_getarrvaltally(val.rtx.c, val.c)
v = C.get_arr_val_tally(val.rtx.c, C.hawk_uintptr_t(val.c))
return int(v)
}
// TODO: function to get the first index and last index or the capacity
// function to traverse?
func (val *Val) GetArrayField(index int) (*Val, error) {
var v *C.hawk_val_t
v = C.hawk_rtx_getarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index))
if v == nil { return nil, val.rtx.make_errinfo() }
return val.rtx.make_val(func() *C.hawk_val_t { return v })
var v CPtrVal
v = CPtrVal(C.get_arr_val_fld(val.rtx.c, C.hawk_uintptr_t(val.c), C.hawk_ooi_t(index)))
if v == 0 { return nil, val.rtx.make_errinfo() }
return val.rtx.make_val(func() CPtrVal { return v })
}
func (val *Val) SetArrayField(index int, v *Val) error {
var vv *C.hawk_val_t
vv = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), v.c)
if vv == nil { return val.rtx.make_errinfo() }
var vv CPtrVal
vv = CPtrVal(C.set_arr_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
C.hawk_ooi_t(index),
C.hawk_uintptr_t(v.c)))
if vv == 0 { return val.rtx.make_errinfo() }
return nil
}
func (val *Val) SetArrayFieldWithInt(index int, v int) error {
var vv *C.hawk_val_t
var ww *C.hawk_val_t
vv = C.hawk_rtx_makeintval(val.rtx.c, C.hawk_int_t(v))
if vv == nil { return val.rtx.make_errinfo() }
C.hawk_rtx_refupval(val.rtx.c, vv)
ww = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), vv)
C.hawk_rtx_refdownval(val.rtx.c, vv)
if ww == nil { return val.rtx.make_errinfo() }
var vv CPtrVal
var ww CPtrVal
vv = CPtrVal(C.make_int_val(val.rtx.c, C.hawk_int_t(v)))
if vv == 0 { return val.rtx.make_errinfo() }
C.ref_up_val(val.rtx.c, C.hawk_uintptr_t(vv))
ww = CPtrVal(C.set_arr_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
C.hawk_ooi_t(index),
C.hawk_uintptr_t(vv)))
C.ref_down_val(val.rtx.c, C.hawk_uintptr_t(vv))
if ww == 0 { return val.rtx.make_errinfo() }
return nil
}
func (val *Val) SetArrayFieldWithFlt(index int, v float64) error {
var vv *C.hawk_val_t
vv = C.make_flt_val(val.rtx.c, C.double(v))
if vv == nil { return val.rtx.make_errinfo() }
C.hawk_rtx_refupval(val.rtx.c, vv)
vv = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), vv)
C.hawk_rtx_refdownval(val.rtx.c, vv)
if vv == nil { return val.rtx.make_errinfo() }
var vv CPtrVal
var ww CPtrVal
vv = CPtrVal(C.make_flt_val(val.rtx.c, C.double(v)))
if vv == 0 { return val.rtx.make_errinfo() }
C.ref_up_val(val.rtx.c, C.hawk_uintptr_t(vv))
ww = CPtrVal(C.set_arr_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
C.hawk_ooi_t(index),
C.hawk_uintptr_t(vv)))
C.ref_down_val(val.rtx.c, C.hawk_uintptr_t(vv))
if ww == 0 { return val.rtx.make_errinfo() }
return nil
}
func (val *Val) SetArrayFieldWithStr(index int, v string) error {
var vv *C.hawk_val_t
var vv CPtrVal
var ww CPtrVal
var cv *C.hawk_bch_t
cv = C.CString(v)
vv = C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))))
C.free(unsafe.Pointer(cv))
if vv == nil { return val.rtx.make_errinfo() }
C.hawk_rtx_refupval(val.rtx.c, vv)
vv = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), vv)
C.hawk_rtx_refdownval(val.rtx.c, vv)
if vv == nil { return val.rtx.make_errinfo() }
if vv == 0 { return val.rtx.make_errinfo() }
C.ref_up_val(val.rtx.c, C.hawk_uintptr_t(vv))
ww = CPtrVal(C.set_arr_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
C.hawk_ooi_t(index),
C.hawk_uintptr_t(vv)))
C.ref_down_val(val.rtx.c, C.hawk_uintptr_t(vv))
if ww == 0 { return val.rtx.make_errinfo() }
return nil
}
func (itr *ValArrayItr) cptr() *C.hawk_val_arr_itr_t {
return (*C.hawk_val_arr_itr_t)(unsafe.Pointer(&itr.c[0]))
}
func (val *Val) GetFirstArrayField(itr *ValArrayItr) (int, *Val) {
var i *C.hawk_val_arr_itr_t
var v *Val
var err error
i = C.hawk_rtx_getfirstarrvalitr(val.rtx.c, val.c, &itr.c)
i = C.get_first_arr_val_itr(val.rtx.c, C.hawk_uintptr_t(val.c), itr.cptr())
if i == nil { return -1, nil }
v, err = val.rtx.make_val(func() *C.hawk_val_t { return itr.c.elem })
v, err = val.rtx.make_val(func() CPtrVal {
return CPtrVal(C.val_arr_itr_elem(itr.cptr()))
})
if err != nil { return -1, nil }
return int(itr.c.itr.idx), v;
return int(itr.cptr().itr.idx), v;
}
func (val *Val) GetNextArrayField(itr *ValArrayItr) (int, *Val) {
var i *C.hawk_val_arr_itr_t
var v *Val
var err error
i = C.hawk_rtx_getnextarrvalitr(val.rtx.c, val.c, &itr.c)
i = C.get_next_arr_val_itr(val.rtx.c, C.hawk_uintptr_t(val.c), itr.cptr())
if i == nil { return -1, nil }
v, err = val.rtx.make_val(func() *C.hawk_val_t { return itr.c.elem })
v, err = val.rtx.make_val(func() CPtrVal {
return CPtrVal(C.val_arr_itr_elem(itr.cptr()))
})
if err != nil { return -1, nil }
return int(itr.c.itr.idx), v;
return int(itr.cptr().itr.idx), v;
}
func (val *Val) GetMapField(key string) (*Val, error) {
var v *C.hawk_val_t
var v CPtrVal
var uc []C.hawk_uch_t
uc = string_to_uchars(key)
v = C.hawk_rtx_getmapvalfld(val.rtx.c, val.c, &uc[0], C.hawk_oow_t(len(uc)))
if v == nil { return nil, val.rtx.make_errinfo() }
return val.rtx.make_val(func() *C.hawk_val_t { return v })
v = CPtrVal(C.get_map_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
&uc[0],
C.hawk_oow_t(len(uc))))
if v == 0 { return nil, val.rtx.make_errinfo() }
return val.rtx.make_val(func() CPtrVal { return v })
}
func (val *Val) SetMapField(key string, v *Val) error {
var vv *C.hawk_val_t
var vv CPtrVal
var kk []C.hawk_uch_t
kk = string_to_uchars(key)
vv = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), v.c)
if vv == nil { return val.rtx.make_errinfo() }
vv = CPtrVal(C.set_map_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
&kk[0],
C.hawk_oow_t(len(kk)),
C.hawk_uintptr_t(v.c)))
if vv == 0 { return val.rtx.make_errinfo() }
return nil
}
func (val *Val) SetMapFieldWithInt(key string, v int) error {
var kk []C.hawk_uch_t
var vv *C.hawk_val_t
var ww *C.hawk_val_t
var vv CPtrVal
var ww CPtrVal
kk = string_to_uchars(key)
vv = C.hawk_rtx_makeintval(val.rtx.c, C.hawk_int_t(v))
if vv == nil { return val.rtx.make_errinfo() }
C.hawk_rtx_refupval(val.rtx.c, vv)
ww = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), vv)
C.hawk_rtx_refdownval(val.rtx.c, vv)
if ww == nil { return val.rtx.make_errinfo() }
vv = CPtrVal(C.make_int_val(val.rtx.c, C.hawk_int_t(v)))
if vv == 0 { return val.rtx.make_errinfo() }
C.ref_up_val(val.rtx.c, C.hawk_uintptr_t(vv))
ww = CPtrVal(C.set_map_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
&kk[0],
C.hawk_oow_t(len(kk)),
C.hawk_uintptr_t(vv)))
C.ref_down_val(val.rtx.c, C.hawk_uintptr_t(vv))
if ww == 0 { return val.rtx.make_errinfo() }
return nil
}
func (val *Val) SetMapFieldWithFlt(key string, v float64) error {
var kk []C.hawk_uch_t
var vv *C.hawk_val_t
var ww *C.hawk_val_t
var vv CPtrVal
var ww CPtrVal
kk = string_to_uchars(key)
vv = C.make_flt_val(val.rtx.c, C.double(v))
if vv == nil { return val.rtx.make_errinfo() }
C.hawk_rtx_refupval(val.rtx.c, vv)
ww = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), vv)
C.hawk_rtx_refdownval(val.rtx.c, vv)
if ww == nil { return val.rtx.make_errinfo() }
vv = CPtrVal(C.make_flt_val(val.rtx.c, C.double(v)))
if vv == 0 { return val.rtx.make_errinfo() }
C.ref_up_val(val.rtx.c, C.hawk_uintptr_t(vv))
ww = CPtrVal(C.set_map_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
&kk[0],
C.hawk_oow_t(len(kk)),
C.hawk_uintptr_t(vv)))
C.ref_down_val(val.rtx.c, C.hawk_uintptr_t(vv))
if ww == 0 { return val.rtx.make_errinfo() }
return nil
}
func (val *Val) SetMapFieldWithStr(key string, v string) error {
var kk []C.hawk_uch_t
var vv *C.hawk_val_t
var ww *C.hawk_val_t
var vv CPtrVal
var ww CPtrVal
var cv *C.hawk_bch_t
kk = string_to_uchars(key)
cv = C.CString(v)
vv = C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))))
C.free(unsafe.Pointer(cv))
if vv == nil { return val.rtx.make_errinfo() }
C.hawk_rtx_refupval(val.rtx.c, vv)
ww = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), vv)
C.hawk_rtx_refdownval(val.rtx.c, vv)
if ww == nil { return val.rtx.make_errinfo() }
if vv == 0 { return val.rtx.make_errinfo() }
C.ref_up_val(val.rtx.c, C.hawk_uintptr_t(vv))
ww = CPtrVal(C.set_map_val_fld(
val.rtx.c,
C.hawk_uintptr_t(val.c),
&kk[0],
C.hawk_oow_t(len(kk)),
C.hawk_uintptr_t(vv)))
C.ref_down_val(val.rtx.c, C.hawk_uintptr_t(vv))
if ww == 0 { return val.rtx.make_errinfo() }
return nil
}
@@ -1360,10 +1541,14 @@ func (val *Val) GetFirstMapField(itr *ValMapItr) (string, *Val) {
var k string
var v *Val
var err error
i = C.hawk_rtx_getfirstmapvalitr(val.rtx.c, val.c, &itr.c)
i = C.get_first_map_val_itr(val.rtx.c, C.hawk_uintptr_t(val.c), &itr.c)
if i == nil { return "", nil }
k = string(uchars_to_rune_slice((*C.hawk_uch_t)(itr.c.pair.key.ptr), uintptr(itr.c.pair.key.len)))
v, err = val.rtx.make_val(func() *C.hawk_val_t { return (*C.hawk_val_t)(itr.c.pair.val.ptr) })
v, err = val.rtx.make_val(func() CPtrVal {
return CPtrVal(C.val_map_itr_val(&itr.c))
})
if err != nil { return "", nil }
return k, v;
}
@@ -1373,10 +1558,14 @@ func (val *Val) GetNextMapField(itr *ValMapItr) (string, *Val) {
var k string
var v *Val
var err error
i = C.hawk_rtx_getnextmapvalitr(val.rtx.c, val.c, &itr.c)
i = C.get_next_map_val_itr(val.rtx.c, C.hawk_uintptr_t(val.c), &itr.c)
if i == nil { return "", nil }
k = string(uchars_to_rune_slice((*C.hawk_uch_t)(itr.c.pair.key.ptr), uintptr(itr.c.pair.key.len)))
v, err = val.rtx.make_val(func() *C.hawk_val_t { return (*C.hawk_val_t)(itr.c.pair.val.ptr) })
v, err = val.rtx.make_val(func() CPtrVal {
return CPtrVal(C.val_map_itr_val(&itr.c))
})
if err != nil { return "", nil }
return k, v;
}
+696 -13
View File
@@ -19,7 +19,9 @@ func make_hawk(script string) (*hawk.Hawk, error) {
var err error
h, err = hawk.New()
if err != nil { return nil, err }
if err != nil {
return nil, err
}
err = h.ParseText(script)
if err != nil {
@@ -31,7 +33,7 @@ func make_hawk(script string) (*hawk.Hawk, error) {
}
func enbase64(rtx *hawk.Rtx) error {
fmt.Printf ("*** ENBASE64 RTX %p\n", rtx) // << this is 0 from time to time.. TODO: fix it..
fmt.Printf("*** ENBASE64 RTX %p\n", rtx) // << this is 0 from time to time.. TODO: fix it..
fmt.Printf("****ENBASE64 [%d]\n", rtx.GetFuncArgCount())
var a0 *hawk.Val = hawk.Must(rtx.GetFuncArg(0))
@@ -47,7 +49,7 @@ func debase64(rtx *hawk.Rtx) error {
fmt.Printf("****DEBASE64 [%d]\n", rtx.GetFuncArgCount())
rtx.SetFuncRet(hawk.Must(rtx.NewFltVal(-999.1111)))
return nil
//return fmt.Errorf("what the hell.....")
// return fmt.Errorf("what the hell.....")
}
func make_hawk_extended(script string) (*hawk.Hawk, error) {
@@ -55,7 +57,9 @@ func make_hawk_extended(script string) (*hawk.Hawk, error) {
var err error
h, err = hawk.New()
if err != nil { return nil, err }
if err != nil {
return nil, err
}
h.AddFunc("enbase64", 1, 10, "", enbase64)
h.AddFunc("debase64", 1, 1, "", debase64)
@@ -69,6 +73,314 @@ func make_hawk_extended(script string) (*hawk.Hawk, error) {
return h, nil
}
func echoint(rtx *hawk.Rtx) error {
var v *hawk.Val
var i int
var err error
v, err = rtx.GetFuncArg(0)
if err != nil {
return err
}
i, err = v.ToInt()
if err != nil {
return err
}
return rtx.SetFuncRetWithInt(i)
}
func force_gc() {
runtime.GC()
runtime.Gosched()
}
func force_full_gc() {
var junk [][]byte
var i int
junk = make([][]byte, 32)
for i = 0; i < len(junk); i++ {
junk[i] = make([]byte, 1024+(i*17))
}
runtime.GC()
debug.FreeOSMemory()
runtime.Gosched()
runtime.KeepAlive(junk)
}
func keep_vals_alive(vals []*hawk.Val) {
var holder []*hawk.Val
holder = make([]*hawk.Val, len(vals))
copy(holder, vals)
force_full_gc()
runtime.KeepAlive(holder)
}
func expect_type(t *testing.T, v *hawk.Val, want hawk.ValType, msg string) {
t.Helper()
if v.Type() != want {
t.Fatalf("%s: expected type %s but got %s", msg, want.String(), v.Type().String())
}
}
func expect_int_val(t *testing.T, v *hawk.Val, want int, msg string) {
var got int
var s string
var err error
t.Helper()
got, err = v.ToInt()
if err != nil {
t.Fatalf("%s: failed to convert to int - %s", msg, err.Error())
}
if got != want {
t.Fatalf("%s: expected %d but got %d", msg, want, got)
}
s, err = v.ToStr()
if err != nil {
t.Fatalf("%s: failed to convert to string - %s", msg, err.Error())
}
if s != fmt.Sprintf("%d", want) {
t.Fatalf("%s: expected string %q but got %q", msg, fmt.Sprintf("%d", want), s)
}
}
func expect_map_ints_with_gc(t *testing.T, v *hawk.Val, want map[string]int, gc func()) {
var key string
var f *hawk.Val
var got map[string]int
var itr hawk.ValMapItr
var err error
t.Helper()
if v.Type() != hawk.VAL_MAP {
t.Fatalf("expected a map but got %s", v.Type().String())
}
for key = range want {
gc()
f, err = v.GetMapField(key)
if err != nil {
t.Fatalf("failed to get map field %q - %s", key, err.Error())
}
expect_int_val(t, f, want[key], fmt.Sprintf("map field %q", key))
}
got = make(map[string]int)
key, f = v.GetFirstMapField(&itr)
for f != nil {
var iv int
gc()
iv, err = f.ToInt()
if err != nil {
t.Fatalf("failed to convert iterated map value for key %q - %s", key, err.Error())
}
got[key] = iv
gc()
key, f = v.GetNextMapField(&itr)
}
if len(got) != len(want) {
t.Fatalf("expected %d iterated map entries but got %d", len(want), len(got))
}
for key = range want {
if got[key] != want[key] {
t.Fatalf("iterated map field %q: expected %d but got %d", key, want[key], got[key])
}
}
}
func expect_map_ints(t *testing.T, v *hawk.Val, want map[string]int) {
expect_map_ints_with_gc(t, v, want, force_gc)
}
func expect_array_ints_with_gc(t *testing.T, v *hawk.Val, want map[int]int, gc func()) {
var idx int
var f *hawk.Val
var got map[int]int
var itr hawk.ValArrayItr
var err error
t.Helper()
if v.Type() != hawk.VAL_ARR {
t.Fatalf("expected an array but got %s", v.Type().String())
}
if v.ArrayTally() != len(want) {
t.Fatalf("expected %d array elements but got %d", len(want), v.ArrayTally())
}
for idx = range want {
gc()
f, err = v.GetArrayField(idx)
if err != nil {
t.Fatalf("failed to get array field %d - %s", idx, err.Error())
}
expect_int_val(t, f, want[idx], fmt.Sprintf("array field %d", idx))
}
got = make(map[int]int)
idx, f = v.GetFirstArrayField(&itr)
for f != nil {
var iv int
gc()
iv, err = f.ToInt()
if err != nil {
t.Fatalf("failed to convert iterated array value at %d - %s", idx, err.Error())
}
got[idx] = iv
gc()
idx, f = v.GetNextArrayField(&itr)
}
if len(got) != len(want) {
t.Fatalf("expected %d iterated array entries but got %d", len(want), len(got))
}
for idx = range want {
if got[idx] != want[idx] {
t.Fatalf("iterated array field %d: expected %d but got %d", idx, want[idx], got[idx])
}
}
}
func expect_array_ints(t *testing.T, v *hawk.Val, want map[int]int) {
expect_array_ints_with_gc(t, v, want, force_gc)
}
func echo_tagged(rtx *hawk.Rtx) error {
var v *hawk.Val
var err error
force_full_gc()
v, err = rtx.GetFuncArg(0)
if err != nil {
return err
}
keep_vals_alive([]*hawk.Val{v})
rtx.SetFuncRet(v)
keep_vals_alive([]*hawk.Val{v})
return nil
}
func sum_tagged(rtx *hawk.Rtx) error {
var vals []*hawk.Val
var argc int
var i int
var sum int
argc = rtx.GetFuncArgCount()
vals = make([]*hawk.Val, argc)
for i = 0; i < argc; i++ {
var v *hawk.Val
var iv int
var err error
force_full_gc()
v, err = rtx.GetFuncArg(i)
if err != nil {
return err
}
vals[i] = v
force_full_gc()
iv, err = v.ToInt()
if err != nil {
return err
}
sum += iv
}
keep_vals_alive(vals)
return rtx.SetFuncRetWithInt(sum)
}
func make_tagged_map(rtx *hawk.Rtx) error {
var m *hawk.Val
var vals []*hawk.Val
var entry = []struct {
key string
val int
}{
{"zero", 0},
{"one", 1},
{"neg", -1},
{"big", 777777},
{"small", -333333},
}
var i int
var err error
m, err = rtx.NewMapVal()
if err != nil {
return err
}
vals = make([]*hawk.Val, len(entry))
for i = 0; i < len(entry); i++ {
vals[i], err = rtx.NewIntVal(entry[i].val)
if err != nil {
return err
}
force_full_gc()
if err = m.SetMapField(entry[i].key, vals[i]); err != nil {
return err
}
}
keep_vals_alive(vals)
rtx.SetFuncRet(m)
force_full_gc()
runtime.KeepAlive(m)
return nil
}
func make_tagged_arr(rtx *hawk.Rtx) error {
var a *hawk.Val
var vals []*hawk.Val
var entry = []int{0, 1, -1, 777777, -333333}
var i int
var err error
a, err = rtx.NewArrVal(0)
if err != nil {
return err
}
vals = make([]*hawk.Val, len(entry))
for i = 0; i < len(entry); i++ {
vals[i], err = rtx.NewIntVal(entry[i])
if err != nil {
return err
}
force_full_gc()
if err = a.SetArrayField(i+1, vals[i]); err != nil {
return err
}
}
keep_vals_alive(vals)
rtx.SetFuncRet(a)
force_full_gc()
runtime.KeepAlive(a)
return nil
}
func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
var rtx *hawk.Rtx
var v *hawk.Val
@@ -86,9 +398,9 @@ func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
}
v, err = rtx.Call("x",
hawk.Must(rtx.NewVal/*FromInt*/(id + 10)),
hawk.Must(rtx.NewVal([]byte{'A',66,67,68,69})),
hawk.Must(rtx.NewVal/*FromStr*/("this is cool")))
hawk.Must(rtx.NewVal /*FromInt*/ (id+10)),
hawk.Must(rtx.NewVal([]byte{'A', 66, 67, 68, 69})),
hawk.Must(rtx.NewVal /*FromStr*/ ("this is cool")))
if err != nil {
t.Errorf("failed to invoke function 'x' for rtx id[%d] - %s", id, err.Error())
rtx.Close()
@@ -105,13 +417,17 @@ func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
// check if ValCount() returns the right number of values created. 3 explicitly and 1 return value
i = rtx.ValCount()
if i != 4 { t.Errorf("the number of val objects for rtx id[%d] must be 4. but %d was returned", id, i) }
if i != 4 {
t.Errorf("the number of val objects for rtx id[%d] must be 4. but %d was returned", id, i)
}
rtx.Close()
// it's safe to all ValCount() after Close() has been called.
i = rtx.ValCount()
if i != 0 { t.Errorf("the number of val objects for rtx id[%d] must be 0. but %d was returned", id, i) }
if i != 0 {
t.Errorf("the number of val objects for rtx id[%d] must be 0. but %d was returned", id, i)
}
}
func Test1(t *testing.T) {
@@ -143,12 +459,14 @@ return 1.9923;
// when rtx objects are all closed, the counter must drop to 0
i = h.RtxCount()
if i != 0 { t.Errorf("the number of rtx objects must be 0. but %d was returned", i) }
if i != 0 {
t.Errorf("the number of rtx objects must be 0. but %d was returned", i)
}
h.Close()
h = nil
fmt.Printf ("== END of Test1 ==\n")
fmt.Printf("== END of Test1 ==\n")
runtime.GC()
runtime.Gosched()
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
@@ -298,7 +616,7 @@ func Test3(t *testing.T) {
debug.SetGCPercent(100) // enable normal GC
fmt.Printf ("BEGINNING OF TEST3\n")
fmt.Printf("BEGINNING OF TEST3\n")
h, err = make_hawk_extended(`function main(s) {
print enbase64(s, "hello", 1.289);
@@ -325,10 +643,375 @@ return x
}
h.Close()
fmt.Printf ("END OF TEST3\n")
fmt.Printf("END OF TEST3\n")
runtime.GC()
runtime.Gosched()
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
}
func Test4(t *testing.T) {
var h *hawk.Hawk
var rtx *hawk.Rtx
var v *hawk.Val
var gm *hawk.Val
var ga *hawk.Val
var err error
var round int
debug.SetGCPercent(100)
h, err = hawk.New()
if err != nil {
t.Fatalf("Failed to make hawk - %s", err.Error())
}
h.AddFunc("echoint", 1, 1, "", echoint)
err = h.ParseText(`function ret_zero() { return 0; }
function ret_one() { return 1; }
function ret_neg() { return -1; }
function call_echo_zero() { return echoint(0); }
function call_echo_neg() { return echoint(-1); }
function make_int_map() {
@local x;
x["zero"] = 0;
x["one"] = 1;
x["neg"] = -1;
return x;
}
function make_int_arr() {
@local x;
x = hawk::array(0, 1, -1);
return x;
}`)
if err != nil {
h.Close()
t.Fatalf("Failed to parse hawk script - %s", err.Error())
}
rtx, err = h.NewRtx("test4", nil, nil)
if err != nil {
h.Close()
t.Fatalf("failed to create rtx - %s", err.Error())
}
for round = 0; round < 32; round++ {
for _, tc := range []struct {
name string
want int
}{
{"ret_zero", 0},
{"ret_one", 1},
{"ret_neg", -1},
{"call_echo_zero", 0},
{"call_echo_neg", -1},
} {
force_gc()
v, err = rtx.Call(tc.name)
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call %s - %s", tc.name, err.Error())
}
force_gc()
expect_int_val(t, v, tc.want, tc.name)
}
}
v, err = rtx.Call("make_int_map")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call make_int_map - %s", err.Error())
}
expect_map_ints(t, v, map[string]int{
"zero": 0,
"one": 1,
"neg": -1,
})
v, err = rtx.Call("make_int_arr")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call make_int_arr - %s", err.Error())
}
expect_array_ints(t, v, map[int]int{
1: 0,
2: 1,
3: -1,
})
gm = hawk.Must(rtx.NewMapVal())
if err = gm.SetMapFieldWithInt("zero", 0); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set zero map field - %s", err.Error())
}
if err = gm.SetMapFieldWithInt("one", 1); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set one map field - %s", err.Error())
}
if err = gm.SetMapFieldWithInt("neg", -1); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set neg map field - %s", err.Error())
}
expect_map_ints(t, gm, map[string]int{
"zero": 0,
"one": 1,
"neg": -1,
})
ga = hawk.Must(rtx.NewArrVal(0))
if err = ga.SetArrayFieldWithInt(1, 0); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set array field 1 - %s", err.Error())
}
if err = ga.SetArrayFieldWithInt(2, 1); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set array field 2 - %s", err.Error())
}
if err = ga.SetArrayFieldWithInt(3, -1); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set array field 3 - %s", err.Error())
}
expect_array_ints(t, ga, map[int]int{
1: 0,
2: 1,
3: -1,
})
rtx.Close()
h.Close()
force_gc()
time.Sleep(100 * time.Millisecond)
}
func Test5TaggedPointerStress(t *testing.T) {
var h *hawk.Hawk
var rtx *hawk.Rtx
var v *hawk.Val
var args []*hawk.Val
var gzero int
var gone int
var gneg int
var round int
var old_gc_percent int
var err error
old_gc_percent = debug.SetGCPercent(1)
defer debug.SetGCPercent(old_gc_percent)
h, err = hawk.New()
if err != nil {
t.Fatalf("Failed to make hawk - %s", err.Error())
}
h.AddFunc("go_echo_tagged", 1, 1, "", echo_tagged)
h.AddFunc("go_sum_tagged", 1, 16, "", sum_tagged)
h.AddFunc("go_make_tagged_map", 0, 0, "", make_tagged_map)
h.AddFunc("go_make_tagged_arr", 0, 0, "", make_tagged_arr)
gzero, err = h.AddGlobal("gzero")
if err != nil {
h.Close()
t.Fatalf("failed to add global gzero - %s", err.Error())
}
gone, err = h.AddGlobal("gone")
if err != nil {
h.Close()
t.Fatalf("failed to add global gone - %s", err.Error())
}
gneg, err = h.AddGlobal("gneg")
if err != nil {
h.Close()
t.Fatalf("failed to add global gneg - %s", err.Error())
}
err = h.ParseText(`function ret_arg(a) { return a; }
function wrap_echo(a) { return go_echo_tagged(a); }
function wrap_sum(a, b, c, d, e) { return go_sum_tagged(a, b, c, d, e); }
function wrap_map() { return go_make_tagged_map(); }
function wrap_arr() { return go_make_tagged_arr(); }
function make_hawk_map() {
@local x;
x["zero"] = 0;
x["one"] = 1;
x["neg"] = -1;
x["big"] = 777777;
x["small"] = -333333;
return x;
}
function make_hawk_arr() {
@local x;
x = hawk::array(0, 1, -1, 777777, -333333);
return x;
}
function sum_globals() { return gzero + gone + gneg; }`)
if err != nil {
h.Close()
t.Fatalf("Failed to parse hawk script - %s", err.Error())
}
rtx, err = h.NewRtx("test5", nil, nil)
if err != nil {
h.Close()
t.Fatalf("failed to create rtx - %s", err.Error())
}
for round = 0; round < 128; round++ {
args = []*hawk.Val{
hawk.Must(rtx.NewIntVal(0)),
hawk.Must(rtx.NewIntVal(1)),
hawk.Must(rtx.NewIntVal(-1)),
hawk.Must(rtx.NewIntVal(round)),
hawk.Must(rtx.NewIntVal(-round - 1)),
hawk.Must(rtx.NewByteVal(byte('A' + (round % 26)))),
hawk.Must(rtx.NewCharVal(rune('a' + (round % 26)))),
}
keep_vals_alive(args)
if err = rtx.SetGlobal(gzero, args[0]); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set gzero - %s", err.Error())
}
if err = rtx.SetGlobal(gone, args[1]); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set gone - %s", err.Error())
}
if err = rtx.SetGlobal(gneg, args[2]); err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to set gneg - %s", err.Error())
}
force_full_gc()
v, err = rtx.Call("sum_globals")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call sum_globals - %s", err.Error())
}
force_full_gc()
expect_int_val(t, v, 0, "sum_globals")
v, err = rtx.Call("ret_arg", args[0])
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call ret_arg - %s", err.Error())
}
force_full_gc()
expect_int_val(t, v, 0, "ret_arg(0)")
v, err = rtx.Call("wrap_echo", args[1])
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call wrap_echo for int - %s", err.Error())
}
force_full_gc()
expect_int_val(t, v, 1, "wrap_echo(1)")
v, err = rtx.Call("wrap_sum", args[0], args[1], args[2], args[3], args[4])
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call wrap_sum - %s", err.Error())
}
force_full_gc()
expect_int_val(t, v, -1, "wrap_sum")
v, err = rtx.Call("wrap_arr")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call wrap_arr - %s", err.Error())
}
expect_array_ints_with_gc(t, v, map[int]int{
1: 0,
2: 1,
3: -1,
4: 777777,
5: -333333,
}, force_full_gc)
v, err = rtx.Call("wrap_map")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call wrap_map - %s", err.Error())
}
expect_map_ints_with_gc(t, v, map[string]int{
"zero": 0,
"one": 1,
"neg": -1,
"big": 777777,
"small": -333333,
}, force_full_gc)
v, err = rtx.Call("make_hawk_arr")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call make_hawk_arr - %s", err.Error())
}
expect_array_ints_with_gc(t, v, map[int]int{
1: 0,
2: 1,
3: -1,
4: 777777,
5: -333333,
}, force_full_gc)
v, err = rtx.Call("make_hawk_map")
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call make_hawk_map - %s", err.Error())
}
expect_map_ints_with_gc(t, v, map[string]int{
"zero": 0,
"one": 1,
"neg": -1,
"big": 777777,
"small": -333333,
}, force_full_gc)
v, err = rtx.Call("wrap_echo", args[5])
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call wrap_echo for byte value - %s", err.Error())
}
force_full_gc()
expect_type(t, v, hawk.VAL_BCHR, "wrap_echo(byte)")
v, err = rtx.Call("wrap_echo", args[6])
if err != nil {
rtx.Close()
h.Close()
t.Fatalf("failed to call wrap_echo for char value - %s", err.Error())
}
force_full_gc()
expect_type(t, v, hawk.VAL_CHAR, "wrap_echo(char)")
keep_vals_alive(args)
}
rtx.Close()
h.Close()
force_full_gc()
time.Sleep(100 * time.Millisecond)
}
+1 -2
View File
@@ -382,9 +382,8 @@ public:
{
DEPTH_INCLUDE = HAWK_OPT_DEPTH_INCLUDE,
DEPTH_BLOCK_PARSE = HAWK_OPT_DEPTH_BLOCK_PARSE,
DEPTH_BLOCK_RUN = HAWK_OPT_DEPTH_BLOCK_RUN,
DEPTH_EXPR_PARSE = HAWK_OPT_DEPTH_EXPR_PARSE,
DEPTH_EXPR_RUN = HAWK_OPT_DEPTH_EXPR_RUN,
DEPTH_RECURS_RUN = HAWK_OPT_DEPTH_RECURS_RUN,
DEPTH_REX_BUILD = HAWK_OPT_DEPTH_REX_BUILD,
DEPTH_REX_MATCH = HAWK_OPT_DEPTH_REX_MATCH
};
+1
View File
@@ -93,6 +93,7 @@ libhawk_la_SOURCES = \
big5.c \
big5.h \
chr.c \
cstack.c \
cut-prv.h \
cut.c \
dir.c \
+47 -34
View File
@@ -258,22 +258,22 @@ am__libhawk_la_SOURCES_DIST = hawk.h hawk-arr.h hawk-chr.h hawk-cli.h \
hawk-map.h hawk-mtx.h hawk-rbt.h hawk-pac1.h hawk-pio.h \
hawk-po.h hawk-skad.h hawk-utl.h hawk-sed.h hawk-sio.h \
hawk-str.h hawk-tio.h hawk-tre.h hawk-upac.h hawk-xma.h \
Hawk.hpp Hawk-Sed.hpp arr.c big5.c big5.h chr.c cut-prv.h \
cut.c dir.c ecs-imp.h ecs.c err-prv.h err.c err-sys.c \
fmt-imp.h fmt.c fnc-prv.h fnc.c gbk.c gbk.h gem.c gem-glob.c \
gem-nwif.c gem-nwif2.c hawk-prv.h hawk.c htb.c idmap-imp.h \
jis0208.c jis0208.h json.c json-prv.h ksc5601.c ksc5601.h \
mb8.c misc-imp.h misc-prv.h misc.c parse-prv.h parse.c \
po-cat.c rbt.c rec.c rio-prv.h rio.c run-prv.h run.c sed-prv.h \
sed.c skad-prv.h skad.c tre-prv.h tre-ast.c tre-ast.h \
tre-compile.c tre-compile.h tre-match-bt.c tre-match-pa.c \
tre-match-ut.h tre-mem.c tre-mem.h tre-parse.c tre-parse.h \
tre-stack.h tre-stack.c tre.c tree-prv.h tree.c uch-prop.h \
uch-case.h utf16.c utf8.c utl-ass.c utl-cmgr.c utl-rnd.c \
utl-sort.c utl-str.c utl-sys.c utl-xstr.c utl.c val-prv.h \
val.c xma.c cli-imp.h cli.c fio.c mtx.c pio.c sio.c syscall.h \
tio.c std.c std-cut.c std-json.c std-sed.c Hawk.cpp Std.cpp \
Sed.cpp Std-Sed.cpp mod-hawk.c mod-hawk.h mod-math.c \
Hawk.hpp Hawk-Sed.hpp arr.c big5.c big5.h chr.c cstack.c \
cut-prv.h cut.c dir.c ecs-imp.h ecs.c err-prv.h err.c \
err-sys.c fmt-imp.h fmt.c fnc-prv.h fnc.c gbk.c gbk.h gem.c \
gem-glob.c gem-nwif.c gem-nwif2.c hawk-prv.h hawk.c htb.c \
idmap-imp.h jis0208.c jis0208.h json.c json-prv.h ksc5601.c \
ksc5601.h mb8.c misc-imp.h misc-prv.h misc.c parse-prv.h \
parse.c po-cat.c rbt.c rec.c rio-prv.h rio.c run-prv.h run.c \
sed-prv.h sed.c skad-prv.h skad.c tre-prv.h tre-ast.c \
tre-ast.h tre-compile.c tre-compile.h tre-match-bt.c \
tre-match-pa.c tre-match-ut.h tre-mem.c tre-mem.h tre-parse.c \
tre-parse.h tre-stack.h tre-stack.c tre.c tree-prv.h tree.c \
uch-prop.h uch-case.h utf16.c utf8.c utl-ass.c utl-cmgr.c \
utl-rnd.c utl-sort.c utl-str.c utl-sys.c utl-xstr.c utl.c \
val-prv.h val.c xma.c cli-imp.h cli.c fio.c mtx.c pio.c sio.c \
syscall.h tio.c std.c std-cut.c std-json.c std-sed.c Hawk.cpp \
Std.cpp Sed.cpp Std-Sed.cpp mod-hawk.c mod-hawk.h mod-math.c \
mod-math.h mod-str.c mod-str.h mod-sys.c mod-sys.h \
../mod/mod-ffi.c ../mod/mod-ffi.h ../mod/mod-memc.c \
../mod/mod-memc.h ../mod/mod-mysql.c ../mod/mod-mysql.h \
@@ -303,21 +303,22 @@ am__dirstamp = $(am__leading_dot)dirstamp
@ENABLE_MOD_UCI_STATIC_TRUE@am__objects_11 = \
@ENABLE_MOD_UCI_STATIC_TRUE@ ../mod/libhawk_la-mod-uci.lo
am_libhawk_la_OBJECTS = $(am__objects_2) libhawk_la-arr.lo \
libhawk_la-big5.lo libhawk_la-chr.lo libhawk_la-cut.lo \
libhawk_la-dir.lo libhawk_la-ecs.lo libhawk_la-err.lo \
libhawk_la-err-sys.lo libhawk_la-fmt.lo libhawk_la-fnc.lo \
libhawk_la-gbk.lo libhawk_la-gem.lo libhawk_la-gem-glob.lo \
libhawk_la-gem-nwif.lo libhawk_la-gem-nwif2.lo \
libhawk_la-hawk.lo libhawk_la-htb.lo libhawk_la-jis0208.lo \
libhawk_la-json.lo libhawk_la-ksc5601.lo libhawk_la-mb8.lo \
libhawk_la-misc.lo libhawk_la-parse.lo libhawk_la-po-cat.lo \
libhawk_la-rbt.lo libhawk_la-rec.lo libhawk_la-rio.lo \
libhawk_la-run.lo libhawk_la-sed.lo libhawk_la-skad.lo \
libhawk_la-tre-ast.lo libhawk_la-tre-compile.lo \
libhawk_la-tre-match-bt.lo libhawk_la-tre-match-pa.lo \
libhawk_la-tre-mem.lo libhawk_la-tre-parse.lo \
libhawk_la-tre-stack.lo libhawk_la-tre.lo libhawk_la-tree.lo \
libhawk_la-utf16.lo libhawk_la-utf8.lo libhawk_la-utl-ass.lo \
libhawk_la-big5.lo libhawk_la-chr.lo libhawk_la-cstack.lo \
libhawk_la-cut.lo libhawk_la-dir.lo libhawk_la-ecs.lo \
libhawk_la-err.lo libhawk_la-err-sys.lo libhawk_la-fmt.lo \
libhawk_la-fnc.lo libhawk_la-gbk.lo libhawk_la-gem.lo \
libhawk_la-gem-glob.lo libhawk_la-gem-nwif.lo \
libhawk_la-gem-nwif2.lo libhawk_la-hawk.lo libhawk_la-htb.lo \
libhawk_la-jis0208.lo libhawk_la-json.lo libhawk_la-ksc5601.lo \
libhawk_la-mb8.lo libhawk_la-misc.lo libhawk_la-parse.lo \
libhawk_la-po-cat.lo libhawk_la-rbt.lo libhawk_la-rec.lo \
libhawk_la-rio.lo libhawk_la-run.lo libhawk_la-sed.lo \
libhawk_la-skad.lo libhawk_la-tre-ast.lo \
libhawk_la-tre-compile.lo libhawk_la-tre-match-bt.lo \
libhawk_la-tre-match-pa.lo libhawk_la-tre-mem.lo \
libhawk_la-tre-parse.lo libhawk_la-tre-stack.lo \
libhawk_la-tre.lo libhawk_la-tree.lo libhawk_la-utf16.lo \
libhawk_la-utf8.lo libhawk_la-utl-ass.lo \
libhawk_la-utl-cmgr.lo libhawk_la-utl-rnd.lo \
libhawk_la-utl-sort.lo libhawk_la-utl-str.lo \
libhawk_la-utl-sys.lo libhawk_la-utl-xstr.lo libhawk_la-utl.lo \
@@ -357,8 +358,10 @@ am__depfiles_remade = ../mod/$(DEPDIR)/libhawk_la-mod-ffi.Plo \
./$(DEPDIR)/libhawk_la-Std-Sed.Plo \
./$(DEPDIR)/libhawk_la-Std.Plo ./$(DEPDIR)/libhawk_la-arr.Plo \
./$(DEPDIR)/libhawk_la-big5.Plo ./$(DEPDIR)/libhawk_la-chr.Plo \
./$(DEPDIR)/libhawk_la-cli.Plo ./$(DEPDIR)/libhawk_la-cut.Plo \
./$(DEPDIR)/libhawk_la-dir.Plo ./$(DEPDIR)/libhawk_la-ecs.Plo \
./$(DEPDIR)/libhawk_la-cli.Plo \
./$(DEPDIR)/libhawk_la-cstack.Plo \
./$(DEPDIR)/libhawk_la-cut.Plo ./$(DEPDIR)/libhawk_la-dir.Plo \
./$(DEPDIR)/libhawk_la-ecs.Plo \
./$(DEPDIR)/libhawk_la-err-sys.Plo \
./$(DEPDIR)/libhawk_la-err.Plo ./$(DEPDIR)/libhawk_la-fio.Plo \
./$(DEPDIR)/libhawk_la-fmt.Plo ./$(DEPDIR)/libhawk_la-fnc.Plo \
@@ -703,7 +706,7 @@ pkginclude_HEADERS = hawk.h hawk-arr.h hawk-chr.h hawk-cli.h \
$(am__append_7)
pkglib_LTLIBRARIES = libhawk.la $(am__append_11)
libhawk_la_SOURCES = $(pkginclude_HEADERS) arr.c big5.c big5.h chr.c \
cut-prv.h cut.c dir.c ecs-imp.h ecs.c err-prv.h err.c \
cstack.c cut-prv.h cut.c dir.c ecs-imp.h ecs.c err-prv.h err.c \
err-sys.c fmt-imp.h fmt.c fnc-prv.h fnc.c gbk.c gbk.h gem.c \
gem-glob.c gem-nwif.c gem-nwif2.c hawk-prv.h hawk.c htb.c \
idmap-imp.h jis0208.c jis0208.h json.c json-prv.h ksc5601.c \
@@ -914,6 +917,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-big5.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-chr.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-cli.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-cstack.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-cut.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-dir.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-ecs.Plo@am__quote@ # am--include-marker
@@ -1058,6 +1062,13 @@ libhawk_la-chr.lo: chr.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_la_CFLAGS) $(CFLAGS) -c -o libhawk_la-chr.lo `test -f 'chr.c' || echo '$(srcdir)/'`chr.c
libhawk_la-cstack.lo: cstack.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_la_CFLAGS) $(CFLAGS) -MT libhawk_la-cstack.lo -MD -MP -MF $(DEPDIR)/libhawk_la-cstack.Tpo -c -o libhawk_la-cstack.lo `test -f 'cstack.c' || echo '$(srcdir)/'`cstack.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhawk_la-cstack.Tpo $(DEPDIR)/libhawk_la-cstack.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cstack.c' object='libhawk_la-cstack.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_la_CFLAGS) $(CFLAGS) -c -o libhawk_la-cstack.lo `test -f 'cstack.c' || echo '$(srcdir)/'`cstack.c
libhawk_la-cut.lo: cut.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_la_CFLAGS) $(CFLAGS) -MT libhawk_la-cut.lo -MD -MP -MF $(DEPDIR)/libhawk_la-cut.Tpo -c -o libhawk_la-cut.lo `test -f 'cut.c' || echo '$(srcdir)/'`cut.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhawk_la-cut.Tpo $(DEPDIR)/libhawk_la-cut.Plo
@@ -1771,6 +1782,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libhawk_la-big5.Plo
-rm -f ./$(DEPDIR)/libhawk_la-chr.Plo
-rm -f ./$(DEPDIR)/libhawk_la-cli.Plo
-rm -f ./$(DEPDIR)/libhawk_la-cstack.Plo
-rm -f ./$(DEPDIR)/libhawk_la-cut.Plo
-rm -f ./$(DEPDIR)/libhawk_la-dir.Plo
-rm -f ./$(DEPDIR)/libhawk_la-ecs.Plo
@@ -1897,6 +1909,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libhawk_la-big5.Plo
-rm -f ./$(DEPDIR)/libhawk_la-chr.Plo
-rm -f ./$(DEPDIR)/libhawk_la-cli.Plo
-rm -f ./$(DEPDIR)/libhawk_la-cstack.Plo
-rm -f ./$(DEPDIR)/libhawk_la-cut.Plo
-rm -f ./$(DEPDIR)/libhawk_la-dir.Plo
-rm -f ./$(DEPDIR)/libhawk_la-ecs.Plo
+181
View File
@@ -0,0 +1,181 @@
/*
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_GNU_SOURCE)
/* to expose non-portable functions like pthread_getattr_np() */
#define _GNU_SOURCE
#endif
#include "hawk-prv.h"
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
#if defined(_WIN32)
# include <windows.h>
#elif defined(__HAIKU__)
# include <OS.h>
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <pthread.h>
# if defined(__FreeBSD__)
# include <pthread_np.h>
# elif defined(__OpenBSD__)
# include <signal.h>
# include <pthread_np.h>
# endif
#endif
int hawk_rtx_entercstack (hawk_rtx_t* rtx)
{
hawk_oow_t low = 0, high = HAWK_TYPE_MAX(hawk_oow_t);
hawk_oow_t pos = HAWK_CSTACK_POSITION(low);
#if defined(_WIN32)
MEMORY_BASIC_INFORMATION mbi;
typedef BOOL (WINAPI *get_guarantee_t)(ULONG*);
get_guarantee_t get_guarantee;
HMODULE kernel;
ULONG guarantee = 0;
if (!VirtualQuery((const void*)pos, &mbi, HAWK_SIZEOF(mbi))) goto unavailable;
/* AllocationBase includes the reserved portion, unlike the TIB's
* StackLimit which only describes currently committed stack pages. */
low = (hawk_oow_t)mbi.AllocationBase;
high = (hawk_oow_t)mbi.BaseAddress + mbi.RegionSize;
/* A host may reserve additional exception-handling stack space. A zero
* request queries it without changing it. Resolve dynamically for old
* Windows versions which do not implement SetThreadStackGuarantee. */
kernel = GetModuleHandleA("kernel32.dll");
if (HAWK_UNLIKELY(!kernel)) goto unavailable;
get_guarantee = (get_guarantee_t)GetProcAddress(kernel, "SetThreadStackGuarantee");
if (get_guarantee && !get_guarantee(&guarantee)) goto unavailable;
if (low >= high || guarantee >= high - low)
{
hawk_rtx_seterrbfmt(rtx, HAWK_NULL, HAWK_ESTACK, "native C stack limit reached");
return -1;
}
low += guarantee;
#elif defined(__HAIKU__)
thread_info ti;
if (get_thread_info(find_thread(HAWK_NULL), &ti) != B_OK) goto unavailable;
/* The Kernel Kit documentation has this:
* https://www.haiku-os.org/legacy-docs/bebook/TheKernelKit_ThreadsAndTeams.html#thread_info
* Warning
* The two stack pointers are currently inverted such that stack_base is less than stack_end.
* (In a stack-grows-down world, the base should be greater than the end.) */
low = (hawk_oow_t)ti.stack_base;
high = (hawk_oow_t)ti.stack_end;
#elif defined(__APPLE__)
size_t size;
high = (hawk_oow_t)pthread_get_stackaddr_np(pthread_self());
size = pthread_get_stacksize_np(pthread_self());
if (size > high) goto unavailable;
low = high - size;
#elif defined(__OpenBSD__)
stack_t seg;
if (pthread_stackseg_np(pthread_self(), &seg) != 0) goto unavailable;
high = (hawk_oow_t)seg.ss_sp; /* this API returns the top, not the base */
if (seg.ss_size > high) goto unavailable;
low = high - seg.ss_size;
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
pthread_attr_t attr;
void* addr;
size_t size, guard;
int n;
#if defined(__FreeBSD__) || defined(__NetBSD__)
if (pthread_attr_init(&attr) != 0) goto unavailable;
n = pthread_attr_get_np(pthread_self(), &attr);
if (n != 0)
{
pthread_attr_destroy(&attr);
goto unavailable;
}
#else
if (pthread_getattr_np(pthread_self(), &attr) != 0) goto unavailable;
#endif
n = pthread_attr_getstack(&attr, &addr, &size);
guard = 0;
if (n == 0) n = pthread_attr_getguardsize(&attr, &guard);
pthread_attr_destroy(&attr);
if (n != 0 || guard >= size) goto unavailable;
low = (hawk_oow_t)addr;
if (size > HAWK_TYPE_MAX(hawk_oow_t) - low) goto unavailable;
high = low + size;
/* some pthread implementations include the guard in the reported
* interval, others exclude it. exclude it conservatively in either case. */
#if defined(HAWK_CSTACK_GROWS_UPWARDS)
high -= guard;
#else
low += guard;
#endif
#endif
if (low >= high || pos < low || pos >= high) goto unavailable;
if (high - low <= HAWK_CSTACK_HEADROOM) goto cstack_full;
#if defined(HAWK_CSTACK_GROWS_UPWARDS)
high -= HAWK_CSTACK_HEADROOM;
#else
low += HAWK_CSTACK_HEADROOM;
#endif
if (pos < low || pos >= high) goto cstack_full;
#if defined(HAWK_CSTACK_GROWS_UPWARDS)
rtx->cstack_limit = high;
#else
rtx->cstack_limit = low;
#endif
return 0;
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
unavailable:
hawk_rtx_seterrbfmt(rtx, HAWK_NULL, HAWK_ESYSERR, "unable to determine native C stack bounds");
return -1;
cstack_full:
hawk_rtx_seterrbfmt(rtx, HAWK_NULL, HAWK_ESTACK, "native C stack limit reached");
return -1;
#endif
}
#endif
+29 -2
View File
@@ -169,6 +169,9 @@
/* Define to 1 if you have the 'ffi_prep_cif_var' function. */
#undef HAVE_FFI_PREP_CIF_VAR
/* Define to 1 if you have the 'find_thread' function. */
#undef HAVE_FIND_THREAD
/* Define to 1 if you have the 'floor' function. */
#undef HAVE_FLOOR
@@ -223,6 +226,9 @@
/* Define to 1 if you have the 'gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define if Haiku get_thread_info() is available */
#undef HAVE_GET_THREAD_INFO
/* Define to 1 if you have the 'gmtime_r' function. */
#undef HAVE_GMTIME_R
@@ -355,15 +361,36 @@
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* pthreads has pthread_mutex_timedlock() */
/* Define to 1 if you have the 'pthread_attr_getguardsize' function. */
#undef HAVE_PTHREAD_ATTR_GETGUARDSIZE
/* Define to 1 if you have the 'pthread_attr_getstack' function. */
#undef HAVE_PTHREAD_ATTR_GETSTACK
/* Define to 1 if you have the 'pthread_attr_get_np' function. */
#undef HAVE_PTHREAD_ATTR_GET_NP
/* Define to 1 if you have the 'pthread_getattr_np' function. */
#undef HAVE_PTHREAD_GETATTR_NP
/* Define to 1 if you have the 'pthread_get_stackaddr_np' function. */
#undef HAVE_PTHREAD_GET_STACKADDR_NP
/* Define to 1 if you have the 'pthread_get_stacksize_np' function. */
#undef HAVE_PTHREAD_GET_STACKSIZE_NP
/* Define to 1 if you have the 'pthread_mutex_timedlock' function. */
#undef HAVE_PTHREAD_MUTEX_TIMEDLOCK
/* pthreads has pthread_mutex_trylock() */
/* Define to 1 if you have the 'pthread_mutex_trylock' function. */
#undef HAVE_PTHREAD_MUTEX_TRYLOCK
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
/* Define to 1 if you have the 'pthread_stackseg_np' function. */
#undef HAVE_PTHREAD_STACKSEG_NP
/* Define to 1 if you have the <quadmath.h> header file. */
#undef HAVE_QUADMATH_H
-2
View File
@@ -1776,8 +1776,6 @@ typedef enum hawk_log_mask_t hawk_log_mask_t;
# error Unsupported platform
#endif
#if 0
/* =========================================================================
* SOCKET ADDRESS
+79 -5
View File
@@ -69,6 +69,8 @@ typedef struct hawk_tree_t hawk_tree_t;
#define HAWK_ENABLE_ATOMIC_SIG
#endif
#define HAWK_ENABLE_CSTACK_CHECK
/* ------------------------------------------------------------------------ */
/* private headers. some files are affected by feature macros above */
@@ -259,14 +261,13 @@ struct hawk_t
union
{
hawk_oow_t a[7]; /**< to access the elements of the #s field as an array */
hawk_oow_t a[6]; /**< to access the elements of the #s field as an array */
struct
{
hawk_oow_t incl;
hawk_oow_t block_parse;
hawk_oow_t block_run;
hawk_oow_t expr_parse;
hawk_oow_t expr_run;
hawk_oow_t recurs_run;
hawk_oow_t rex_build;
hawk_oow_t rex_match;
} s; /**< defines the maximum nesting depths */
@@ -462,6 +463,10 @@ struct hawk_rtx_t
hawk_oow_t stack_base;
hawk_oow_t stack_limit;
/* Native stack stopping boundary for the current host entry, unrelated to
* the value stack above. Saved/restored across host callback reentry. */
hawk_oow_t cstack_limit;
/* heap-based stack for iterative statement execution */
hawk_exec_stack_t* exec_stack;
hawk_oow_t exec_stack_size;
@@ -618,8 +623,7 @@ struct hawk_rtx_t
struct
{
hawk_oow_t block;
hawk_oow_t expr; /* expression */
hawk_oow_t recurs; /* recursion depth including both blocks and expressions */
} depth;
struct
@@ -730,6 +734,38 @@ static HAWK_INLINE void HAWK_RTX_STACK_POP (hawk_rtx_t* rtx)
# define HAWK_DEFAULT_MODPOSTFIX ""
#endif
/* ------------------------------------------------------------------------ */
#if defined(HAWK_ENABLE_CSTACK_CHECK) && defined(_WIN32)
# define HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#elif defined(HAWK_ENABLE_CSTACK_CHECK) && defined(__HAIKU__) && defined(HAVE_FIND_THREAD) && defined(HAVE_GET_THREAD_INFO)
# define HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#elif defined(HAWK_ENABLE_CSTACK_CHECK) && defined(__APPLE__) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) && defined(HAVE_PTHREAD_GET_STACKSIZE_NP)
# define HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#elif defined(HAWK_ENABLE_CSTACK_CHECK) && defined(__OpenBSD__) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_STACKSEG_NP)
# define HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#elif defined(HAWK_ENABLE_CSTACK_CHECK) && defined(__linux__) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) && defined(HAVE_PTHREAD_ATTR_GETGUARDSIZE)
# define HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#elif defined(HAWK_ENABLE_CSTACK_CHECK) && (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_ATTR_GET_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) && defined(HAVE_PTHREAD_ATTR_GETGUARDSIZE)
# define HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#else
# undef HAWK_HAVE_NATIVE_CSTACK_BOUNDS
#endif
#if defined(__hppa__)
#define HAWK_CSTACK_GROWS_UPWARDS (1)
#undef HAWK_CSTACK_GROWS_DOWNWARDS
#else
#undef HAWK_CSTACK_GROWS_UPWARDS
#define HAWK_CSTACK_GROWS_DOWNWARDS (1)
#endif
/* leave room for unchecked C helpers, error reporting and value cleanup.
* This is not a guarantee for arbitrary native extension code or alloca(). */
#define HAWK_CSTACK_HEADROOM ((hawk_oow_t)65536)
/* ------------------------------------------------------------------------ */
#if defined(__cplusplus)
extern "C" {
#endif
@@ -746,6 +782,44 @@ void* hawk_rtx_commit_environ (
hawk_rtx_env_mk_type_t env_mk_type
);
/* read SP without forcing a frame pointer in hot evaluators. SP and the
* frame-address fallback stay on the real stack under AddressSanitizer,
* unlike an address-taken local that may be placed on its fake stack. */
#if (defined(__GNUC__) || defined(__clang__)) && (defined(__x86_64__) || defined(__i386__) || (defined(__aarch64__) && HAWK_SIZEOF_VOID_P == 8) || defined(__arm__))
static HAWK_INLINE_ALWAYS hawk_oow_t hawk_cstack_position (void)
{
hawk_oow_t pos;
#if defined(__x86_64__) && HAWK_SIZEOF_VOID_P == 8
__asm__ __volatile__("mov %%rsp, %0" : "=r" (pos));
#elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("mov %%esp, %0" : "=r" (pos));
#else
__asm__ __volatile__("mov %0, sp" : "=r" (pos));
#endif
return pos;
}
#define HAWK_CSTACK_POSITION(local) hawk_cstack_position()
#elif defined(__GNUC__) || defined(__clang__)
#define HAWK_CSTACK_POSITION(local) ((hawk_oow_t)__builtin_frame_address(0))
#else
#define HAWK_CSTACK_POSITION(local) ((hawk_oow_t)&(local))
#endif
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
/* entry validates both bounds. during evaluation the native stack grows
* towards only one boundary; thread/fiber reentry refreshes that boundary. */
#if defined(HAWK_CSTACK_GROWS_UPWARDS)
#define HAWK_CSTACK_OK(rtx,local) (HAWK_CSTACK_POSITION(local) < (rtx)->cstack_limit)
#else
#define HAWK_CSTACK_OK(rtx,local) (HAWK_CSTACK_POSITION(local) >= (rtx)->cstack_limit)
#endif
#else
#define HAWK_CSTACK_OK(rtx,local) (1)
#endif
int hawk_rtx_entercstack(hawk_rtx_t* rtx);
#if defined(__cplusplus)
}
#endif
+2 -4
View File
@@ -592,9 +592,8 @@ int hawk_setopt (hawk_t* hawk, hawk_opt_t id, const void* value)
case HAWK_OPT_DEPTH_INCLUDE:
case HAWK_OPT_DEPTH_BLOCK_PARSE: /* s.block_parse */
case HAWK_OPT_DEPTH_BLOCK_RUN: /* s.block_run */
case HAWK_OPT_DEPTH_EXPR_PARSE: /* s.expr_parse */
case HAWK_OPT_DEPTH_EXPR_RUN: /* s.expr_run */
case HAWK_OPT_DEPTH_RECURS_RUN: /* s.expr_run */
case HAWK_OPT_DEPTH_REX_BUILD:
case HAWK_OPT_DEPTH_REX_MATCH:
hawk->opt.depth.a[id - HAWK_OPT_DEPTH_INCLUDE] = *(const hawk_oow_t*)value;
@@ -640,9 +639,8 @@ int hawk_getopt (hawk_t* hawk, hawk_opt_t id, void* value)
case HAWK_OPT_DEPTH_INCLUDE:
case HAWK_OPT_DEPTH_BLOCK_PARSE:
case HAWK_OPT_DEPTH_BLOCK_RUN:
case HAWK_OPT_DEPTH_EXPR_PARSE:
case HAWK_OPT_DEPTH_EXPR_RUN:
case HAWK_OPT_DEPTH_RECURS_RUN:
case HAWK_OPT_DEPTH_REX_BUILD:
case HAWK_OPT_DEPTH_REX_MATCH:
*(hawk_oow_t*)value = hawk->opt.depth.a[id - HAWK_OPT_DEPTH_INCLUDE];
+6 -2
View File
@@ -841,6 +841,7 @@ struct hawk_prm_t
hawk_mod_getsym_t modgetsym;
hawk_log_write_t logwrite;
#if 0
struct
{
@@ -1316,9 +1317,12 @@ enum hawk_opt_t
HAWK_OPT_DEPTH_INCLUDE,
HAWK_OPT_DEPTH_BLOCK_PARSE,
HAWK_OPT_DEPTH_BLOCK_RUN,
HAWK_OPT_DEPTH_EXPR_PARSE,
HAWK_OPT_DEPTH_EXPR_RUN,
/* HAWK_OPT_DEPTH_RECURS_RUN is ignored on the platform where the native
* C stack information is available */
HAWK_OPT_DEPTH_RECURS_RUN,
HAWK_OPT_DEPTH_REX_BUILD,
HAWK_OPT_DEPTH_REX_MATCH,
+2 -2
View File
@@ -93,7 +93,7 @@ static __IDMAP_NODE_T* __MAKE_IDMAP_NODE (hawk_rtx_t* rtx, __IDMAP_LIST_T* list)
node = hawk_rtx_callocmem(rtx, HAWK_SIZEOF(*node));
if (!node) goto oops;
if (list->map.high <= list->map.capa)
if (list->map.high >= list->map.capa)
{
hawk_oow_t newcapa, inc;
__IDMAP_NODE_T** tmp;
@@ -107,7 +107,7 @@ static __IDMAP_NODE_T* __MAKE_IDMAP_NODE (hawk_rtx_t* rtx, __IDMAP_LIST_T* list)
tmp = (__IDMAP_NODE_T**)hawk_rtx_reallocmem(rtx, list->map.tab, HAWK_SIZEOF(*tmp) * newcapa);
if (!tmp) goto oops;
HAWK_MEMSET (&tmp[list->map.capa], 0, HAWK_SIZEOF(*tmp) * (newcapa - list->map.capa));
HAWK_MEMSET(&tmp[list->map.capa], 0, HAWK_SIZEOF(*tmp) * (newcapa - list->map.capa));
list->map.tab = tmp;
list->map.capa = newcapa;
+239 -26
View File
@@ -24,6 +24,7 @@
#include "mod-sys.h"
#include "hawk-prv.h"
#include <hawk-fio.h>
#include <hawk-pio.h>
#include <hawk-dir.h>
@@ -66,6 +67,7 @@
#endif
#include <stdlib.h> /* getenv, system */
#include <stdio.h> /* remove */
#include <time.h>
#include <errno.h>
#include <string.h>
@@ -3128,6 +3130,190 @@ static int fnc_getenv (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
/* ------------------------------------------------------------ */
static int fnc_tempname (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
static const hawk_bch_t default_prefix[] = HAWK_BT("hawk-");
sys_list_t* sys_list;
hawk_val_t* prefix_arg = HAWK_NULL;
hawk_val_t* retv = HAWK_NULL;
hawk_bch_t* prefix_buf = HAWK_NULL;
const hawk_bch_t* prefix = default_prefix;
hawk_oow_t prefix_len = HAWK_COUNTOF(default_prefix) - 1;
const hawk_bch_t* tmpdir;
hawk_oow_t tmpdir_len, path_len, extra, i;
hawk_bch_t* path = HAWK_NULL;
hawk_fio_t* fio;
int need_sep;
#if defined(_WIN32)
hawk_bch_t tmpdir_buf[MAX_PATH + 1];
hawk_bch_t* tmpdir_alloc = HAWK_NULL;
DWORD n;
#endif
sys_list = rtx_to_sys_list(rtx, fi);
if (hawk_rtx_getnargs(rtx) >= 1)
{
prefix_arg = hawk_rtx_getarg(rtx, 0);
prefix_buf = hawk_rtx_getvalbcstr(rtx, prefix_arg, &prefix_len);
if (!prefix_buf)
{
copy_error_to_sys_list(rtx, sys_list);
goto soft_fail;
}
prefix = prefix_buf;
if (hawk_find_bchar_in_bchars(prefix, prefix_len, '\0'))
{
set_error_on_sys_list(rtx, sys_list, HAWK_EINVAL, HAWK_T("invalid temporary file prefix"));
goto soft_fail;
}
for (i = 0; i < prefix_len; i++)
{
if (HAWK_IS_PATH_SEP(prefix[i]))
{
set_error_on_sys_list(rtx, sys_list, HAWK_EINVAL, HAWK_T("temporary file prefix contains a path separator"));
goto soft_fail;
}
}
}
#if defined(_WIN32)
n = GetTempPathA(HAWK_COUNTOF(tmpdir_buf), tmpdir_buf);
if (n == 0)
{
set_error_on_sys_list(rtx, sys_list, hawk_syserr_to_errnum(GetLastError()), HAWK_T("unable to get the temporary directory"));
goto soft_fail;
}
if (n >= HAWK_COUNTOF(tmpdir_buf))
{
DWORD capa;
if ((hawk_oow_t)n >= HAWK_TYPE_MAX(hawk_oow_t) / HAWK_SIZEOF(*tmpdir_alloc))
{
set_error_on_sys_list(rtx, sys_list, HAWK_EINVAL, HAWK_T("temporary directory path too long"));
goto soft_fail;
}
capa = n + 1;
tmpdir_alloc = hawk_rtx_allocmem(rtx, (hawk_oow_t)capa * HAWK_SIZEOF(*tmpdir_alloc));
if (!tmpdir_alloc)
{
copy_error_to_sys_list(rtx, sys_list);
goto soft_fail;
}
n = GetTempPathA(capa, tmpdir_alloc);
if (n == 0)
{
set_error_on_sys_list(rtx, sys_list, hawk_syserr_to_errnum(GetLastError()), HAWK_T("unable to get the temporary directory"));
goto soft_fail;
}
if (n >= capa)
{
set_error_on_sys_list(rtx, sys_list, HAWK_EINVAL, HAWK_T("temporary directory path too long"));
goto soft_fail;
}
tmpdir = tmpdir_alloc;
}
else tmpdir = tmpdir_buf;
#else
tmpdir = getenv("TMPDIR");
if (!tmpdir || !tmpdir[0]) tmpdir = getenv("TEMP");
if (!tmpdir || !tmpdir[0]) tmpdir = getenv("TMP");
if (!tmpdir || !tmpdir[0])
{
#if defined(__OS2__) || defined(__DOS__)
tmpdir = ".";
#elif defined(vms) || defined(__vms)
tmpdir = "SYS$SCRATCH:";
#elif defined(P_tmpdir)
tmpdir = P_tmpdir;
#else
tmpdir = "/tmp";
#endif
}
#endif
tmpdir_len = hawk_count_bcstr(tmpdir);
need_sep = tmpdir_len > 0 && !HAWK_IS_PATH_SEP(tmpdir[tmpdir_len - 1]);
#if defined(vms) || defined(__vms)
if (tmpdir_len > 0 && tmpdir[tmpdir_len - 1] == ':') need_sep = 0;
#endif
/* Four trailing characters are replaced by HAWK_FIO_TEMPORARY. */
extra = 5 + need_sep; /* random suffix plus terminating null */
if (prefix_len > HAWK_TYPE_MAX(hawk_oow_t) - extra ||
tmpdir_len > HAWK_TYPE_MAX(hawk_oow_t) - prefix_len - extra)
{
set_error_on_sys_list(rtx, sys_list, HAWK_EINVAL, HAWK_T("temporary file path too long"));
goto soft_fail;
}
path_len = tmpdir_len + need_sep + prefix_len + 4;
path = hawk_rtx_allocmem(rtx, (path_len + 1) * HAWK_SIZEOF(*path));
if (!path)
{
copy_error_to_sys_list(rtx, sys_list);
goto soft_fail;
}
HAWK_MEMCPY(path, tmpdir, tmpdir_len * HAWK_SIZEOF(*path));
i = tmpdir_len;
if (need_sep)
{
/* TODO: no hardcoding? */
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
path[i++] = '\\';
#else
path[i++] = '/';
#endif
}
HAWK_MEMCPY(&path[i], prefix, prefix_len * HAWK_SIZEOF(*path));
i += prefix_len;
HAWK_MEMCPY(&path[i], "0000", 4 * HAWK_SIZEOF(*path));
path[path_len] = '\0';
fio = hawk_fio_open(
hawk_rtx_getgem(rtx), 0, (const hawk_ooch_t*)path,
HAWK_FIO_BCSTRPATH | HAWK_FIO_TEMPORARY | HAWK_FIO_WRITE |
HAWK_FIO_CREATE | HAWK_FIO_EXCLUSIVE,
HAWK_FIO_RUSR | HAWK_FIO_WUSR
);
if (!fio)
{
copy_error_to_sys_list(rtx, sys_list);
goto soft_fail;
}
hawk_fio_close(fio);
retv = hawk_rtx_makestrvalwithbcstr(rtx, path);
if (!retv)
{
remove(path);
goto hard_fail;
}
hawk_rtx_setretval(rtx, retv);
if (path) hawk_rtx_freemem(rtx, path);
#if defined(_WIN32)
if (tmpdir_alloc) hawk_rtx_freemem(rtx, tmpdir_alloc);
#endif
if (prefix_buf) hawk_rtx_freevalbcstr(rtx, prefix_arg, prefix_buf);
return 0;
soft_fail:
retv = hawk_rtx_makestrvalwithoocstr(rtx, HAWK_T(""));
if (!retv) goto hard_fail;
hawk_rtx_setretval(rtx, retv);
hard_fail:
if (path) hawk_rtx_freemem(rtx, path);
#if defined(_WIN32)
if (tmpdir_alloc) hawk_rtx_freemem(rtx, tmpdir_alloc);
#endif
if (prefix_buf) hawk_rtx_freevalbcstr(rtx, prefix_arg, prefix_buf);
return retv? 0: -1;
}
/* ------------------------------------------------------------ */
/*
BEGIN {
if (sys::getnwifcfg("eth0", sys::NWIFCFG_IN6, x) >= 0)
@@ -5405,7 +5591,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_int8_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.ptr[rdp->pack.len++] = (hawk_int8_t)v;
}
break;
@@ -5417,7 +5604,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uint8_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.ptr[rdp->pack.len++] = (hawk_uint8_t)v;
}
break;
@@ -5429,7 +5617,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_int16_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uint16(&rdp->pack.ptr[rdp->pack.len], (hawk_int16_t)v, endian);
}
break;
@@ -5441,7 +5630,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uint16_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uint16(&rdp->pack.ptr[rdp->pack.len], (hawk_uint16_t)v, endian);
}
break;
@@ -5453,7 +5643,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_int32_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uint32(&rdp->pack.ptr[rdp->pack.len], (hawk_int32_t)v, endian);
}
break;
@@ -5465,7 +5656,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uint32_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uint32(&rdp->pack.ptr[rdp->pack.len], (hawk_uint32_t)v, endian);
}
break;
@@ -5478,7 +5670,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_int64_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uint64(&rdp->pack.ptr[rdp->pack.len], (hawk_int64_t)v, endian);
}
break;
@@ -5492,7 +5685,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uint64_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uint64(&rdp->pack.ptr[rdp->pack.len], (hawk_uint64_t)v, endian);
}
break;
@@ -5505,7 +5699,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_intmax_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uintmax_t(&rdp->pack.ptr[rdp->pack.len], (hawk_intmax_t)v, endian);
}
break;
@@ -5517,7 +5712,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uintmax_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uintmax_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uintmax_t)v, endian);
}
break;
@@ -5529,7 +5725,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_intptr_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uintptr_t(&rdp->pack.ptr[rdp->pack.len], (hawk_intptr_t)v, endian);
}
break;
@@ -5541,7 +5738,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uintptr_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoint_inline(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoint_inline(rtx, tmp, &v) <= -1) goto oops_internal;
rdp->pack.len += pack_uintptr_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uintptr_t)v, endian);
}
break;
@@ -5557,7 +5755,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uint32_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoflt(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoflt(rtx, tmp, &v) <= -1) goto oops_internal;
x = (float)v;
HAWK_MEMCPY(&y, &x, HAWK_SIZEOF(y));
rdp->pack.len += pack_uint32(&rdp->pack.ptr[rdp->pack.len], y, endian);
@@ -5575,7 +5774,8 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
PACK_CHECK_ARG_AND_BUF(rep_cnt, HAWK_SIZEOF(hawk_uint64_t) * rep_cnt);
for (rc = 0; rc < rep_cnt; rc++)
{
if (hawk_rtx_valtoflt(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal;
hawk_val_t* tmp = hawk_rtx_getarg(rtx, arg_idx++);
if (hawk_rtx_valtoflt(rtx, tmp, &v) <= -1) goto oops_internal;
x = (double)v;
HAWK_MEMCPY(&y, &x, HAWK_SIZEOF(y));
rdp->pack.len += pack_uint64(&rdp->pack.ptr[rdp->pack.len], y, endian);
@@ -5849,7 +6049,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, (hawk_int8_t)*binp++);
hawk_int8_t tmp = (hawk_int8_t)*binp++;
v = hawk_rtx_makeintval_inline(rtx, tmp);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
@@ -5861,7 +6062,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, *binp++);
hawk_uint8_t tmp = *binp++;
v = hawk_rtx_makeintval_inline(rtx, tmp);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
@@ -5873,7 +6075,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int16_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_int16(binp, endian));
hawk_int16_t tmp = unpack_int16(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_int16_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5886,7 +6089,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint16_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_uint16(binp, endian));
hawk_uint16_t tmp = unpack_uint16(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_uint16_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5899,7 +6103,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int32_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_int32(binp, endian));
hawk_int32_t tmp = unpack_int32(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_int32_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5912,7 +6117,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint32_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_uint32(binp, endian));
hawk_uint32_t tmp = unpack_uint32(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_uint32_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5926,7 +6132,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int64_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_int64(binp, endian));
hawk_int64_t tmp = unpack_int64(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_int64_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5941,7 +6148,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint64_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_uint64(binp, endian));
hawk_uint64_t tmp = unpack_uint64(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_uint64_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5955,7 +6163,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_intmax_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_intmax(binp, endian));
hawk_intmax_t tmp = unpack_intmax(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_intmax_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5968,7 +6177,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uintmax_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_uintmax(binp, endian));
hawk_uintmax_t tmp = unpack_uintmax(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_uintmax_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5981,7 +6191,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_intptr_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_intptr(binp, endian));
hawk_intptr_t tmp = unpack_intptr(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_intptr_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -5994,7 +6205,8 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uintptr_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval_inline(rtx, unpack_uintptr(binp, endian));
hawk_uintptr_t tmp = unpack_uintptr(binp, endian);
v = hawk_rtx_makeintval_inline(rtx, tmp);
binp += HAWK_SIZEOF(hawk_uintptr_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
@@ -6302,6 +6514,7 @@ static hawk_mod_fnc_tab_t fnctab[] =
{ HAWK_T("tcgetattr"), { { 2, 2, HAWK_T("vr") }, fnc_tcgetattr, 0 } },
{ HAWK_T("tcsetattr"), { { 3, 3, HAWK_NULL }, fnc_tcsetattr, 0 } },
{ HAWK_T("tcsetraw"), { { 1, 1, HAWK_NULL }, fnc_tcsetraw, 0 } },
{ HAWK_T("tempname"), { { 0, 1, HAWK_NULL }, fnc_tempname, 0 } },
{ HAWK_T("uname"), { { 0, 0, HAWK_NULL }, fnc_uname, 0 } },
{ HAWK_T("unlink"), { { 1, 1, HAWK_NULL }, fnc_unlink, 0 } },
{ HAWK_T("unpack"), { { 2, A_MAX, HAWK_T("vvr") }, fnc_unpack, 0 } },
+3 -3
View File
@@ -28,8 +28,8 @@
enum hawk_assop_type_t
{
/* if you change this, you have to change assop_str in tree.c.
* synchronize it wit:
* - binop_func in eval_assignment of run.c
* synchronize it with:
* - operator dispatch in eval_assignment of run.c
* - assop in assing_to_opcode of parse.c
* - TOK_XXX_ASSN in tok_t in parse.c
* - assop_str in tree.c
@@ -53,7 +53,7 @@ enum hawk_assop_type_t
enum hawk_binop_type_t
{
/* if you change this, you have to change
* binop_str in tree.c and binop_func in run.c accordingly. */
* binop_str in tree.c and eval_binary in run.c accordingly. */
HAWK_BINOP_LOR,
HAWK_BINOP_LAND,
HAWK_BINOP_IN,
+310 -93
View File
@@ -221,9 +221,7 @@ static int read_record (hawk_rtx_t* rtx);
static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t* buf, hawk_oow_t* len, hawk_nde_t** remidx, hawk_int_t* firstidxint);
static hawk_ooi_t idxnde_to_int (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_nde_t** remidx);
typedef hawk_val_t* (*binop_func_t) (hawk_rtx_t* rtx, hawk_val_t* left, hawk_val_t* right);
typedef hawk_val_t* (*eval_expr_t) (hawk_rtx_t* rtx, hawk_nde_t* nde);
static binop_func_t get_binop_func (int opcode);
#define POS_VAL(rtx, idx) \
(((idx) == 0)? (rtx)->inrec.d0: \
@@ -1489,7 +1487,14 @@ static void fini_rtx (hawk_rtx_t* rtx, int fini_globals)
{
while (rtx->forin.size > 0)
{
hawk_rtx_refdownval_inline(rtx, rtx->forin.ptr[--rtx->forin.size]);
hawk_val_t* tmp;
/* assign it to a temporary first because hawk_rtx_refdownval_inline()
* could be a macro if the compiler doesn't have the inline support.
* in that case, the decrement operation can happen multiple time if
* rtx->forin.ptr[--rtx->forin.size] is passed as a parameter to
* hawk_rtx_refdownval_inline() */
tmp = rtx->forin.ptr[--rtx->forin.size];
hawk_rtx_refdownval_inline(rtx, tmp);
}
hawk_rtx_freemem(rtx, rtx->forin.ptr);
rtx->forin.ptr = HAWK_NULL;
@@ -2036,7 +2041,11 @@ static hawk_val_t* run_bpae_loop (hawk_rtx_t* rtx)
}
/* start the BEGIN-pattern block-END loop */
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
static HAWK_INLINE_ALWAYS hawk_val_t* rtx_loop (hawk_rtx_t* rtx)
#else
hawk_val_t* hawk_rtx_loop (hawk_rtx_t* rtx)
#endif
{
hawk_val_t* retv = HAWK_NULL;
hawk_oow_t saved_stack_top;
@@ -2082,6 +2091,24 @@ hawk_val_t* hawk_rtx_loop (hawk_rtx_t* rtx)
return retv;
}
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
hawk_val_t* hawk_rtx_loop (hawk_rtx_t* rtx)
{
hawk_val_t* v;
hawk_oow_t limit = rtx->cstack_limit;
/* cstack query at execution entry, not rtx creation: a host may move an idle rtx
* to another thread. never cache a failed query as an unlimited stack. */
if (hawk_rtx_entercstack(rtx) <= -1) return HAWK_NULL;
v = rtx_loop(rtx);
rtx->cstack_limit = limit;
return v;
}
#endif
hawk_val_t* hawk_rtx_execwithucstrarr (hawk_rtx_t* rtx, const hawk_uch_t* args[], hawk_oow_t nargs)
{
hawk_val_t* v;
@@ -2162,7 +2189,11 @@ hawk_fun_t* hawk_rtx_findfunwithucstr (hawk_rtx_t* rtx, const hawk_uch_t* name)
}
/* call an AWK function by the function structure */
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
static HAWK_INLINE_ALWAYS hawk_val_t* rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args[], hawk_oow_t nargs)
#else
hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args[], hawk_oow_t nargs)
#endif
{
struct capture_retval_data_t crdata;
hawk_val_t* v;
@@ -2299,6 +2330,23 @@ hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args
return v;
}
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args[], hawk_oow_t nargs)
{
hawk_val_t* v;
hawk_oow_t limit = rtx->cstack_limit;
/* cstack query at execution entry, not rtx creation: a host may move an idle rtx
* to another thread. never cache a failed query as an unlimited stack. */
if (hawk_rtx_entercstack(rtx) <= -1) return HAWK_NULL;
v = rtx_callfun(rtx, fun, args, nargs);
rtx->cstack_limit = limit;
return v;
}
#endif
/* call an AWK function by name */
hawk_val_t* hawk_rtx_callwithucstr (hawk_rtx_t* rtx, const hawk_uch_t* name, hawk_val_t* args[], hawk_oow_t nargs)
{
@@ -2343,7 +2391,13 @@ hawk_val_t* hawk_rtx_callwithucstrarr (hawk_rtx_t* rtx, const hawk_uch_t* name,
ret = hawk_rtx_callwithucstr(rtx, name, v, nargs);
oops:
while (i > 0) hawk_rtx_refdownval_inline(rtx, v[--i]);
while (i > 0)
{
hawk_val_t* tmp;
tmp = v[--i];
hawk_rtx_refdownval_inline(rtx, tmp);
}
hawk_rtx_freemem(rtx, v);
return ret;
}
@@ -2371,7 +2425,13 @@ hawk_val_t* hawk_rtx_callwithbcstrarr (hawk_rtx_t* rtx, const hawk_bch_t* name,
ret = hawk_rtx_callwithbcstr(rtx, name, v, nargs);
oops:
while (i > 0) hawk_rtx_refdownval_inline(rtx, v[--i]);
while (i > 0)
{
hawk_val_t* tmp;
tmp = v[--i];
hawk_rtx_refdownval_inline(rtx, tmp);
}
hawk_rtx_freemem(rtx, v);
return ret;
}
@@ -2399,7 +2459,13 @@ hawk_val_t* hawk_rtx_callwithooucstrarr (hawk_rtx_t* rtx, const hawk_ooch_t* nam
ret = hawk_rtx_callwithoocstr(rtx, name, v, nargs);
oops:
while (i > 0) hawk_rtx_refdownval_inline(rtx, v[--i]);
while (i > 0)
{
hawk_val_t* tmp;
tmp = v[--i];
hawk_rtx_refdownval_inline(rtx, tmp);
}
hawk_rtx_freemem(rtx, v);
return ret;
}
@@ -2427,7 +2493,13 @@ hawk_val_t* hawk_rtx_callwithoobcstrarr (hawk_rtx_t* rtx, const hawk_ooch_t* nam
ret = hawk_rtx_callwithoocstr(rtx, name, v, nargs);
oops:
while (i > 0) hawk_rtx_refdownval_inline(rtx, v[--i]);
while (i > 0)
{
hawk_val_t* tmp;
tmp = v[--i];
hawk_rtx_refdownval_inline(rtx, tmp);
}
hawk_rtx_freemem(rtx, v);
return ret;
}
@@ -2694,18 +2766,25 @@ static int run_block (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
{
int n;
if (rtx->hawk->opt.depth.s.block_run > 0 &&
rtx->depth.block >= rtx->hawk->opt.depth.s.block_run)
#if defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
if (HAWK_UNLIKELY(!HAWK_CSTACK_OK(rtx,n)))
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_EBLKNST,
"run-time block depth(%zu) reached limit(%zu)",
rtx->depth.block, rtx->hawk->opt.depth.s.block_run);
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_ESTACK, "native C stack limit reached in running a block");
return -1;
}
rtx->depth.block++;
n = run_block0(rtx, nde);
rtx->depth.block--;
#else
if (HAWK_UNLIKELY(rtx->hawk->opt.depth.s.recurs_run > 0 && rtx->depth.recurs >= rtx->hawk->opt.depth.s.recurs_run))
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_EBLKNST,
"run-time recursion depth(%zu) reached limit(%zu)",
rtx->depth.recurs, rtx->hawk->opt.depth.s.recurs_run);
return -1;
}
rtx->depth.recurs++;
n = run_block0(rtx, nde);
rtx->depth.recurs--;
#endif
return n;
}
@@ -3024,15 +3103,24 @@ static void leave_block_iterative (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
while (tmp > 0);
}
HAWK_ASSERT(rtx->depth.block > 0);
rtx->depth.block--;
#if !defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
HAWK_ASSERT(rtx->depth.recurs > 0);
rtx->depth.recurs--;
#endif
}
static void leave_forin_iterative (hawk_rtx_t* rtx, hawk_oow_t base)
{
while (rtx->forin.size > base)
{
hawk_rtx_refdownval_inline(rtx, rtx->forin.ptr[--rtx->forin.size]);
hawk_val_t* tmp;
/* assign it to a temporary first because hawk_rtx_refdownval_inline()
* could be a macro if the compiler doesn't have the inline support.
* in that case, the decrement operation can happen multiple time if
* rtx->forin.ptr[--rtx->forin.size] is passed as a parameter to
* hawk_rtx_refdownval_inline() */
tmp = rtx->forin.ptr[--rtx->forin.size];
hawk_rtx_refdownval_inline(rtx, tmp);
}
}
@@ -3056,16 +3144,18 @@ static void unwind_exec_stack (hawk_rtx_t* rtx, hawk_oow_t base)
static int enter_block_iterative (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
{
if (rtx->hawk->opt.depth.s.block_run > 0 &&
rtx->depth.block >= rtx->hawk->opt.depth.s.block_run)
#if !defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
if (rtx->hawk->opt.depth.s.recurs_run > 0 &&
rtx->depth.recurs >= rtx->hawk->opt.depth.s.recurs_run)
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_EBLKNST,
"run-time block depth(%zu) reached limit(%zu)",
rtx->depth.block, rtx->hawk->opt.depth.s.block_run);
"run-time recursion depth(%zu) reached limit(%zu)",
rtx->depth.recurs, rtx->hawk->opt.depth.s.recurs_run);
return -1;
}
rtx->depth.block++;
rtx->depth.recurs++;
#endif
if (nde->nlcls > 0)
{
@@ -3073,7 +3163,9 @@ static int enter_block_iterative (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < tmp))
{
rtx->depth.block--;
#if !defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
rtx->depth.recurs--;
#endif
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_ESTACK,
"stack full(avail=%zu, limit=%zu) for %zu local variables",
HAWK_RTX_STACK_AVAIL(rtx), rtx->stack_limit, tmp);
@@ -3270,6 +3362,12 @@ static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
hawk_oow_t base;
hawk_exec_stack_t es;
if (HAWK_UNLIKELY(!HAWK_CSTACK_OK(rtx,es)))
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_ESTACK, "native C stack limit reached in running a statement");
return -1;
}
HAWK_ASSERT(nde != HAWK_NULL);
base = rtx->exec_stack_size;
@@ -4811,6 +4909,18 @@ static hawk_val_t* eval_expression0 (hawk_rtx_t* rtx, hawk_nde_t* nde)
HAWK_ASSERT(nde->type >= HAWK_NDE_GRP && (nde->type - HAWK_NDE_GRP) < HAWK_COUNTOF(__evaluator));
#if !defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
if (HAWK_UNLIKELY(rtx->hawk->opt.depth.s.recurs_run > 0 && rtx->depth.recurs >= rtx->hawk->opt.depth.s.recurs_run))
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_EBLKNST,
"run-time recursion depth(%zu) reached limit(%zu)",
rtx->depth.recurs, rtx->hawk->opt.depth.s.recurs_run);
return HAWK_NULL;
}
rtx->depth.recurs++;
#endif
switch(nde->type)
{
#if !defined(KEEP_EVAL_FNCALL_FUN)
@@ -4894,10 +5004,22 @@ static hawk_val_t* eval_expression0 (hawk_rtx_t* rtx, hawk_nde_t* nde)
case HAWK_NDE_GBLIDX:
case HAWK_NDE_LCLIDX:
case HAWK_NDE_NAMEDIDX:
if (HAWK_UNLIKELY(!HAWK_CSTACK_OK(rtx,v)))
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_ESTACK, "native C stack limit reached in evaluating an indexed expression");
goto oops;
}
v = eval_indexed(rtx, (hawk_nde_var_t*)nde);
break;
default:
/* leaf loads above cannot recurse. check before descending into
* an evaluator; direct user calls are checked in rtx_evalcall. */
if (HAWK_UNLIKELY(!HAWK_CSTACK_OK(rtx,v)))
{
hawk_rtx_seterrbfmt(rtx, &nde->loc, HAWK_ESTACK, "native C stack limit reached in evaluating an expression");
goto oops;
}
v = __evaluator[nde->type - HAWK_NDE_GRP](rtx, nde);
break;
}
@@ -4918,9 +5040,15 @@ static hawk_val_t* eval_expression0 (hawk_rtx_t* rtx, hawk_nde_t* nde)
done:
/* this function returns a regular expression without further mathiching.
* it is done in eval_expression(). */
#if !defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
rtx->depth.recurs--;
#endif
return v;
oops:
#if !defined(HAWK_HAVE_NATIVE_CSTACK_BOUNDS)
rtx->depth.recurs--;
#endif
ADJERR_LOC(rtx, &nde->loc);
return HAWK_NULL;
}
@@ -4984,24 +5112,6 @@ static hawk_val_t* eval_assignment (hawk_rtx_t* rtx, hawk_nde_t* nde)
if (ass->opcode != HAWK_ASSOP_NONE)
{
hawk_val_t* val2, * tmp;
static binop_func_t binop_func[] =
{
/* this table must match hawk_assop_type_t in rtx.h */
HAWK_NULL, /* HAWK_ASSOP_NONE */
eval_binop_plus,
eval_binop_minus,
eval_binop_mul,
eval_binop_div,
eval_binop_idiv,
eval_binop_mod,
eval_binop_exp,
eval_binop_concat,
eval_binop_rshift,
eval_binop_lshift,
eval_binop_band,
eval_binop_bxor,
eval_binop_bor
};
HAWK_ASSERT(ass->left->next == HAWK_NULL);
val2 = eval_expression(rtx, ass->left);
@@ -5013,11 +5123,66 @@ static hawk_val_t* eval_assignment (hawk_rtx_t* rtx, hawk_nde_t* nde)
hawk_rtx_refupval_inline(rtx, val2);
HAWK_ASSERT(ass->opcode >= 0);
HAWK_ASSERT(ass->opcode < HAWK_COUNTOF(binop_func));
HAWK_ASSERT(binop_func[ass->opcode] != HAWK_NULL);
switch (ass->opcode)
{
case HAWK_ASSOP_PLUS:
tmp = eval_binop_plus(rtx, val2, val);
break;
tmp = binop_func[ass->opcode](rtx, val2, val);
case HAWK_ASSOP_MINUS:
tmp = eval_binop_minus(rtx, val2, val);
break;
case HAWK_ASSOP_MUL:
tmp = eval_binop_mul(rtx, val2, val);
break;
case HAWK_ASSOP_DIV:
tmp = eval_binop_div(rtx, val2, val);
break;
case HAWK_ASSOP_IDIV:
tmp = eval_binop_idiv(rtx, val2, val);
break;
case HAWK_ASSOP_MOD:
tmp = eval_binop_mod(rtx, val2, val);
break;
case HAWK_ASSOP_EXP:
tmp = eval_binop_exp(rtx, val2, val);
break;
case HAWK_ASSOP_CONCAT:
tmp = eval_binop_concat(rtx, val2, val);
break;
case HAWK_ASSOP_RS:
tmp = eval_binop_rshift(rtx, val2, val);
break;
case HAWK_ASSOP_LS:
tmp = eval_binop_lshift(rtx, val2, val);
break;
case HAWK_ASSOP_BAND:
tmp = eval_binop_band(rtx, val2, val);
break;
case HAWK_ASSOP_BXOR:
tmp = eval_binop_bxor(rtx, val2, val);
break;
case HAWK_ASSOP_BOR:
tmp = eval_binop_bor(rtx, val2, val);
break;
default:
HAWK_ASSERT(!"invalid assignment operator");
hawk_rtx_seterrnum(rtx, &nde->loc, HAWK_EINTERN);
tmp = HAWK_NULL;
break;
}
if (HAWK_UNLIKELY(!tmp))
{
hawk_rtx_refdownval_inline(rtx, val2);
@@ -5471,50 +5636,6 @@ static hawk_val_t* do_assignment_positional (hawk_rtx_t* rtx, hawk_nde_pos_t* po
return (lv == 0)? rtx->inrec.d0: rtx->inrec.flds[lv-1].val;
}
static binop_func_t get_binop_func (int opcode)
{
static binop_func_t binop_func[] =
{
/* the order of the functions should be inline with
* the operator declaration in rtx.h */
HAWK_NULL, /* eval_binop_lor */
HAWK_NULL, /* eval_binop_land */
HAWK_NULL, /* eval_binop_in */
eval_binop_bor,
eval_binop_bxor,
eval_binop_band,
eval_binop_teq,
eval_binop_tne,
eval_binop_eq,
eval_binop_ne,
eval_binop_gt,
eval_binop_ge,
eval_binop_lt,
eval_binop_le,
eval_binop_lshift,
eval_binop_rshift,
eval_binop_plus,
eval_binop_minus,
eval_binop_mul,
eval_binop_div,
eval_binop_idiv,
eval_binop_mod,
eval_binop_exp,
eval_binop_concat,
HAWK_NULL, /* eval_binop_ma */
HAWK_NULL /* eval_binop_nm */
};
HAWK_ASSERT(opcode >= 0 && opcode < HAWK_COUNTOF(binop_func));
return binop_func[opcode];
}
static hawk_val_t* eval_binary (hawk_rtx_t* rtx, hawk_nde_t* nde)
{
hawk_nde_exp_t* exp = (hawk_nde_exp_t*)nde;
@@ -5562,8 +5683,98 @@ static hawk_val_t* eval_binary (hawk_rtx_t* rtx, hawk_nde_t* nde)
hawk_rtx_refupval_inline(rtx, right);
HAWK_ASSERT(get_binop_func(exp->opcode) != HAWK_NULL);
res = get_binop_func(exp->opcode)(rtx, left, right);
switch (exp->opcode)
{
case HAWK_BINOP_BOR:
res = eval_binop_bor(rtx, left, right);
break;
case HAWK_BINOP_BXOR:
res = eval_binop_bxor(rtx, left, right);
break;
case HAWK_BINOP_BAND:
res = eval_binop_band(rtx, left, right);
break;
case HAWK_BINOP_TEQ:
res = eval_binop_teq(rtx, left, right);
break;
case HAWK_BINOP_TNE:
res = eval_binop_tne(rtx, left, right);
break;
case HAWK_BINOP_EQ:
res = eval_binop_eq(rtx, left, right);
break;
case HAWK_BINOP_NE:
res = eval_binop_ne(rtx, left, right);
break;
case HAWK_BINOP_GT:
res = eval_binop_gt(rtx, left, right);
break;
case HAWK_BINOP_GE:
res = eval_binop_ge(rtx, left, right);
break;
case HAWK_BINOP_LT:
res = eval_binop_lt(rtx, left, right);
break;
case HAWK_BINOP_LE:
res = eval_binop_le(rtx, left, right);
break;
case HAWK_BINOP_LS:
res = eval_binop_lshift(rtx, left, right);
break;
case HAWK_BINOP_RS:
res = eval_binop_rshift(rtx, left, right);
break;
case HAWK_BINOP_PLUS:
res = eval_binop_plus(rtx, left, right);
break;
case HAWK_BINOP_MINUS:
res = eval_binop_minus(rtx, left, right);
break;
case HAWK_BINOP_MUL:
res = eval_binop_mul(rtx, left, right);
break;
case HAWK_BINOP_DIV:
res = eval_binop_div(rtx, left, right);
break;
case HAWK_BINOP_IDIV:
res = eval_binop_idiv(rtx, left, right);
break;
case HAWK_BINOP_MOD:
res = eval_binop_mod(rtx, left, right);
break;
case HAWK_BINOP_EXP:
res = eval_binop_exp(rtx, left, right);
break;
case HAWK_BINOP_CONCAT:
res = eval_binop_concat(rtx, left, right);
break;
default:
HAWK_ASSERT(!"invalid binary operator");
hawk_rtx_seterrnum(rtx, &nde->loc, HAWK_EINTERN);
res = HAWK_NULL;
break;
}
if (HAWK_UNLIKELY(!res)) ADJERR_LOC(rtx, &nde->loc);
hawk_rtx_refdownval_inline(rtx, left);
@@ -7540,7 +7751,7 @@ static hawk_val_t* eval_binop_concat (hawk_rtx_t* rtx, hawk_val_t* left, hawk_va
return res;
}
static hawk_val_t* eval_binop_match0 (
static HAWK_INLINE_ALWAYS hawk_val_t* eval_binop_match0 (
hawk_rtx_t* rtx, hawk_val_t* left, hawk_val_t* right,
const hawk_loc_t* lloc, const hawk_loc_t* rloc, int ret)
{
@@ -8254,6 +8465,12 @@ hawk_val_t* hawk_rtx_evalcall (
hawk_val_t* v;
int n;
if (HAWK_UNLIKELY(!HAWK_CSTACK_OK(rtx,n)))
{
hawk_rtx_seterrbfmt(rtx, &call->loc, HAWK_ESTACK, "native C stack limit reached in calling a function");
return HAWK_NULL;
}
/*
* ---------------------
* lcln <- stack top
+9 -6
View File
@@ -69,6 +69,7 @@
# if defined(HAVE_CRT_EXTERNS_H)
# include <crt_externs.h> /* MacOSX/darwin. _NSGetEnviron() */
# endif
#endif
#if !defined(HAWK_HAVE_CFG_H)
@@ -313,6 +314,8 @@ hawk_flt_t hawk_stdmathmod (hawk_t* hawk, hawk_flt_t x, hawk_flt_t y)
#endif
}
/* ----------------------------------------------------------------------- */
/* [IMPORTANT]
* hawk_stdmodXXXX() functions must not access the extension
* area of 'hawk'. they are used in StdAwk.cpp which instantiates
@@ -702,9 +705,9 @@ static HAWK_INLINE void reset_log_to_default (xtn_t* xtn)
#if defined(EMSCRIPTEN)
EM_JS(int, write_all, (int, const hawk_bch_t* ptr, hawk_oow_t len), {
// UTF8ToString() doesn't handle a null byte in the middle of an array.
// Use the heap memory and pass the right portion to UTF8Decoder.
//console.log ("%s", UTF8ToString(ptr, len));
/* UTF8ToString() doesn't handle a null byte in the middle of an array.
* Use the heap memory and pass the right portion to UTF8Decoder. */
/*console.log ("%s", UTF8ToString(ptr, len));*/
console.log ("%s", UTF8Decoder.decode(HEAPU8.subarray(ptr, ptr + len)));
return 0;
});
@@ -715,9 +718,9 @@ static int write_all (int fd, const hawk_bch_t* ptr, hawk_oow_t len)
{
#if defined(EMSCRIPTEN)
EM_ASM_ ({
// UTF8ToString() doesn't handle a null byte in the middle of an array.
// Use the heap memory and pass the right portion to UTF8Decoder.
//console.log ("%s", UTF8ToString($0, $1));
/* UTF8ToString() doesn't handle a null byte in the middle of an array.
* Use the heap memory and pass the right portion to UTF8Decoder.*/
/*console.log ("%s", UTF8ToString($0, $1));*/
console.log ("%s", UTF8Decoder.decode(HEAPU8.subarray($0, $0 + $1)));
}, ptr, len);
#else
+27 -19
View File
@@ -200,7 +200,7 @@ static HAWK_INLINE_ALWAYS hawk_val_t* hawk_rtx_makeintval_inline (hawk_rtx_t* rt
return HAWK_IN_INT_RANGE(v)? HAWK_INT_TO_VTR(v): hawk_rtx_makeintval_full(rtx, v);
}
#else
#define hawk_rtx_makeintval_inline(rtx, v) (HAWK_IN_INT_RANGE(v)? HAWK_INT_TO_VTR(v): hawk_rtx_makeintval_full(rtx, v))
#define hawk_rtx_makeintval_inline(rtx, v) hawk_rtx_makeintval(rtx, v)
#endif
void hawk_rtx_freeval (
@@ -228,13 +228,15 @@ static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_inline (hawk_rtx_t* rtx, hawk_v
}
#elif defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_ADD)
#define hawk_rtx_refupval_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) { \
HAWK_ATOMIC_FETCH_ADD(&(val)->v_refs, 1, HAWK_ATOMIC_RELAXED); \
hawk_val_t* _hawk_vtmp_ = (val); \
if (HAWK_VTR_IS_POINTER(_hawk_vtmp_) && !HAWK_IS_STATICVAL(_hawk_vtmp_)) { \
HAWK_ATOMIC_FETCH_ADD(&_hawk_vtmp_->v_refs, 1, HAWK_ATOMIC_RELAXED); \
} \
} while(0)
#else
#define hawk_rtx_refupval_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) (val)->v_refs++; \
hawk_val_t* _hawk_vtmp_ = (val); \
if (HAWK_VTR_IS_POINTER(_hawk_vtmp_) && !HAWK_IS_STATICVAL(_hawk_vtmp_)) _hawk_vtmp_->v_refs++; \
} while(0)
#endif
@@ -255,20 +257,24 @@ static HAWK_INLINE_ALWAYS void hawk_rtx_refdownval_inline (hawk_rtx_t* rtx, hawk
}
#elif defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_SUB)
#define hawk_rtx_refdownval_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) \
hawk_rtx_t* _hawk_rtmp_ = (rtx); \
hawk_val_t* _hawk_vtmp_ = (val); \
if (HAWK_VTR_IS_POINTER(_hawk_vtmp_) && !HAWK_IS_STATICVAL(_hawk_vtmp_)) \
{ \
HAWK_ASSERT(((hawk_val_t*)(val))->v_refs > 0); \
if (HAWK_ATOMIC_FETCH_SUB(&((hawk_val_t*)(val))->v_refs, 1, HAWK_ATOMIC_RELAXED) == 1) \
hawk_rtx_freeval(rtx, val, HAWK_RTX_FREEVAL_CACHE); \
HAWK_ASSERT(_hawk_vtmp_->v_refs > 0); \
if (HAWK_ATOMIC_FETCH_SUB(&_hawk_vtmp_->v_refs, 1, HAWK_ATOMIC_RELAXED) == 1) \
hawk_rtx_freeval(_hawk_rtmp_, _hawk_vtmp_, HAWK_RTX_FREEVAL_CACHE); \
} \
} while(0)
#else
#define hawk_rtx_refdownval_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) \
hawk_rtx_t* _hawk_rtmp_ = (rtx); \
hawk_val_t* _hawk_vtmp_ = (val); \
if (HAWK_VTR_IS_POINTER(_hawk_vtmp_) && !HAWK_IS_STATICVAL(_hawk_vtmp_)) \
{ \
HAWK_ASSERT(((hawk_val_t*)(val))->v_refs > 0); \
((hawk_val_t*)(val))->v_refs--; \
if (((hawk_val_t*)(val))->v_refs <= 0) hawk_rtx_freeval(rtx, val, HAWK_RTX_FREEVAL_CACHE); \
HAWK_ASSERT(_hawk_vtmp_->v_refs > 0); \
_hawk_vtmp_->v_refs--; \
if (_hawk_vtmp_->v_refs <= 0) hawk_rtx_freeval(_hawk_rtmp_, _hawk_vtmp_, HAWK_RTX_FREEVAL_CACHE); \
} \
} while(0)
#endif
@@ -288,18 +294,20 @@ static HAWK_INLINE_ALWAYS void hawk_rtx_refdownval_nofree_inline (hawk_rtx_t* rt
}
#elif defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_SUB)
#define hawk_rtx_refdownval_nofree_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) \
hawk_val_t* _hawk_vtmp_ = (val); \
if (HAWK_VTR_IS_POINTER(_hawk_vtmp_) && !HAWK_IS_STATICVAL(_hawk_vtmp_)) \
{ \
HAWK_ASSERT(((hawk_val_t*)(val))->v_refs > 0); \
HAWK_ATOMIC_FETCH_SUB(&((hawk_val_t*)(val))->v_refs, 1, HAWK_ATOMIC_RELAXED);
HAWK_ASSERT(_hawk_vtmp_->v_refs > 0); \
HAWK_ATOMIC_FETCH_SUB(&_hawk_vtmp_->v_refs, 1, HAWK_ATOMIC_RELAXED); \
} \
} while(0)
#else
#define hawk_rtx_refdownval_nofree_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) \
hawk_val_t* _hawk_vtmp_ = (val); \
if (HAWK_VTR_IS_POINTER(_hawk_vtmp_) && !HAWK_IS_STATICVAL(_hawk_vtmp_)) \
{ \
HAWK_ASSERT(((hawk_val_t*)(val))->v_refs > 0); \
((hawk_val_t*)(val))->v_refs--; \
HAWK_ASSERT(_hawk_vtmp_->v_refs > 0); \
_hawk_vtmp_->v_refs--; \
} \
} while(0)
#endif
@@ -318,7 +326,7 @@ static HAWK_INLINE int hawk_rtx_valtoint_inline (hawk_rtx_t* rtx, const hawk_val
return n;
}
#else
/* i can't easily inlinde this function without using compiler extentions or changing the return value to a parameter */
/* i can't easily inline this function without using compiler extentions or changing the return value to a parameter */
#define hawk_rtx_valtoint_inline(rtx, v, l) hawk_rtx_valtoint(rtx, v, l)
#endif
+2 -1
View File
@@ -583,7 +583,8 @@ hawk_val_t* hawk_rtx_makeintval_full (hawk_rtx_t* rtx, hawk_int_t v)
{
hawk_val_int_t* val;
if (HAWK_IN_INT_RANGE(v)) return HAWK_INT_TO_VTR(v);
HAWK_ASSERT(!HAWK_IN_INT_RANGE(v));
/*if (HAWK_IN_INT_RANGE(v)) return HAWK_INT_TO_VTR(v);*/
if (!rtx->vmgr.ifree)
{
+3
View File
@@ -261,6 +261,9 @@ rm -rf "%{buildroot}"
%defattr(-,root,root)
%{_includedir}/*
%{_libdir}/libhawk.so
%{_datadir}/hawk/go/hawk.go
%{_datadir}/hawk/go/hawk-inst.go
%{_datadir}/hawk/go/go.mod
%files static
%defattr(-,root,root)
+9 -2
View File
@@ -20,7 +20,7 @@ endif
check_SCRIPTS += h-003.hawk h-004.hawk h-009.hawk h-010.hawk \
h-011.hawk h-012.hawk h-013.hawk h-014.hawk h-015.hawk \
h-016.hawk h-017.hawk h-018.hawk h-019.hawk h-020.hawk \
h-021.hawk h-022.hawk h-023.hawk h-024.hawk h-025.hawk
h-021.hawk h-022.hawk h-023.hawk h-024.hawk h-025.hawk h-026.hawk h-027.hawk
check_SCRIPTS += regress-filename.sh regress-extra-info.sh regress-environ.sh
@@ -28,6 +28,7 @@ check_ERRORS = e-001.err
##noinst_SCRIPTS = $(check_SCRIPTS)
EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
bench-map-keys.hawk bench-int-comparisons.hawk \
journal-toc.hawk journal-toc.in journal-toc.out journal-toc-html.out \
bibtex-to-html.hawk bibtex-to-html.out \
fs-test.hawk fs-test.in fs-test.out \
@@ -36,7 +37,7 @@ EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
run-hawk-test.sh regress-extra-info.sh \
two-way-pipe.hawk two-way-pipe.out
check_PROGRAMS = t-001 t-002 t-003 t-004 t-005 t-006 t-007 t-008 t-009 t-010
check_PROGRAMS = t-001 t-002 t-003 t-004 t-005 t-006 t-007 t-008 t-009 t-010 t-011
if ENABLE_CXX
check_PROGRAMS += t-101
@@ -99,6 +100,12 @@ t_010_CFLAGS = $(CFLAGS_COMMON)
t_010_LDFLAGS = $(LDFLAGS_COMMON)
t_010_LDADD = $(LIBADD_COMMON)
t_011_SOURCES = t-011.c tap.h
t_011_CPPFLAGS = $(CPPFLAGS_COMMON)
t_011_CFLAGS = $(CFLAGS_COMMON)
t_011_LDFLAGS = $(LDFLAGS_COMMON)
t_011_LDADD = $(LIBADD_COMMON)
if ENABLE_CXX
t_101_SOURCES = t-101.cpp tap.h
t_101_CPPFLAGS = $(CPPFLAGS_COMMON)
+48 -6
View File
@@ -92,7 +92,8 @@ host_triplet = @host@
@ENABLE_WIDE_CHAR_TRUE@am__append_1 = h-001.hawk h-002.hawk
check_PROGRAMS = t-001$(EXEEXT) t-002$(EXEEXT) t-003$(EXEEXT) \
t-004$(EXEEXT) t-005$(EXEEXT) t-006$(EXEEXT) t-007$(EXEEXT) \
t-008$(EXEEXT) t-009$(EXEEXT) t-010$(EXEEXT) $(am__EXEEXT_1)
t-008$(EXEEXT) t-009$(EXEEXT) t-010$(EXEEXT) t-011$(EXEEXT) \
$(am__EXEEXT_1)
@ENABLE_CXX_TRUE@am__append_2 = t-101
subdir = t
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -176,6 +177,12 @@ t_010_DEPENDENCIES = $(am__DEPENDENCIES_2)
t_010_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_010_CFLAGS) $(CFLAGS) \
$(t_010_LDFLAGS) $(LDFLAGS) -o $@
am_t_011_OBJECTS = t_011-t-011.$(OBJEXT)
t_011_OBJECTS = $(am_t_011_OBJECTS)
t_011_DEPENDENCIES = $(am__DEPENDENCIES_2)
t_011_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_011_CFLAGS) $(CFLAGS) \
$(t_011_LDFLAGS) $(LDFLAGS) -o $@
am__t_101_SOURCES_DIST = t-101.cpp tap.h
@ENABLE_CXX_TRUE@am_t_101_OBJECTS = t_101-t-101.$(OBJEXT)
t_101_OBJECTS = $(am_t_101_OBJECTS)
@@ -203,7 +210,8 @@ am__depfiles_remade = ./$(DEPDIR)/t_001-t-001.Po \
./$(DEPDIR)/t_004-t-004.Po ./$(DEPDIR)/t_005-t-005.Po \
./$(DEPDIR)/t_006-t-006.Po ./$(DEPDIR)/t_007-t-007.Po \
./$(DEPDIR)/t_008-t-008.Po ./$(DEPDIR)/t_009-t-009.Po \
./$(DEPDIR)/t_010-t-010.Po ./$(DEPDIR)/t_101-t-101.Po
./$(DEPDIR)/t_010-t-010.Po ./$(DEPDIR)/t_011-t-011.Po \
./$(DEPDIR)/t_101-t-101.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -244,11 +252,11 @@ am__v_CXXLD_1 =
SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) $(t_003_SOURCES) \
$(t_004_SOURCES) $(t_005_SOURCES) $(t_006_SOURCES) \
$(t_007_SOURCES) $(t_008_SOURCES) $(t_009_SOURCES) \
$(t_010_SOURCES) $(t_101_SOURCES)
$(t_010_SOURCES) $(t_011_SOURCES) $(t_101_SOURCES)
DIST_SOURCES = $(t_001_SOURCES) $(t_002_SOURCES) $(t_003_SOURCES) \
$(t_004_SOURCES) $(t_005_SOURCES) $(t_006_SOURCES) \
$(t_007_SOURCES) $(t_008_SOURCES) $(t_009_SOURCES) \
$(t_010_SOURCES) $(am__t_101_SOURCES_DIST)
$(t_010_SOURCES) $(t_011_SOURCES) $(am__t_101_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -659,10 +667,11 @@ check_SCRIPTS = $(am__append_1) h-003.hawk h-004.hawk h-009.hawk \
h-010.hawk h-011.hawk h-012.hawk h-013.hawk h-014.hawk \
h-015.hawk h-016.hawk h-017.hawk h-018.hawk h-019.hawk \
h-020.hawk h-021.hawk h-022.hawk h-023.hawk h-024.hawk \
h-025.hawk regress-filename.sh regress-extra-info.sh \
regress-environ.sh
h-025.hawk h-026.hawk h-027.hawk regress-filename.sh \
regress-extra-info.sh regress-environ.sh
check_ERRORS = e-001.err
EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
bench-map-keys.hawk bench-int-comparisons.hawk \
journal-toc.hawk journal-toc.in journal-toc.out journal-toc-html.out \
bibtex-to-html.hawk bibtex-to-html.out \
fs-test.hawk fs-test.in fs-test.out \
@@ -718,6 +727,11 @@ t_010_CPPFLAGS = $(CPPFLAGS_COMMON)
t_010_CFLAGS = $(CFLAGS_COMMON)
t_010_LDFLAGS = $(LDFLAGS_COMMON)
t_010_LDADD = $(LIBADD_COMMON)
t_011_SOURCES = t-011.c tap.h
t_011_CPPFLAGS = $(CPPFLAGS_COMMON)
t_011_CFLAGS = $(CFLAGS_COMMON)
t_011_LDFLAGS = $(LDFLAGS_COMMON)
t_011_LDADD = $(LIBADD_COMMON)
@ENABLE_CXX_TRUE@t_101_SOURCES = t-101.cpp tap.h
@ENABLE_CXX_TRUE@t_101_CPPFLAGS = $(CPPFLAGS_COMMON)
@ENABLE_CXX_TRUE@t_101_CFLAGS = $(CFLAGS_COMMON)
@@ -820,6 +834,10 @@ t-010$(EXEEXT): $(t_010_OBJECTS) $(t_010_DEPENDENCIES) $(EXTRA_t_010_DEPENDENCIE
@rm -f t-010$(EXEEXT)
$(AM_V_CCLD)$(t_010_LINK) $(t_010_OBJECTS) $(t_010_LDADD) $(LIBS)
t-011$(EXEEXT): $(t_011_OBJECTS) $(t_011_DEPENDENCIES) $(EXTRA_t_011_DEPENDENCIES)
@rm -f t-011$(EXEEXT)
$(AM_V_CCLD)$(t_011_LINK) $(t_011_OBJECTS) $(t_011_LDADD) $(LIBS)
t-101$(EXEEXT): $(t_101_OBJECTS) $(t_101_DEPENDENCIES) $(EXTRA_t_101_DEPENDENCIES)
@rm -f t-101$(EXEEXT)
$(AM_V_CXXLD)$(t_101_LINK) $(t_101_OBJECTS) $(t_101_LDADD) $(LIBS)
@@ -840,6 +858,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_008-t-008.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_009-t-009.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_010-t-010.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_011-t-011.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_101-t-101.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@@ -1012,6 +1031,20 @@ t_010-t-010.obj: t-010.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_010_CPPFLAGS) $(CPPFLAGS) $(t_010_CFLAGS) $(CFLAGS) -c -o t_010-t-010.obj `if test -f 't-010.c'; then $(CYGPATH_W) 't-010.c'; else $(CYGPATH_W) '$(srcdir)/t-010.c'; fi`
t_011-t-011.o: t-011.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_011_CPPFLAGS) $(CPPFLAGS) $(t_011_CFLAGS) $(CFLAGS) -MT t_011-t-011.o -MD -MP -MF $(DEPDIR)/t_011-t-011.Tpo -c -o t_011-t-011.o `test -f 't-011.c' || echo '$(srcdir)/'`t-011.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_011-t-011.Tpo $(DEPDIR)/t_011-t-011.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-011.c' object='t_011-t-011.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_011_CPPFLAGS) $(CPPFLAGS) $(t_011_CFLAGS) $(CFLAGS) -c -o t_011-t-011.o `test -f 't-011.c' || echo '$(srcdir)/'`t-011.c
t_011-t-011.obj: t-011.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_011_CPPFLAGS) $(CPPFLAGS) $(t_011_CFLAGS) $(CFLAGS) -MT t_011-t-011.obj -MD -MP -MF $(DEPDIR)/t_011-t-011.Tpo -c -o t_011-t-011.obj `if test -f 't-011.c'; then $(CYGPATH_W) 't-011.c'; else $(CYGPATH_W) '$(srcdir)/t-011.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_011-t-011.Tpo $(DEPDIR)/t_011-t-011.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-011.c' object='t_011-t-011.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_011_CPPFLAGS) $(CPPFLAGS) $(t_011_CFLAGS) $(CFLAGS) -c -o t_011-t-011.obj `if test -f 't-011.c'; then $(CYGPATH_W) 't-011.c'; else $(CYGPATH_W) '$(srcdir)/t-011.c'; fi`
.cpp.o:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@@ -1344,6 +1377,13 @@ t-010.log: t-010$(EXEEXT)
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
t-011.log: t-011$(EXEEXT)
@p='t-011$(EXEEXT)'; \
b='t-011'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
t-101.log: t-101$(EXEEXT)
@p='t-101$(EXEEXT)'; \
b='t-101'; \
@@ -1482,6 +1522,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t_008-t-008.Po
-rm -f ./$(DEPDIR)/t_009-t-009.Po
-rm -f ./$(DEPDIR)/t_010-t-010.Po
-rm -f ./$(DEPDIR)/t_011-t-011.Po
-rm -f ./$(DEPDIR)/t_101-t-101.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
@@ -1538,6 +1579,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t_008-t-008.Po
-rm -f ./$(DEPDIR)/t_009-t-009.Po
-rm -f ./$(DEPDIR)/t_010-t-010.Po
-rm -f ./$(DEPDIR)/t_011-t-011.Po
-rm -f ./$(DEPDIR)/t_101-t-101.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
+6
View File
@@ -0,0 +1,6 @@
BEGIN {
for (i = 0; i < 2000000; i++) {
s += (i > 30) + (i < 300) + (i == 200) + (i != 300);
}
print s;
}
+8
View File
@@ -0,0 +1,8 @@
BEGIN {
m["key"] = 7;
m["other"] = 11;
for (i = 0; i < 2000000; i++) {
s += m["key"] + m["other"];
}
print s;
}
+11 -8
View File
@@ -30,24 +30,27 @@ function test_print_bytecode()
{
@local line;
@local rc;
@local path;
sys::unlink("/tmp/hawk-fbc-print.tmp");
path = sys::tempname("hawk-fbc-print-");
tap_ensure(path != "", 1, @SCRIPTNAME, @SCRIPTLINE);
if (path == "") return;
OFS = ",";
print 1, (OFS = ":"), 3 > "/tmp/hawk-fbc-print.tmp";
print "" >> "/tmp/hawk-fbc-print.tmp";
close("/tmp/hawk-fbc-print.tmp");
print 1, (OFS = ":"), 3 > path;
print "" >> path;
close(path);
rc = (getline line < "/tmp/hawk-fbc-print.tmp");
rc = (getline line < path);
tap_ensure(rc, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(line, "1,::3", @SCRIPTNAME, @SCRIPTLINE);
rc = (getline line < "/tmp/hawk-fbc-print.tmp");
rc = (getline line < path);
tap_ensure(rc, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(line, "", @SCRIPTNAME, @SCRIPTLINE);
close("/tmp/hawk-fbc-print.tmp");
sys::unlink("/tmp/hawk-fbc-print.tmp");
close(path);
sys::unlink(path);
}
function test_unary_bytecode()
+8 -4
View File
@@ -48,16 +48,21 @@ function run_test (x, more_opts, in_name, set_out_name, out_name)
inf = sprintf("%s/%s.in", TDIR, in_name);
expf = sprintf("%s/%s.out", TDIR, out_name);
outf = sprintf("/tmp/%s.%d.out", out_name, sys::getpid());
outf = sys::tempname(out_name "-");
if (outf == "")
{
tap_fail(sprintf("%s[%d] %s - unable to create a temporary file - %s", @SCRIPTNAME, @SCRIPTLINE, x, sys::errmsg()));
return;
}
##print TDIR, inf, expf, outf;
if (set_out_name)
{
cmd=sprintf("%s %s -vT_OUT_NAME=%s -f %s/%s.hawk --modlibdirs=%s %s", ARGV[0], more_opts, outf, TDIR, x, hawk::modlibdirs(), inf);
cmd=sprintf("%s %s -vT_OUT_NAME=\"%s\" -f %s/%s.hawk --modlibdirs=%s %s", ARGV[0], more_opts, outf, TDIR, x, hawk::modlibdirs(), inf);
}
else
{
cmd=sprintf("%s %s -f %s/%s.hawk --modlibdirs=%s %s > %s", ARGV[0], more_opts, TDIR, x, hawk::modlibdirs(), inf, outf);
cmd=sprintf("%s %s -f %s/%s.hawk --modlibdirs=%s %s > \"%s\"", ARGV[0], more_opts, TDIR, x, hawk::modlibdirs(), inf, outf);
}
##print cmd;
system(cmd);
@@ -104,4 +109,3 @@ function main()
run_github_step_JSON_awk();
tap_end();
}
+46 -2
View File
@@ -21,8 +21,13 @@ function run_pipe_test(label, prog, expect)
{
@local out, cmd, data;
out = sprintf("/tmp/hawk-pipecloexec-%s-%d.log", label, sys::getpid());
cmd = sprintf("%s '%s' 3>%s 2>/dev/null", ARGV[0], prog, out);
out = sys::tempname("hawk-pipecloexec-" label "-");
if (out == "")
{
tap_fail(sprintf("%s[%d] %s - unable to create a temporary file - %s", @SCRIPTNAME, @SCRIPTLINE, label, sys::errmsg()));
return;
}
cmd = sprintf("%s '%s' 3>\"%s\" 2>/dev/null", ARGV[0], prog, out);
system(cmd);
data = read_file(out);
@@ -40,12 +45,51 @@ function run_pipe_test(label, prog, expect)
sys::unlink(out);
}
function test_tempname()
{
@local p1, p2, bad, line, rc;
p1 = sys::tempname();
tap_ensure(p1 != "", 1, @SCRIPTNAME, @SCRIPTLINE);
if (p1 == "") return;
p2 = sys::tempname("hawk-tempname-test-");
tap_ensure(p2 != "", 1, @SCRIPTNAME, @SCRIPTLINE);
if (p2 == "")
{
sys::unlink(p1);
return;
}
tap_ensure(p1 != p2, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(sys::basename(p2) ~ /^hawk-tempname-test-/, 1, @SCRIPTNAME, @SCRIPTLINE);
rc = (getline line < p1);
close(p1);
tap_ensure(rc, 0, @SCRIPTNAME, @SCRIPTLINE);
print "temporary data" > p1;
close(p1);
rc = (getline line < p1);
close(p1);
tap_ensure(rc, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(line, "temporary data", @SCRIPTNAME, @SCRIPTLINE);
bad = sys::tempname("invalid/prefix");
tap_ensure(bad, "", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(sys::errmsg() != "", 1, @SCRIPTNAME, @SCRIPTLINE);
sys::unlink(p1);
sys::unlink(p2);
}
function main()
{
## if PIPCLOEXEC is turned on, the file descriptor created by the shell (3> in run_pipe_test)
## doesn't get inherited to the 'cat' commands in the following text
@local uname;
test_tempname();
uname = sys::uname()
if (uname["sysname"] ~ /Linux|Unix/) {
run_pipe_test("inherit-default", "BEGIN { print \"hello\" | \"cat >&3\" }", "hello\n");
+10 -2
View File
@@ -8,8 +8,16 @@
@global rec_no;
BEGIN {
p1 = sprintf("/tmp/h-017-a.%d.tmp", sys::getpid());
p2 = sprintf("/tmp/h-017-b.%d.tmp", sys::getpid());
p1 = sys::tempname("h-017-a-");
p2 = sys::tempname("h-017-b-");
if (p1 == "" || p2 == "")
{
if (p1 != "") sys::unlink(p1);
if (p2 != "") sys::unlink(p2);
tap_fail(sprintf("%s[%d] unable to create temporary files - %s", @SCRIPTNAME, @SCRIPTLINE, sys::errmsg()));
tap_end();
@abort 1;
}
print "A1" > p1;
print "A2" >> p1;
+10 -2
View File
@@ -8,8 +8,16 @@
@global rec_no;
BEGIN {
p1 = sprintf("/tmp/h-017-a.%d.tmp", sys::getpid());
p2 = sprintf("/tmp/h-017-b.%d.tmp", sys::getpid());
p1 = sys::tempname("h-018-a-");
p2 = sys::tempname("h-018-b-");
if (p1 == "" || p2 == "")
{
if (p1 != "") sys::unlink(p1);
if (p2 != "") sys::unlink(p2);
tap_fail(sprintf("%s[%d] unable to create temporary files - %s", @SCRIPTNAME, @SCRIPTLINE, sys::errmsg()));
tap_end();
@abort 1;
}
print "x1" > p1;
print "x2" >> p1;
+8 -3
View File
@@ -22,15 +22,20 @@ function slurp(path, line, out, first)
function run_case(caseno, vopts, userargs, expected, cmd, inf, outf, got)
{
inf = sprintf("%s/%s", TDIR, "h-024.in");
outf = sprintf("/tmp/%s.%d.%d.out", "h-024", sys::getpid(), caseno);
outf = sys::tempname(sprintf("h-024-%d-", caseno));
if (outf == "")
{
tap_fail(sprintf("%s[%d] case %d - unable to create a temporary file - %s", @SCRIPTNAME, @SCRIPTLINE, caseno, sys::errmsg()));
return;
}
cmd = sprintf("%s -vCASE=%d %s -f %s/%s --modlibdirs=%s %s %s > %s",
cmd = sprintf("%s -vCASE=%d %s -f %s/%s --modlibdirs=%s %s %s > \"%s\"",
ARGV[0], caseno, vopts, TDIR, "h-024-child.hawk", hawk::modlibdirs(), userargs, inf, outf);
system(cmd);
got = slurp(outf);
tap_ensure(got, expected, @SCRIPTNAME, @SCRIPTLINE);
system(sprintf("rm -f %s", outf));
sys::unlink(outf);
}
function main()
+3 -1
View File
@@ -317,8 +317,10 @@ function test_compound_assign( x)
## string concatenation compound assignment
x = "hello";
x = x " " "world";
x %%= " " "world";
tap_ensure(x, "hello world", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure((x %%= "!"), "hello world!", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(x, "hello world!", @SCRIPTNAME, @SCRIPTLINE);
}
## -----------------------------------------------------------------------
+74
View File
@@ -0,0 +1,74 @@
@pragma entry main
@pragma implicit off
@include "tap.inc";
function frame_return(n, omitted)
{
@local text, map, unused;
tap_ensure(omitted === @nil, @true, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(unused === @nil, @true, @SCRIPTNAME, @SCRIPTLINE);
text = sprintf("frame-%d", n);
map["text"] = text;
unused = "occupied";
if (n > 0)
{
@local child;
child = frame_return(n - 1);
tap_ensure(child["text"], sprintf("frame-%d", n - 1), @SCRIPTNAME, @SCRIPTLINE);
}
return map;
}
function frame_ref(&value, suffix, omitted)
{
@local text;
tap_ensure(omitted === @nil, @true, @SCRIPTNAME, @SCRIPTLINE);
text = value suffix;
value = text;
return text;
}
function frame_forward(value)
{
@local result;
result = frame_ref(value, "-direct");
tap_ensure(result, value, @SCRIPTNAME, @SCRIPTLINE);
result = hawk::call("frame_ref", value, "-indirect");
tap_ensure(result, value, @SCRIPTNAME, @SCRIPTLINE);
return value;
}
function frame_variadic(first, ...)
{
@local i, result;
result = first;
for (i = 1; i < @argc; i++) result = result %% @argv[i];
return result;
}
function main()
{
@local i, result, map;
for (i = 0; i < 3; i++)
{
@local fresh, text;
tap_ensure(fresh === @nil, @true, @SCRIPTNAME, @SCRIPTLINE);
fresh["previous"] = i;
text = sprintf("iteration-%d", i);
map = frame_return(3);
tap_ensure(map["text"], "frame-3", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(text, sprintf("iteration-%d", i), @SCRIPTNAME, @SCRIPTLINE);
}
result = frame_forward("start");
tap_ensure(result, "start-direct-indirect", @SCRIPTNAME, @SCRIPTLINE);
map["text"] = "indexed";
result = frame_ref(map["text"], "-updated");
tap_ensure(map["text"], "indexed-updated", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(result, map["text"], @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(frame_variadic(frame_forward("a"), frame_variadic("b", "c"), "d"),
"a-direct-indirectbcd", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(frame_variadic("only"), "only", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(frame_variadic() === @nil, @true, @SCRIPTNAME, @SCRIPTLINE);
tap_end();
}
+70
View File
@@ -0,0 +1,70 @@
@pragma entry main
@pragma implicit off
@include "tap.inc";
function replace_key(&value)
{
value = "replaced";
}
function test_literal_keys()
{
@local map, key, i;
map[""] = "empty";
map["a\0b"] = "embedded nul";
map["01"] = "leading zero";
map["1"] = "one";
tap_ensure(map[""], "empty", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(map["a\0b"], "embedded nul", @SCRIPTNAME, @SCRIPTLINE);
key = "a\0b";
tap_ensure(map[key], map["a\0b"], @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(map["01"], "leading zero", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(map[1], "one", @SCRIPTNAME, @SCRIPTLINE);
map.outer["inner"].value = 10;
map["outer"].inner["value"] += 3;
tap_ensure(map.outer.inner.value, 13, @SCRIPTNAME, @SCRIPTLINE);
replace_key(map["outer"]["inner"]["value"]);
tap_ensure(map.outer.inner.value, "replaced", @SCRIPTNAME, @SCRIPTLINE);
map["left", "right"] = 42;
tap_ensure(map["left", "right"], 42, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(("left", "right") in map, @true, @SCRIPTNAME, @SCRIPTLINE);
delete map["a\0b"];
tap_ensure("a\0b" in map, @false, @SCRIPTNAME, @SCRIPTLINE);
for (i = 0; i < 10; i++)
{
map["counter"]++;
map["nested"]["counter"] = map["counter"];
}
tap_ensure(map.nested.counter, 10, @SCRIPTNAME, @SCRIPTLINE);
key = "";
for (i = 0; i < 800; i++) key = key %% "x";
map["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] = "long key";
tap_ensure(map[key], "long key", @SCRIPTNAME, @SCRIPTLINE);
map[key] = "updated long key";
tap_ensure(map["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"], "updated long key", @SCRIPTNAME, @SCRIPTLINE);
}
function check_order(a, b, less, equal)
{
tap_ensure(a < b, less, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(a <= b, less || equal, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(a == b, equal, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(a != b, !equal, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(a >= b, !less, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(a > b, !(less || equal), @SCRIPTNAME, @SCRIPTLINE);
}
function main()
{
test_literal_keys();
check_order(-100000, 100000, @true, @false);
check_order(100000, -100000, @false, @false);
check_order(0, 0, @false, @true);
check_order(-1, -1, @false, @true);
check_order(1, 1, @false, @true);
check_order(2147483647, -2147483647, @false, @false);
check_order(-2147483647, 0, @true, @false);
check_order(2147483647, 2147483647, @false, @true);
tap_end();
}
+280
View File
@@ -0,0 +1,280 @@
/* Native stack exhaustion must return an error, unwind, and permit reuse.
* Parse/open on the main thread, then execute the same rtx on smaller stacks. */
#include <hawk.h>
#include <hawk-utl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tap.h"
#if defined(_WIN32)
#define TEST_CSTACK
#elif defined(__HAIKU__) && defined(HAVE_FIND_THREAD) && defined(HAVE_GET_THREAD_INFO)
#define TEST_CSTACK
#elif defined(__APPLE__) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) && defined(HAVE_PTHREAD_GET_STACKSIZE_NP)
#define TEST_CSTACK
#elif defined(__OpenBSD__) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_STACKSEG_NP)
#define TEST_CSTACK
#elif defined(__linux__) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) && defined(HAVE_PTHREAD_ATTR_GETGUARDSIZE)
#define TEST_CSTACK
#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_ATTR_GET_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) && defined(HAVE_PTHREAD_ATTR_GETGUARDSIZE)
#define TEST_CSTACK
#endif
#if defined(TEST_CSTACK)
# if defined(_WIN32)
# include <windows.h>
# else
# include <pthread.h>
# include <sys/mman.h>
# include <unistd.h>
# if !defined(MAP_ANONYMOUS)
# define MAP_ANONYMOUS MAP_ANON
# endif
# endif
#endif
#if defined(TEST_CSTACK)
static int reenter (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
hawk_val_t* v;
(void)fi;
v = hawk_rtx_callwithbcstr(rtx, "callback", HAWK_NULL, 0);
if (!v) return -1;
hawk_rtx_setretval(rtx, v);
hawk_rtx_refdownval(rtx, v);
return 0;
}
struct job_t
{
hawk_rtx_t* rtx;
const char* name; /* NULL exercises hawk_rtx_loop() */
int require_native;
int passed;
};
static void* exhaust (void* data)
{
struct job_t* job = (struct job_t*)data;
hawk_val_t* v;
v = job->name? hawk_rtx_callwithbcstr(job->rtx, job->name, HAWK_NULL, 0): hawk_rtx_loop(job->rtx);
job->passed = !v && hawk_rtx_geterrnum(job->rtx) == HAWK_ESTACK &&
(!job->require_native || strstr(hawk_rtx_geterrbmsg(job->rtx), "native C stack limit reached") != HAWK_NULL);
if (!job->passed) printf("# unexpected result: %s\n", hawk_rtx_geterrbmsg(job->rtx));
if (v) hawk_rtx_refdownval(job->rtx, v);
return HAWK_NULL;
}
#if defined(_WIN32)
static DWORD WINAPI thread_main (LPVOID data)
{
exhaust(data);
return 0;
}
#endif
static int on_stack (struct job_t* job, size_t size)
{
#if defined(_WIN32)
HANDLE thread = CreateThread(HAWK_NULL, size, thread_main, job, STACK_SIZE_PARAM_IS_A_RESERVATION, HAWK_NULL);
DWORD n;
if (!thread) return -1;
n = WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
return n == WAIT_OBJECT_0? 0: -1;
#elif defined(__HAIKU__)
pthread_attr_t attr;
pthread_t thread;
int n, started = 0;
n = pthread_attr_init(&attr);
if (n == 0)
{
/* On Haiku, passing an existing mmap() area to pthread_attr_setstack()
* prevents the thread entry point from running. Let the kernel allocate
* an exact-sized stack instead.
*
* [NOTE]
* This branch may work on other platforms that support pthread_attr_setstacksize.
* In posix specification, the given size to pthread_attr_setstacksize
* is the minimum size. so the actual stack may be larger than requested.
* If the exact-sized stack is allocated, the test becomes less deterministic */
n = pthread_attr_setstacksize(&attr, size);
if (n == 0)
{
n = pthread_create(&thread, &attr, exhaust, job);
started = (n == 0);
}
pthread_attr_destroy(&attr);
if (n == 0) n = pthread_join(thread, HAWK_NULL);
}
return started && n == 0? 0: -1;
#else
pthread_attr_t attr;
pthread_t thread;
void* stack;
long page = sysconf(_SC_PAGESIZE);
int n, started = 0;
if (page <= 0) return -1;
/* Supply the exact allocation: pthreads may otherwise reuse a cached,
* larger stack and turn the small-stack regression into a false pass. */
stack = mmap(HAWK_NULL, size + 2 * page, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (stack == MAP_FAILED) return -1;
if (mprotect((char*)stack + page, size, PROT_READ | PROT_WRITE) != 0)
{
munmap(stack, size + 2 * page);
return -1;
}
n = pthread_attr_init(&attr);
if (n == 0)
{
n = pthread_attr_setstack(&attr, (char*)stack + page, size);
if (n == 0)
{
n = pthread_create(&thread, &attr, exhaust, job);
started = (n == 0);
}
pthread_attr_destroy(&attr);
if (n == 0) n = pthread_join(thread, HAWK_NULL);
}
/* A failed join cannot prove that the worker stopped using this stack. */
if (!started || n == 0) munmap(stack, size + 2 * page);
return n == 0? 0: -1;
#endif
}
static void check_reuse (hawk_rtx_t* rtx)
{
hawk_val_t* v;
hawk_int_t n = 0;
v = hawk_rtx_callwithbcstr(rtx, "answer", HAWK_NULL, 0);
OK(v && hawk_rtx_valtoint(rtx, v, &n) == 0 && n == 42, "rtx reusable on main thread after exhaustion");
if (v) hawk_rtx_refdownval(rtx, v);
}
#endif
int main (void)
{
#if defined(TEST_CSTACK)
static const char prefix[] =
"@pragma stack_limit 1048576\n"
"function direct() { @local s; s = sprintf(\"value-%d\", 1); return 1 + direct(); }\n"
"function mutual() { return other(); }\n"
"function other() { return mutual(); }\n"
"function callback() { return host_reenter(); }\n"
"function answer() { return 42; }\n"
"BEGIN { direct(); }\n"
"function expression() { @local n; n = 1; return n";
static const char* names[] = { "direct", "mutual", "callback", "expression", HAWK_NULL };
static const size_t sizes[] = { 128 * 1024, 256 * 1024, 512 * 1024 };
hawk_t* hawk;
hawk_rtx_t* rtx = HAWK_NULL;
hawk_parsestd_t in[2];
hawk_fnc_bspec_t spec;
hawk_oow_t unlimited = 0;
struct job_t job;
char* src;
size_t i, j, len;
int n;
no_plan();
hawk = hawk_openstd(0, HAWK_NULL);
OK(hawk != HAWK_NULL, "open interpreter");
if (!hawk) return exit_status();
/* Make depth/value-stack limits incapable of masking native exhaustion. */
hawk_setopt(hawk, HAWK_OPT_DEPTH_RECURS_RUN, &unlimited);
memset(&spec, 0, sizeof(spec));
spec.impl = reenter;
OK(hawk_addfncwithbcstr(hawk, "host_reenter", &spec) != HAWK_NULL, "register host callback");
src = (char*)malloc(sizeof(prefix) + 12000);
OK(src != HAWK_NULL, "allocate expression source");
if (!src) goto done;
strcpy(src, prefix);
len = strlen(src);
/* Not constant-foldable; evaluates recursively without function calls. */
for (i = 0; i < 5000; i++) { src[len++] = '+'; src[len++] = 'n'; }
strcpy(src + len, "; }\n");
memset(in, 0, sizeof(in));
in[0].type = HAWK_PARSESTD_BCS;
in[0].u.bcs.ptr = src;
in[0].u.bcs.len = strlen(src);
in[1].type = HAWK_PARSESTD_NULL;
n = hawk_parsestd(hawk, in, HAWK_NULL);
OK(n >= 0, "parse recursive functions and long expression");
free(src);
if (n < 0) { printf("# %s\n", hawk_geterrbmsg(hawk)); goto done; }
rtx = hawk_rtx_openstd(hawk, 0, HAWK_T("t-011"), HAWK_NULL, HAWK_NULL, HAWK_NULL);
OK(rtx != HAWK_NULL, "open runtime on main thread");
if (!rtx) goto done;
job.rtx = rtx;
job.name = "direct";
job.require_native = 0;
job.passed = 0;
exhaust(&job);
OK(job.passed, "stack exhaustion on main thread");
check_reuse(rtx);
job.require_native = 1;
for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++)
{
for (j = 0; j < sizeof(names) / sizeof(names[0]); j++)
{
job.name = names[j];
job.passed = 0;
printf("# stack=%lu entry=%s\n", (unsigned long)sizes[i], job.name? job.name: "BEGIN");
n = on_stack(&job, sizes[i]);
OK(n == 0, "execute on bounded worker stack");
OK(n == 0 && job.passed, "native stack exhausted gracefully");
check_reuse(rtx);
}
}
/* An entry with less than the reserve must refuse even trivial work. */
job.name = "answer";
job.passed = 0;
OK(on_stack(&job, 64 * 1024) == 0 && job.passed, "reject entry without stack headroom");
check_reuse(rtx);
done:
if (rtx) hawk_rtx_close(rtx);
hawk_close(hawk);
return exit_status();
#else
static char src[] =
"function direct() { return 1 + direct(); }\n"
"function answer() { return 42; }\n";
hawk_t* hawk;
hawk_rtx_t* rtx = HAWK_NULL;
hawk_parsestd_t in[2];
hawk_val_t* v;
hawk_oow_t limit = 32;
hawk_int_t answer = 0;
int n;
no_plan();
hawk = hawk_openstd(0, HAWK_NULL);
OK(hawk != HAWK_NULL, "open interpreter for logical-depth fallback");
if (!hawk) return exit_status();
OK(hawk_setopt(hawk, HAWK_OPT_DEPTH_RECURS_RUN, &limit) == 0, "set logical recursion limit");
memset(in, 0, sizeof(in));
in[0].type = HAWK_PARSESTD_BCS;
in[0].u.bcs.ptr = src;
in[0].u.bcs.len = sizeof(src) - 1;
in[1].type = HAWK_PARSESTD_NULL;
n = hawk_parsestd(hawk, in, HAWK_NULL);
OK(n >= 0, "parse fallback test functions");
if (n < 0) goto fallback_done;
rtx = hawk_rtx_openstd(hawk, 0, HAWK_T("t-011"), HAWK_NULL, HAWK_NULL, HAWK_NULL);
OK(rtx != HAWK_NULL, "open runtime for logical-depth fallback");
if (!rtx) goto fallback_done;
v = hawk_rtx_callwithbcstr(rtx, "direct", HAWK_NULL, 0);
OK(!v && hawk_rtx_geterrnum(rtx) == HAWK_EBLKNST, "logical recursion limit stops recursive evaluation");
if (v) hawk_rtx_refdownval(rtx, v);
v = hawk_rtx_callwithbcstr(rtx, "answer", HAWK_NULL, 0);
OK(v && hawk_rtx_valtoint(rtx, v, &answer) == 0 && answer == 42, "runtime reusable after logical-depth exhaustion");
if (v) hawk_rtx_refdownval(rtx, v);
fallback_done:
if (rtx) hawk_rtx_close(rtx);
hawk_close(hawk);
return exit_status();
#endif
}