Compare commits
23
Commits
7f7893d4d1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c89df44d20 | ||
|
|
a7dff29ad9 | ||
|
|
16ce1fd923 | ||
|
|
5a9958229e | ||
|
|
e90130abf5 | ||
|
|
ef9d88359d | ||
|
|
aebeb66a57 | ||
|
|
8593335d89 | ||
|
|
1f42676e6e | ||
|
|
d8a3cbcad5 | ||
|
|
a0b6e3b12b | ||
|
|
ac5c9fecea | ||
|
|
ae34dfdb71 | ||
|
|
9e5afd66a1 | ||
|
|
0834275306 | ||
|
|
dce517bb2f | ||
|
|
e2d648fbba | ||
|
|
ef1c667ec9 | ||
|
|
6844dde1b6 | ||
|
|
260318b24c | ||
|
|
6b7873b230 | ||
|
|
5a563d7c15 | ||
|
|
6dc0dec3e8 |
+4
-1
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,7 +21487,8 @@ 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"
|
||||
|
||||
if test "${enable_wide_char}" != "yes:4"
|
||||
then
|
||||
|
||||
printf "%s\n" "#define HAWK_PREFER_PREFIX_L 1" >>confdefs.h
|
||||
@@ -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
@@ -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],
|
||||
|
||||
@@ -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,35 +808,35 @@ 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 })aAAA
|
||||
//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
|
||||
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
|
||||
//return rtx.make_val(func() *C.hawk_val_t { return val })
|
||||
}
|
||||
|
||||
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,96 +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
|
||||
if val.v_refs <= 0 && C.hawk_rtx_isstaticval(rtx.c, val) == 0 { panic("invalid reference count") }
|
||||
// immediate values or static pointer values must no check the 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))))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1136,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)
|
||||
}
|
||||
|
||||
@@ -1156,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
|
||||
@@ -1167,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
|
||||
@@ -1181,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)
|
||||
@@ -1196,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))
|
||||
@@ -1208,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
|
||||
}
|
||||
|
||||
@@ -1359,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;
|
||||
}
|
||||
@@ -1372,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;
|
||||
}
|
||||
|
||||
+701
-18
@@ -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
|
||||
@@ -184,7 +502,7 @@ return x;
|
||||
rtx, err = h.NewRtx("test2", nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create rtx - %s", err.Error())
|
||||
} else {
|
||||
} else {
|
||||
var v *hawk.Val
|
||||
|
||||
v, err = rtx.Call("get_map", hawk.Must(rtx.NewStrVal("hawk flies")))
|
||||
@@ -265,9 +583,9 @@ return x;
|
||||
}
|
||||
|
||||
/*
|
||||
for i = 1; i <= sz; i++ {
|
||||
fmt.Printf("%d %v\n", i, hawk.Must(v.GetArrayField(i)))
|
||||
}
|
||||
for i = 1; i <= sz; i++ {
|
||||
fmt.Printf("%d %v\n", i, hawk.Must(v.GetArrayField(i)))
|
||||
}
|
||||
*/
|
||||
fmt.Printf("== CHANGING ARRAY ==\n")
|
||||
v.SetArrayField(88, hawk.Must(rtx.NewStrVal("eighty eight")))
|
||||
@@ -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);
|
||||
@@ -313,7 +631,7 @@ return x
|
||||
rtx, err = h.NewRtx("test3", nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create rtx - %s", err.Error())
|
||||
} else {
|
||||
} else {
|
||||
var v *hawk.Val
|
||||
|
||||
v, err = rtx.Call("main", hawk.Must(rtx.NewStrVal("this is a test3 string")))
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -93,6 +93,7 @@ libhawk_la_SOURCES = \
|
||||
big5.c \
|
||||
big5.h \
|
||||
chr.c \
|
||||
cstack.c \
|
||||
cut-prv.h \
|
||||
cut.c \
|
||||
dir.c \
|
||||
|
||||
+47
-34
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -1776,8 +1776,6 @@ typedef enum hawk_log_mask_t hawk_log_mask_t;
|
||||
# error Unsupported platform
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/* =========================================================================
|
||||
* SOCKET ADDRESS
|
||||
|
||||
+79
-5
@@ -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
@@ -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];
|
||||
|
||||
+25
-7
@@ -549,14 +549,14 @@ typedef struct hawk_val_fun_t hawk_val_fun_t;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
typedef hawk_flt_t (*hawk_math1_t) (
|
||||
hawk_t* hawk,
|
||||
hawk_flt_t x
|
||||
hawk_t* hawk,
|
||||
hawk_flt_t x
|
||||
);
|
||||
|
||||
typedef hawk_flt_t (*hawk_math2_t) (
|
||||
hawk_t* hawk,
|
||||
hawk_flt_t x,
|
||||
hawk_flt_t y
|
||||
hawk_t* hawk,
|
||||
hawk_flt_t x,
|
||||
hawk_flt_t y
|
||||
);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -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,
|
||||
|
||||
@@ -3653,6 +3657,20 @@ HAWK_EXPORT int hawk_rtx_isstaticval (
|
||||
const hawk_val_t* val /**< value to check */
|
||||
);
|
||||
|
||||
/**
|
||||
* The hawk_rtx_isimmval() function determines if a value is a immediate value
|
||||
* encoded using pointer tagging.
|
||||
*/
|
||||
HAWK_EXPORT int hawk_rtx_isimmval (
|
||||
hawk_rtx_t* rtx, /**< runtime context */
|
||||
const hawk_val_t* val /**< value to check */
|
||||
);
|
||||
|
||||
HAWK_EXPORT int hawk_rtx_isimmorstaticval (
|
||||
hawk_rtx_t* rtx, /**< runtime context */
|
||||
const hawk_val_t* val /**< value to check */
|
||||
);
|
||||
|
||||
HAWK_EXPORT int hawk_rtx_getvaltype (
|
||||
hawk_rtx_t* rtx,
|
||||
const hawk_val_t* val
|
||||
|
||||
+2
-2
@@ -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
@@ -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 } },
|
||||
|
||||
@@ -601,9 +601,17 @@ static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], para
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(__DOS__)
|
||||
/* not needed on DOS: hawk_pio_init() bails out with HAWK_ENOIMPL there before
|
||||
* any pipe is ever created, so there is no call site for this. */
|
||||
static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
|
||||
{
|
||||
#if defined(O_NONBLOCK)
|
||||
#if defined(_WIN32)
|
||||
/* anonymous pipes created by CreatePipe() cannot be switched to
|
||||
* non-blocking mode. */
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, HAWK_ENOIMPL);
|
||||
return -1;
|
||||
#elif defined(O_NONBLOCK)
|
||||
int flag = HAWK_FCNTL(fd, F_GETFL, 0);
|
||||
if (flag >= 0) flag = HAWK_FCNTL(fd, F_SETFL, (enabled? (flag | O_NONBLOCK): (flag & ~O_NONBLOCK)));
|
||||
if (flag <= -1) hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
@@ -613,6 +621,7 @@ static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int flags, hawk_pio_env_mk_t env_mk, void* env_ctx)
|
||||
@@ -725,6 +734,12 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
}
|
||||
}
|
||||
|
||||
/* handle[1] is the parent's end and is never inherited by the child,
|
||||
* so switching it here - before the child exists - is equivalent to
|
||||
* doing it afterwards, and keeps this failure out of the window in
|
||||
* which a spawned child would have to be cleaned up. */
|
||||
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
|
||||
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
@@ -750,6 +765,8 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
@@ -776,6 +793,8 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
@@ -813,7 +832,7 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
|
||||
startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startup.hStdOutput = GetStdHandle(STD_ERROR_HANDLE);
|
||||
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (startup.hStdInput == INVALID_HANDLE_VALUE ||
|
||||
startup.hStdOutput == INVALID_HANDLE_VALUE ||
|
||||
startup.hStdError == INVALID_HANDLE_VALUE)
|
||||
@@ -1013,6 +1032,12 @@ create_process:
|
||||
DosQueryFHState (handle[1], &state);
|
||||
DosSetFHState (handle[1], state | OPEN_FLAGS_NOINHERIT); */
|
||||
|
||||
/* handle[1] is the parent's end and is marked NOINHERIT above, so
|
||||
* switching it before the child exists is equivalent to doing it
|
||||
* afterwards, and keeps this failure out of the window in which a
|
||||
* spawned child would have to be cleaned up. */
|
||||
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
|
||||
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
@@ -1035,6 +1060,8 @@ create_process:
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
@@ -1058,6 +1085,8 @@ create_process:
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
@@ -1303,6 +1332,15 @@ create_process:
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* O_NONBLOCK belongs to the open file description, and handle[1] is
|
||||
* the parent's end - a different description from the handle[0] the
|
||||
* child inherits, and one the child closes anyway. so switching it
|
||||
* here, before the child exists, is equivalent to doing it after the
|
||||
* spawn, and keeps this failure out of the window in which a spawned
|
||||
* child would have to be cleaned up. */
|
||||
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
|
||||
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
@@ -1313,6 +1351,9 @@ create_process:
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
@@ -1324,6 +1365,9 @@ create_process:
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
@@ -1761,13 +1805,6 @@ create_process:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) ||
|
||||
((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) ||
|
||||
((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1))
|
||||
{
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* store back references */
|
||||
pio->pin[HAWK_PIO_IN].self = pio;
|
||||
pio->pin[HAWK_PIO_OUT].self = pio;
|
||||
@@ -1778,7 +1815,6 @@ create_process:
|
||||
pio->pin[HAWK_PIO_OUT].handle = handle[2];
|
||||
pio->pin[HAWK_PIO_ERR].handle = handle[4];
|
||||
|
||||
|
||||
if (flags & HAWK_PIO_TEXT)
|
||||
{
|
||||
int topt = 0;
|
||||
@@ -1791,6 +1827,9 @@ create_process:
|
||||
{
|
||||
int r;
|
||||
|
||||
/* NOTE: the child process has already been spawned.
|
||||
* jumping to oops for failure below will trigger forced kill of
|
||||
* a child process at the beginning of the oops part */
|
||||
tio[i] = hawk_tio_open(pio->gem, HAWK_SIZEOF(&pio->pin[i]), topt);
|
||||
if (HAWK_UNLIKELY(!tio[i])) goto oops;
|
||||
|
||||
@@ -1808,6 +1847,26 @@ create_process:
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* if the child has already been spawned, a failure in a later step must
|
||||
* not leave it behind: the caller is about to get -1 and will never have
|
||||
* a handle to reap it with. */
|
||||
if (pio->child != HAWK_PIO_PID_NIL)
|
||||
{
|
||||
hawk_errnum_t err = hawk_gem_geterrnum(pio->gem);
|
||||
|
||||
/* SIGKILL, not a bare wait: the child may be long-running, or blocked
|
||||
* writing to a pipe we still hold - either would hang us here. */
|
||||
hawk_pio_kill(pio);
|
||||
|
||||
/* the caller's WAITNOBLOCK/WAITNORETRY must not stop us reaping */
|
||||
pio->flags &= ~HAWK_PIO_WAITNOBLOCK;
|
||||
pio->flags &= ~HAWK_PIO_WAITNORETRY;
|
||||
hawk_pio_wait(pio); /* reaps and resets child to PID_NIL */
|
||||
|
||||
/* kill()/wait() set errnum themselves - restore the real cause */
|
||||
hawk_gem_seterrnum (pio->gem, HAWK_NULL, err);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (windevnul != INVALID_HANDLE_VALUE) CloseHandle(windevnul);
|
||||
|
||||
@@ -1837,11 +1896,20 @@ oops:
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
for (i = minidx; i < maxidx; i++) CloseHandle(handle[i]);
|
||||
#elif defined(__OS2__)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
if (minidx >= 0)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) DosClose(handle[i]);
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) CloseHandle(handle[i]);
|
||||
}
|
||||
}
|
||||
#elif defined(__OS2__)
|
||||
if (minidx >= 0)
|
||||
{
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) DosClose(handle[i]);
|
||||
}
|
||||
}
|
||||
#elif defined(__DOS__)
|
||||
|
||||
@@ -1852,19 +1920,28 @@ oops:
|
||||
posix_spawn_file_actions_destroy (&fa);
|
||||
fa_inited = 0;
|
||||
}
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
if (i >= 0)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
}
|
||||
}
|
||||
#elif defined(HAWK_SYSCALL0) && defined(SYS_vfork)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
if (i >= 0)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
if (i >= 0)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+3
-3
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -2958,13 +3037,17 @@ static int push_exec_stack (hawk_rtx_t* rtx, int state, hawk_nde_t* nde)
|
||||
{
|
||||
hawk_oow_t new_limit;
|
||||
hawk_exec_stack_t* tmp;
|
||||
|
||||
new_limit = rtx->exec_stack_limit + 1;
|
||||
new_limit = HAWK_ALIGN_POW2(new_limit, 64); /* TODO: change align factor */
|
||||
|
||||
tmp = hawk_rtx_reallocmem(rtx, rtx->exec_stack, HAWK_SIZEOF(*tmp) * new_limit);
|
||||
if (HAWK_UNLIKELY(!tmp)) return -1;
|
||||
|
||||
rtx->exec_stack = tmp;
|
||||
rtx->exec_stack_limit = new_limit;
|
||||
}
|
||||
|
||||
rtx->exec_stack[rtx->exec_stack_size].state = state;
|
||||
rtx->exec_stack[rtx->exec_stack_size].nde = nde;
|
||||
rtx->exec_stack[rtx->exec_stack_size].ptr = HAWK_NULL;
|
||||
@@ -2979,7 +3062,7 @@ static int push_exec_stack2 (hawk_rtx_t* rtx, int state, hawk_nde_t* nde, hawk_n
|
||||
int n;
|
||||
|
||||
n = push_exec_stack(rtx, state, nde);
|
||||
if (n <= -1) return -1;
|
||||
if (HAWK_UNLIKELY(n <= -1)) return -1;
|
||||
rtx->exec_stack[rtx->exec_stack_size - 1].ptr = ptr;
|
||||
return 0;
|
||||
}
|
||||
@@ -2989,13 +3072,15 @@ static int push_exec_stack3 (hawk_rtx_t* rtx, int state, hawk_nde_t* nde, hawk_o
|
||||
int n;
|
||||
|
||||
n = push_exec_stack(rtx, state, nde);
|
||||
if (n <= -1) return -1;
|
||||
if (HAWK_UNLIKELY(n <= -1)) return -1;
|
||||
rtx->exec_stack[rtx->exec_stack_size - 1].iv = iv;
|
||||
rtx->exec_stack[rtx->exec_stack_size - 1].base = base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: return the item pointer? */
|
||||
#define pop_exec_stack_unchecked(rtx) ((rtx)->exec_stack_size = (rtx)->exec_stack_size - 1)
|
||||
|
||||
static hawk_exec_stack_t* pop_exec_stack (hawk_rtx_t* rtx, hawk_exec_stack_t* es)
|
||||
{
|
||||
if (rtx->exec_stack_size <= 0) return HAWK_NULL;
|
||||
@@ -3018,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3050,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)
|
||||
{
|
||||
@@ -3067,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);
|
||||
@@ -3093,16 +3191,18 @@ static int enter_block_iterative (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
|
||||
}
|
||||
}
|
||||
|
||||
/* what needs to be done upon entering a block has been done.
|
||||
* rollback(i.e. leave_block_iterative) must undo them from here on. */
|
||||
|
||||
if (push_exec_stack(rtx, EXEC_STATE_BLK_LEAVE, (hawk_nde_t*)nde) <= -1)
|
||||
{
|
||||
leave_block_iterative(rtx, nde);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nde->body &&
|
||||
push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, (hawk_nde_t*)nde, nde->body) <= -1)
|
||||
if (nde->body && push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, (hawk_nde_t*)nde, nde->body) <= -1)
|
||||
{
|
||||
rtx->exec_stack_size--;
|
||||
pop_exec_stack_unchecked(rtx);
|
||||
leave_block_iterative(rtx, nde);
|
||||
return -1;
|
||||
}
|
||||
@@ -3153,13 +3253,18 @@ static int run_statement0 (hawk_rtx_t* rtx, const hawk_exec_stack_t* es)
|
||||
stmt = es->ptr;
|
||||
HAWK_ASSERT(stmt != HAWK_NULL);
|
||||
|
||||
if (stmt->next &&
|
||||
push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, nde, stmt->next) <= -1) return -1;
|
||||
/* For example, consider:
|
||||
* { print "hello"; print "world" }
|
||||
* nde->body is pushed to the stack in enter_block_interactive().
|
||||
* the body is a chain of other statements. each statement needs
|
||||
* to be executed. */
|
||||
if (stmt->next && push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, nde, stmt->next) <= -1) return -1;
|
||||
if (push_exec_stack(rtx, EXEC_STATE_ENTER, stmt) <= -1) return -1;
|
||||
xret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* entering the block */
|
||||
xret = enter_block_iterative(rtx, (hawk_nde_blk_t*)nde);
|
||||
}
|
||||
break;
|
||||
@@ -3257,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;
|
||||
|
||||
@@ -4798,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)
|
||||
@@ -4881,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;
|
||||
}
|
||||
@@ -4905,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;
|
||||
}
|
||||
@@ -4971,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);
|
||||
@@ -5000,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);
|
||||
@@ -5458,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;
|
||||
@@ -5549,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);
|
||||
@@ -7527,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)
|
||||
{
|
||||
@@ -8241,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
|
||||
|
||||
@@ -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
|
||||
|
||||
+29
-27
@@ -231,7 +231,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||
PRINT_EXPR(hawk, px->right);
|
||||
|
||||
HAWK_ASSERT (px->right->next == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right->next == HAWK_NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
|
||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||
PRINT_EXPR(hawk, px->left);
|
||||
HAWK_ASSERT (px->left->next == HAWK_NULL);
|
||||
HAWK_ASSERT(px->left->next == HAWK_NULL);
|
||||
|
||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||
PUT_SRCSTR(hawk, binop_str[px->opcode][(hawk->opt.trait & HAWK_BLANKCONCAT)? 0: 1]);
|
||||
@@ -252,7 +252,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
PRINT_EXPR(hawk, px->right);
|
||||
if (px->right->type == HAWK_NDE_ASS)
|
||||
PUT_SRCSTR(hawk, HAWK_T(")"));
|
||||
HAWK_ASSERT (px->right->next == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right->next == HAWK_NULL);
|
||||
PUT_SRCSTR(hawk, HAWK_T(")"));
|
||||
break;
|
||||
}
|
||||
@@ -260,7 +260,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
case HAWK_NDE_EXP_UNR:
|
||||
{
|
||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||
|
||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||
PUT_SRCSTR(hawk, unrop_str[px->opcode]);
|
||||
@@ -274,7 +274,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
case HAWK_NDE_EXP_INCPRE:
|
||||
{
|
||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||
|
||||
PUT_SRCSTR(hawk, incop_str[px->opcode]);
|
||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||
@@ -286,7 +286,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
case HAWK_NDE_EXP_INCPST:
|
||||
{
|
||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||
|
||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||
PRINT_EXPR(hawk, px->left);
|
||||
@@ -659,14 +659,14 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
hawk_ooch_t tmp[HAWK_SIZEOF(hawk_int_t)*8+2];
|
||||
hawk_oow_t n;
|
||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||
HAWK_ASSERT (px->id.idxa != (hawk_oow_t)-1);
|
||||
HAWK_ASSERT(px->id.idxa != (hawk_oow_t)-1);
|
||||
|
||||
n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, tmp, HAWK_COUNTOF(tmp));
|
||||
|
||||
PUT_SRCSTR(hawk, HAWK_T("__p"));
|
||||
PUT_SRCSTRN(hawk, tmp, n);
|
||||
|
||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -674,8 +674,8 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
{
|
||||
hawk_oow_t n;
|
||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||
HAWK_ASSERT (px->id.idxa != (hawk_oow_t)-1);
|
||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
||||
HAWK_ASSERT(px->id.idxa != (hawk_oow_t)-1);
|
||||
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||
|
||||
PUT_SRCSTR(hawk, HAWK_T("__p"));
|
||||
n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt));
|
||||
@@ -687,10 +687,10 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
case HAWK_NDE_NAMED:
|
||||
{
|
||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||
/*HAWK_ASSERT (px->id.idxa == (hawk_oow_t)-1);
|
||||
/*HAWK_ASSERT(px->id.idxa == (hawk_oow_t)-1);
|
||||
* commented out the above assertion because
|
||||
* id.idxa field holds an index to the rtx->named_slots. */
|
||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||
|
||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||
break;
|
||||
@@ -699,8 +699,10 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
case HAWK_NDE_NAMEDIDX:
|
||||
{
|
||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||
HAWK_ASSERT (px->id.idxa == (hawk_oow_t)-1);
|
||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
||||
/*HAWK_ASSERT(px->id.idxa == (hawk_oow_t)-1);
|
||||
* commented out the above assertion because
|
||||
* id.idxa field holds an index to the rtx->named_slots. */
|
||||
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||
|
||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
||||
@@ -740,7 +742,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
{
|
||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||
}
|
||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -777,7 +779,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
{
|
||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||
}
|
||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
||||
break;
|
||||
}
|
||||
@@ -798,7 +800,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
{
|
||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||
}
|
||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -817,7 +819,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
||||
{
|
||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||
}
|
||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
||||
break;
|
||||
}
|
||||
@@ -1027,7 +1029,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth, int flags)
|
||||
PRINT_EXPR(hawk, px->test);
|
||||
PUT_SRCSTR(hawk, HAWK_T(") "));
|
||||
|
||||
HAWK_ASSERT (px->then_part != HAWK_NULL);
|
||||
HAWK_ASSERT(px->then_part != HAWK_NULL);
|
||||
xflags = STMT_FLAG_NO_LEAD_INDENT;
|
||||
if (!px->else_part) xflags |= STMT_FLAG_NO_ENDING_NL;
|
||||
xdepth = depth + (px->then_part->type != HAWK_NDE_BLK);
|
||||
@@ -1202,7 +1204,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth, int flags)
|
||||
hawk_getkwname(hawk, HAWK_KWID_RETURN, &kw);
|
||||
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||
HAWK_ASSERT (((hawk_nde_return_t*)p)->val->next == HAWK_NULL);
|
||||
HAWK_ASSERT(((hawk_nde_return_t*)p)->val->next == HAWK_NULL);
|
||||
|
||||
PRINT_EXPR(hawk, ((hawk_nde_return_t*)p)->val);
|
||||
PUT_SRCSTR(hawk, HAWK_T(";"));
|
||||
@@ -1225,7 +1227,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth, int flags)
|
||||
hawk_getkwname(hawk, (px->abort? HAWK_KWID_XABORT: HAWK_KWID_EXIT), &kw);
|
||||
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||
HAWK_ASSERT (px->val->next == HAWK_NULL);
|
||||
HAWK_ASSERT(px->val->next == HAWK_NULL);
|
||||
PRINT_EXPR(hawk, px->val);
|
||||
PUT_SRCSTR(hawk, HAWK_T(";"));
|
||||
}
|
||||
@@ -1494,8 +1496,8 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
||||
case HAWK_NDE_EXP_BIN:
|
||||
{
|
||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)p;
|
||||
HAWK_ASSERT (px->left->next == HAWK_NULL);
|
||||
HAWK_ASSERT (px->right->next == HAWK_NULL);
|
||||
HAWK_ASSERT(px->left->next == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right->next == HAWK_NULL);
|
||||
|
||||
hawk_clrpt(hawk, px->left);
|
||||
hawk_clrpt(hawk, px->right);
|
||||
@@ -1508,7 +1510,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
||||
case HAWK_NDE_EXP_INCPST:
|
||||
{
|
||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)p;
|
||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
||||
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||
hawk_clrpt(hawk, px->left);
|
||||
hawk_freemem(hawk, p);
|
||||
break;
|
||||
@@ -1605,7 +1607,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
||||
case HAWK_NDE_ARG:
|
||||
{
|
||||
hawk_nde_var_t* px = (hawk_nde_var_t*)p;
|
||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||
if (px->id.name.ptr) hawk_freemem(hawk, px->id.name.ptr);
|
||||
hawk_freemem(hawk, p);
|
||||
break;
|
||||
@@ -1617,7 +1619,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
||||
case HAWK_NDE_ARGIDX:
|
||||
{
|
||||
hawk_nde_var_t* px = (hawk_nde_var_t*)p;
|
||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
||||
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||
hawk_clrpt(hawk, px->idx);
|
||||
if (px->id.name.ptr) hawk_freemem(hawk, px->id.name.ptr);
|
||||
hawk_freemem(hawk, p);
|
||||
@@ -1678,7 +1680,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
||||
|
||||
default:
|
||||
{
|
||||
HAWK_ASSERT (!"should never happen - invalid node type");
|
||||
HAWK_ASSERT(!"should never happen - invalid node type");
|
||||
hawk_freemem(hawk, p);
|
||||
break;
|
||||
}
|
||||
|
||||
+28
-20
@@ -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
|
||||
@@ -315,10 +323,10 @@ static HAWK_INLINE int hawk_rtx_valtoint_inline (hawk_rtx_t* rtx, const hawk_val
|
||||
*l = (hawk_int_t)r;
|
||||
n = 0;
|
||||
}
|
||||
return n;
|
||||
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
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -1572,11 +1573,21 @@ hawk_val_t* hawk_rtx_makebobval (hawk_rtx_t* rtx, const void* ptr, hawk_oow_t le
|
||||
return (hawk_val_t*)val;
|
||||
}
|
||||
|
||||
int HAWK_INLINE hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
int hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return HAWK_VTR_IS_POINTER(val) && HAWK_IS_STATICVAL(val);
|
||||
}
|
||||
|
||||
int hawk_rtx_isimmval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return !HAWK_VTR_IS_POINTER(val);
|
||||
}
|
||||
|
||||
int hawk_rtx_isimmorstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return !HAWK_VTR_IS_POINTER(val) || HAWK_IS_STATICVAL(val);
|
||||
}
|
||||
|
||||
int hawk_rtx_getvaltype (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return HAWK_RTX_GETVALTYPE(rtx, val);
|
||||
|
||||
@@ -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
@@ -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-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
-5
@@ -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,9 +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 \
|
||||
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 \
|
||||
@@ -717,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)
|
||||
@@ -819,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)
|
||||
@@ -839,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):
|
||||
@@ -1011,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 $@ $< &&\
|
||||
@@ -1343,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'; \
|
||||
@@ -1481,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 \
|
||||
@@ -1537,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
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
BEGIN {
|
||||
for (i = 0; i < 2000000; i++) {
|
||||
s += (i > 30) + (i < 300) + (i == 200) + (i != 300);
|
||||
}
|
||||
print s;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
+576
@@ -0,0 +1,576 @@
|
||||
## xstack expression evaluator tests
|
||||
## Covers every eframe state in eval_expression0_xstack:
|
||||
## HAWK_EF_BIN_LEFT/RIGHT - binary operators
|
||||
## HAWK_EF_LAND_LEFT/RIGHT - logical && with short-circuit
|
||||
## HAWK_EF_LOR_LEFT/RIGHT - logical || with short-circuit
|
||||
## HAWK_EF_UNARY - unary operators
|
||||
## HAWK_EF_CND - ternary conditional
|
||||
## HAWK_EF_ASS_RHS - simple assignment
|
||||
## HAWK_EF_ASS_LHS - compound assignment (read-modify-write)
|
||||
|
||||
@pragma entry main
|
||||
@pragma implicit off
|
||||
|
||||
@include "tap.inc";
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## binary arithmetic operators
|
||||
## -----------------------------------------------------------------------
|
||||
function test_binary_arith( x)
|
||||
{
|
||||
tap_ensure(2 + 3, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(10 - 4, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(3 * 7, 21, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(15 / 4, 3.75, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(17 % 5, 2, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(2 ^ 10, 1024, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(17 \ 5, 3, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(-17 \ 5, -3, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## string concatenation (binary)
|
||||
tap_ensure("hello" " " "world", "hello world", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure("a" "b" "c", "abc", @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## binary comparison operators
|
||||
## -----------------------------------------------------------------------
|
||||
function test_binary_cmp()
|
||||
{
|
||||
tap_ensure((3 < 5), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((5 < 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 <= 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((4 <= 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((5 > 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 > 5), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 >= 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((2 >= 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 == 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 == 4), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 != 4), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((3 != 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## bitwise binary operators
|
||||
## -----------------------------------------------------------------------
|
||||
function test_binary_bitwise()
|
||||
{
|
||||
tap_ensure((0xF0 & 0xFF), 240, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((0x0F & 0xFF), 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((0xF0 | 0x0F), 255, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((0xFF ^^ 0x0F), 240, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((1 << 4), 16, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((256 >> 3), 32, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((0 << 10), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## deeply chained binary expressions (stress eframe stack growth)
|
||||
## The eframe stack starts at 0 and grows 64 at a time; these chains
|
||||
## push many BIN_LEFT frames before resolving any BIN_RIGHT frames.
|
||||
## -----------------------------------------------------------------------
|
||||
function test_binary_chain( x)
|
||||
{
|
||||
## left-associative chain (parser produces left-leaning tree)
|
||||
x = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
|
||||
tap_ensure(x, 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = 1 * 2 * 3 * 4 * 5;
|
||||
tap_ensure(x, 120, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## deeply parenthesised right-associative nesting
|
||||
x = (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + 10)))))))));
|
||||
tap_ensure(x, 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## mix of operators
|
||||
x = 2 * 3 + 4 * 5 - 6 / 2;
|
||||
tap_ensure(x, 23, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## 20-term sum (forces eframe realloc path)
|
||||
x = 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20;
|
||||
tap_ensure(x, 210, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## logical AND -- HAWK_EF_LAND_LEFT / HAWK_EF_LAND_RIGHT
|
||||
## -----------------------------------------------------------------------
|
||||
function test_logical_and( r, se)
|
||||
{
|
||||
## short-circuit: right never evaluated when left is false
|
||||
se = 0;
|
||||
r = 0 && (se = 1);
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(se, 0, @SCRIPTNAME, @SCRIPTLINE); ## right NOT evaluated
|
||||
|
||||
## both sides evaluated when left is true
|
||||
se = 0;
|
||||
r = 1 && (se = 99);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(se, 99, @SCRIPTNAME, @SCRIPTLINE); ## right WAS evaluated
|
||||
|
||||
## false right side
|
||||
r = 1 && 0;
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## chained AND
|
||||
r = 1 && 1 && 1;
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = 1 && 1 && 0;
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## AND with complex subexpressions
|
||||
r = (2 + 3 == 5) && (10 / 2 == 5);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = (2 + 3 == 5) && (10 / 2 == 4);
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## logical OR -- HAWK_EF_LOR_LEFT / HAWK_EF_LOR_RIGHT
|
||||
## -----------------------------------------------------------------------
|
||||
function test_logical_or( r, se)
|
||||
{
|
||||
## short-circuit: right never evaluated when left is true
|
||||
se = 0;
|
||||
r = 1 || (se = 1);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(se, 0, @SCRIPTNAME, @SCRIPTLINE); ## right NOT evaluated
|
||||
|
||||
## both sides evaluated when left is false
|
||||
se = 0;
|
||||
r = 0 || (se = 77);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(se, 77, @SCRIPTNAME, @SCRIPTLINE); ## right WAS evaluated
|
||||
|
||||
## false || false
|
||||
r = 0 || 0;
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## chained OR
|
||||
r = 0 || 0 || 1;
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = 0 || 0 || 0;
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## OR with complex subexpressions
|
||||
r = (1 == 2) || (3 * 3 == 9);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = (1 == 2) || (2 + 2 == 5);
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## mixed AND/OR with nested short-circuit
|
||||
## -----------------------------------------------------------------------
|
||||
function test_logical_mixed( r, se)
|
||||
{
|
||||
r = (1 && 1) || (0 && 1);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = (0 || 0) && (1 || 0);
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = (0 || 1) && (1 && 1) && (0 || 1);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## right side of AND is never reached because left is short-circuit false
|
||||
se = 0;
|
||||
r = (0 && 1) || (se = 5);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(se, 5, @SCRIPTNAME, @SCRIPTLINE); ## OR's right WAS evaluated
|
||||
|
||||
## right side of OR never reached
|
||||
se = 0;
|
||||
r = (1 || (se = 3)) && 1;
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(se, 0, @SCRIPTNAME, @SCRIPTLINE); ## OR's right NOT evaluated
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## unary operators -- HAWK_EF_UNARY
|
||||
## -----------------------------------------------------------------------
|
||||
function test_unary( x)
|
||||
{
|
||||
x = 5;
|
||||
tap_ensure(-x, -5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(+x, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(!x, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(!0, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(~0, -1, @SCRIPTNAME, @SCRIPTLINE); ## bitwise NOT
|
||||
|
||||
## nested unary operators (each adds a UNARY frame)
|
||||
tap_ensure(-(-x), 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(!!x, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(!!!x, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(~(~0), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## unary applied to binary subexpression
|
||||
tap_ensure(-(2 + 3), -5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(!(3 < 2), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(-(2 * 3), -6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(~(0xF0 & 0xFF), -241, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## conditional (ternary) -- HAWK_EF_CND
|
||||
## -----------------------------------------------------------------------
|
||||
function test_conditional( a, b, x)
|
||||
{
|
||||
a = 10; b = 20;
|
||||
|
||||
## basic true/false branch selection
|
||||
tap_ensure((a < b ? "lt" : "ge"), "lt", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((a > b ? "gt" : "le"), "le", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((a == 10 ? a : b), 10, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((a == 99 ? a : b), 20, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## nested ternary (each level adds a CND frame)
|
||||
x = (a < b) ? (b < 30 ? "lt30" : "ge30") : "no";
|
||||
tap_ensure(x, "lt30", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = (a > b) ? "no" : (b > 15 ? "gt15" : "le15");
|
||||
tap_ensure(x, "gt15", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## ternary with binary expressions in all three positions
|
||||
x = (a + b == 30) ? (a * b) : (a - b);
|
||||
tap_ensure(x, 200, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = (a + b == 99) ? (a * b) : (a - b);
|
||||
tap_ensure(x, -10, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## ternary result used in larger expression
|
||||
tap_ensure((a < b ? a : b) + (a > b ? a : b), 30, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## ternary inside AND/OR
|
||||
tap_ensure((1 && (a < b ? 1 : 0)), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((0 || (a > b ? 1 : 0)), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## simple assignment -- HAWK_EF_ASS_RHS (opcode == NONE path)
|
||||
## -----------------------------------------------------------------------
|
||||
function test_simple_assign( x, y, z)
|
||||
{
|
||||
x = 42;
|
||||
tap_ensure(x, 42, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## assignment with complex RHS (exercises BIN/UNARY/CND inside ASS_RHS)
|
||||
x = 3 * 4 + 5;
|
||||
tap_ensure(x, 17, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = (2 < 3 ? 10 : 20) + 5;
|
||||
tap_ensure(x, 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = !(1 == 2);
|
||||
tap_ensure(x, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## chained assignment (right-to-left: z=7, y=7, x=7)
|
||||
x = y = z = 7;
|
||||
tap_ensure(x, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(y, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(z, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## assignment used as expression in larger context
|
||||
tap_ensure((x = 5) + 3, 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(x, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## compound assignment -- HAWK_EF_ASS_LHS (opcode != NONE path)
|
||||
## -----------------------------------------------------------------------
|
||||
function test_compound_assign( x)
|
||||
{
|
||||
x = 10;
|
||||
x += 5; tap_ensure(x, 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x -= 3; tap_ensure(x, 12, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x *= 4; tap_ensure(x, 48, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x /= 6; tap_ensure(x, 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x %= 3; tap_ensure(x, 2, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x ^= 8; tap_ensure(x, 256, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x \= 10; tap_ensure(x, 25, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## compound with complex RHS (BIN evaluator inside ASS_RHS)
|
||||
x = 5;
|
||||
x += 2 * 3; tap_ensure(x, 11, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = 100;
|
||||
x -= (3 + 7); tap_ensure(x, 90, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
x = 4;
|
||||
x *= (1 + 1); tap_ensure(x, 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## bitwise compound assignments
|
||||
x = 0xFF;
|
||||
x &= 0x0F; tap_ensure(x, 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x = 0xF0;
|
||||
x |= 0x0F; tap_ensure(x, 255, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x = 0xFF;
|
||||
x ^^= 0x0F; tap_ensure(x, 240, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x = 1;
|
||||
x <<= 4; tap_ensure(x, 16, @SCRIPTNAME, @SCRIPTLINE);
|
||||
x >>= 2; tap_ensure(x, 4, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## string concatenation compound assignment
|
||||
x = "hello";
|
||||
x %%= " " "world";
|
||||
tap_ensure(x, "hello world", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((x %%= "!"), "hello world!", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(x, "hello world!", @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## function calls with complex argument expressions
|
||||
## (exercises push_arg_from_nde_xstack for each argument)
|
||||
## -----------------------------------------------------------------------
|
||||
function add3(a, b, c) { return a + b + c; }
|
||||
function mul_add(a, b, c) { return a * b + c; }
|
||||
function identity(x) { return x; }
|
||||
function choose(flag, a, b){ return flag ? a : b; }
|
||||
function noop() { return 0; }
|
||||
|
||||
function test_fncall_args( r, tmp)
|
||||
{
|
||||
## args are binary expressions
|
||||
r = add3(1 + 2, 3 * 4, 5 - 1);
|
||||
tap_ensure(r, 19, @SCRIPTNAME, @SCRIPTLINE); ## 3 + 12 + 4
|
||||
|
||||
## arg is a conditional
|
||||
r = choose(1 > 0, "yes", "no");
|
||||
tap_ensure(r, "yes", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = choose(0 > 1, "yes", "no");
|
||||
tap_ensure(r, "no", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## arg is a unary expression
|
||||
r = identity(-(3 + 4));
|
||||
tap_ensure(r, -7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## arg is itself a function call with complex args
|
||||
r = identity(add3(1, 2, 3));
|
||||
tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## arg mixing AND with function call
|
||||
r = choose(1 && 1, add3(1, 2, 3), 0);
|
||||
tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = choose(1 && 0, add3(1, 2, 3), 99);
|
||||
tap_ensure(r, 99, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## arg that is an assignment expression (side-effect)
|
||||
tmp = 0;
|
||||
r = add3((tmp = 10), tmp + 1, tmp + 2);
|
||||
tap_ensure(r, 33, @SCRIPTNAME, @SCRIPTLINE); ## 10 + 11 + 12
|
||||
tap_ensure(tmp, 10, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## deeply nested call in arg
|
||||
r = mul_add(add3(1, 1, 1), identity(4), noop() + 2);
|
||||
tap_ensure(r, 14, @SCRIPTNAME, @SCRIPTLINE); ## 3*4 + 2
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## recursive user-defined functions
|
||||
## (each call goes through evalcall/evalcall_xstack)
|
||||
## -----------------------------------------------------------------------
|
||||
function fib(n) { return n <= 1 ? n : fib(n - 1) + fib(n - 2); }
|
||||
function fact(n) { return n <= 1 ? 1 : n * fact(n - 1); }
|
||||
function sum_to(n) { return n <= 0 ? 0 : n + sum_to(n - 1); }
|
||||
function ack(m, n)
|
||||
{
|
||||
if (m == 0) return n + 1;
|
||||
if (n == 0) return ack(m - 1, 1);
|
||||
return ack(m - 1, ack(m, n - 1));
|
||||
}
|
||||
|
||||
function test_recursive()
|
||||
{
|
||||
@local r;
|
||||
|
||||
tap_ensure(fib(0), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(fib(1), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(fib(10), 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(fib(15), 610, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
tap_ensure(fact(0), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(fact(1), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(fact(10), 3628800, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
tap_ensure(sum_to(0), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(sum_to(100), 5050, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## Ackermann: moderate values to avoid stack overflow
|
||||
tap_ensure(ack(0, 0), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(ack(1, 1), 3, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(ack(2, 2), 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(ack(3, 3), 61, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## deeply nested mixed expressions
|
||||
## (combines BIN, UNARY, CND, ASS — many eframe levels at once)
|
||||
## -----------------------------------------------------------------------
|
||||
function test_deep_mixed()
|
||||
{
|
||||
@local t, a, b, c, x;
|
||||
|
||||
a = 3; b = 4; c = 5;
|
||||
|
||||
## Pythagorean triple check
|
||||
x = (a*a + b*b == c*c) ? "right" : "wrong";
|
||||
tap_ensure(x, "right", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## deeply nested: binary inside conditional inside assignment
|
||||
x = (a < b) ? (b < c ? a + b + c : a * b) : (a - b) * c;
|
||||
tap_ensure(x, 12, @SCRIPTNAME, @SCRIPTLINE); ## a+b+c = 12
|
||||
|
||||
## right-associated depth 10
|
||||
x = (1+(2+(3+(4+(5+(6+(7+(8+(9+10)))))))));
|
||||
tap_ensure(x, 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## logical chains mixed with arithmetic
|
||||
x = (a > 0 && b > 0 && c > 0) ? a * b * c : 0;
|
||||
tap_ensure(x, 60, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## unary inside conditional inside AND
|
||||
x = (!(a > b)) && (-(a - b) > 0);
|
||||
tap_ensure(x, 1, @SCRIPTNAME, @SCRIPTLINE); ## !(3>4)=1, -(3-4)=1 > 0
|
||||
|
||||
## assignment inside binary
|
||||
x = (t = a + b) * (t - a);
|
||||
tap_ensure(x, 28, @SCRIPTNAME, @SCRIPTLINE); ## t=7, 7*4=28
|
||||
tap_ensure(t, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## in operator (delegated to eval_binop_in, not iterative)
|
||||
## Verify the default-case delegation path in eval_expression0_xstack.
|
||||
## -----------------------------------------------------------------------
|
||||
function test_in_operator()
|
||||
{
|
||||
@local m, r;
|
||||
|
||||
m["x"] = 1; m["y"] = 2;
|
||||
|
||||
tap_ensure(("x" in m), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(("z" in m), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## 'in' inside AND/OR (both iterative and delegated evaluators)
|
||||
tap_ensure((("x" in m) && ("y" in m)), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((("x" in m) && ("z" in m)), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure((("z" in m) || ("x" in m)), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## 'in' inside conditional
|
||||
r = ("x" in m) ? m["x"] : -1;
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = ("z" in m) ? m["z"] : -1;
|
||||
tap_ensure(r, -1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## 'in' inside unary
|
||||
tap_ensure(!("z" in m), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(!("x" in m), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## pre/post increment and decrement
|
||||
## (delegated to original eval_expression0 via default: branch)
|
||||
## -----------------------------------------------------------------------
|
||||
function test_incr_decr( x, r)
|
||||
{
|
||||
x = 5;
|
||||
r = ++x; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(x, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = x++; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE); ## returns old value
|
||||
tap_ensure(x, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = --x; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(x, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = x--; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE); ## returns old value
|
||||
tap_ensure(x, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## incr/decr result used in binary expression
|
||||
x = 10;
|
||||
r = (++x) + (++x);
|
||||
tap_ensure(r, 23, @SCRIPTNAME, @SCRIPTLINE); ## 11 + 12
|
||||
tap_ensure(x, 12, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## positional variable ($n) — delegated path
|
||||
## -----------------------------------------------------------------------
|
||||
function test_positional()
|
||||
{
|
||||
@local r;
|
||||
|
||||
$1 = "hello";
|
||||
$2 = "world";
|
||||
r = $1 " " $2;
|
||||
tap_ensure(r, "hello world", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## positional in conditional (force numeric comparison with +0)
|
||||
$1 = 10;
|
||||
r = ($1 + 0 > 5 ? $1 * 2 : $1 / 2);
|
||||
tap_ensure(r, 20, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## positional in compound assignment
|
||||
$1 = 3;
|
||||
$1 += 7;
|
||||
tap_ensure($1, 10, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
## -----------------------------------------------------------------------
|
||||
## match/no-match operators (delegated to eval_binop_ma / eval_binop_nm)
|
||||
## -----------------------------------------------------------------------
|
||||
function test_match_ops()
|
||||
{
|
||||
@local r;
|
||||
|
||||
r = ("hello" ~ /ell/);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = ("hello" ~ /xyz/);
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = ("hello" !~ /xyz/);
|
||||
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
r = ("hello" !~ /ell/);
|
||||
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## match result in AND/OR
|
||||
tap_ensure(("abc" ~ /a/) && ("xyz" ~ /x/), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(("abc" ~ /z/) || ("xyz" ~ /x/), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
## match result in conditional
|
||||
r = ("hawk" ~ /awk/) ? "yes" : "no";
|
||||
tap_ensure(r, "yes", @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
test_binary_arith();
|
||||
test_binary_cmp();
|
||||
test_binary_bitwise();
|
||||
test_binary_chain();
|
||||
test_logical_and();
|
||||
test_logical_or();
|
||||
test_logical_mixed();
|
||||
test_unary();
|
||||
test_conditional();
|
||||
test_simple_assign();
|
||||
test_compound_assign();
|
||||
test_fncall_args();
|
||||
test_recursive();
|
||||
test_deep_mixed();
|
||||
test_in_operator();
|
||||
test_incr_decr();
|
||||
test_positional();
|
||||
test_match_ops();
|
||||
tap_end();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user