Compare commits
13
Commits
4b4238dc50
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d17f1e708 | ||
|
|
f99a8c87f0 | ||
|
|
7be5d0fe61 | ||
|
|
baa01b22e3 | ||
|
|
58d1234020 | ||
|
|
bcdc7d8d36 | ||
|
|
1a8cc6ef43 | ||
|
|
15b42bc269 | ||
|
|
992b1344a8 | ||
|
|
27115ca792 | ||
|
|
05b7e3f728 | ||
|
|
e63dc2c2a0 | ||
|
|
92caa7e8db |
@@ -249,8 +249,8 @@ static int handle_logopt (hak_t* hak, const hak_bch_t* logstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fname.ptr = (hak_bch_t*)logstr;
|
fname.ptr = (hak_bch_t*)logstr;
|
||||||
hak_setoption (hak, HAK_LOG_TARGET_BCS, &fname);
|
hak_setoption (hak, HAK_OPT_LOG_TARGET_BCS, &fname);
|
||||||
hak_setoption (hak, HAK_LOG_MASK, &logmask);
|
hak_setoption (hak, HAK_OPT_LOG_MASK, &logmask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,9 +280,9 @@ static int handle_dbgopt (hak_t* hak, const hak_bch_t* str)
|
|||||||
}
|
}
|
||||||
while (cm);
|
while (cm);
|
||||||
|
|
||||||
hak_getoption(hak, HAK_TRAIT, &trait);
|
hak_getoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
trait |= dbgopt;
|
trait |= dbgopt;
|
||||||
hak_setoption(hak, HAK_TRAIT, &trait);
|
hak_setoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -303,19 +303,19 @@ typedef void(*signal_handler_t)(int);
|
|||||||
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
||||||
static void handle_sigint (int sig)
|
static void handle_sigint (int sig)
|
||||||
{
|
{
|
||||||
if (g_hak) hak_abort (g_hak);
|
if (g_hak) hak_abort(g_hak);
|
||||||
}
|
}
|
||||||
#elif defined(macintosh)
|
#elif defined(macintosh)
|
||||||
/* TODO */
|
/* TODO */
|
||||||
#elif defined(SA_SIGINFO)
|
#elif defined(SA_SIGINFO)
|
||||||
static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx)
|
static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx)
|
||||||
{
|
{
|
||||||
if (g_hak) hak_abort (g_hak);
|
if (g_hak) hak_abort(g_hak);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void handle_sigint (int sig)
|
static void handle_sigint (int sig)
|
||||||
{
|
{
|
||||||
if (g_hak) hak_abort (g_hak);
|
if (g_hak) hak_abort(g_hak);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@ static void set_signal (int sig, signal_handler_t handler)
|
|||||||
#else
|
#else
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
memset (&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
/*sa.sa_handler = handler;*/
|
/*sa.sa_handler = handler;*/
|
||||||
#if defined(SA_SIGINFO)
|
#if defined(SA_SIGINFO)
|
||||||
sa.sa_flags = SA_SIGINFO;
|
sa.sa_flags = SA_SIGINFO;
|
||||||
@@ -336,16 +336,16 @@ static void set_signal (int sig, signal_handler_t handler)
|
|||||||
#else
|
#else
|
||||||
sa.sa_handler = handler;
|
sa.sa_handler = handler;
|
||||||
#endif
|
#endif
|
||||||
sigemptyset (&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
|
|
||||||
sigaction (sig, &sa, NULL);
|
sigaction(sig, &sa, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_signal_to_default (int sig)
|
static void set_signal_to_default (int sig)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
||||||
signal (sig, SIG_DFL);
|
signal(sig, SIG_DFL);
|
||||||
#elif defined(macintosh)
|
#elif defined(macintosh)
|
||||||
/* TODO: implement this */
|
/* TODO: implement this */
|
||||||
#else
|
#else
|
||||||
@@ -354,27 +354,27 @@ static void set_signal_to_default (int sig)
|
|||||||
memset (&sa, 0, sizeof(sa));
|
memset (&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
sigemptyset (&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
|
|
||||||
sigaction (sig, &sa, NULL);
|
sigaction(sig, &sa, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_signal_to_ignore (int sig)
|
static void set_signal_to_ignore (int sig)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
||||||
signal (sig, SIG_IGN);
|
signal(sig, SIG_IGN);
|
||||||
#elif defined(macintosh)
|
#elif defined(macintosh)
|
||||||
/* TODO: implement this */
|
/* TODO: implement this */
|
||||||
#else
|
#else
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
memset (&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = SIG_IGN;
|
sa.sa_handler = SIG_IGN;
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
sigemptyset (&sa.sa_mask);
|
sigemptyset (&sa.sa_mask);
|
||||||
|
|
||||||
sigaction (sig, &sa, NULL);
|
sigaction(sig, &sa, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,6 +865,7 @@ int main (int argc, char* argv[])
|
|||||||
{ ":debug", '\0' },
|
{ ":debug", '\0' },
|
||||||
#endif
|
#endif
|
||||||
{ ":heapsize", '\0' },
|
{ ":heapsize", '\0' },
|
||||||
|
{ ":incdirs", 'I' },
|
||||||
{ ":log", 'l' },
|
{ ":log", 'l' },
|
||||||
{ "info", '\0' },
|
{ "info", '\0' },
|
||||||
{ ":modlibdirs", '\0' },
|
{ ":modlibdirs", '\0' },
|
||||||
@@ -873,7 +874,7 @@ int main (int argc, char* argv[])
|
|||||||
};
|
};
|
||||||
static hak_bopt_t opt =
|
static hak_bopt_t opt =
|
||||||
{
|
{
|
||||||
"l:v",
|
"I:l:v",
|
||||||
lopt
|
lopt
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -882,6 +883,7 @@ int main (int argc, char* argv[])
|
|||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
int show_info = 0;
|
int show_info = 0;
|
||||||
const char* modlibdirs = HAK_NULL;
|
const char* modlibdirs = HAK_NULL;
|
||||||
|
const char* incdirs = HAK_NULL;
|
||||||
|
|
||||||
#if defined(HAK_BUILD_DEBUG)
|
#if defined(HAK_BUILD_DEBUG)
|
||||||
const char* dbgopt = HAK_NULL;
|
const char* dbgopt = HAK_NULL;
|
||||||
@@ -896,6 +898,7 @@ int main (int argc, char* argv[])
|
|||||||
fprintf(stderr, "Usage: %s [options] script-filename [output-filename]\n", argv[0]);
|
fprintf(stderr, "Usage: %s [options] script-filename [output-filename]\n", argv[0]);
|
||||||
fprintf(stderr, "Options are:\n");
|
fprintf(stderr, "Options are:\n");
|
||||||
fprintf(stderr, " --info show build information\n");
|
fprintf(stderr, " --info show build information\n");
|
||||||
|
fprintf(stderr, " -I, --incdirs string specify the list of include directories\n");
|
||||||
fprintf(stderr, " -l, --log string specify the log file path and options\n");
|
fprintf(stderr, " -l, --log string specify the log file path and options\n");
|
||||||
fprintf(stderr, " --modlibdirs string specify directories to load modules from\n");
|
fprintf(stderr, " --modlibdirs string specify directories to load modules from\n");
|
||||||
fprintf(stderr, " -v show verbose messages\n");
|
fprintf(stderr, " -v show verbose messages\n");
|
||||||
@@ -907,6 +910,10 @@ int main (int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
case 'I':
|
||||||
|
incdirs = opt.arg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
logopt = opt.arg;
|
logopt = opt.arg;
|
||||||
break;
|
break;
|
||||||
@@ -980,15 +987,15 @@ int main (int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
hak_oow_t tab_size;
|
hak_oow_t tab_size;
|
||||||
tab_size = HAK_DFL_SYMTAB_SIZE;
|
tab_size = HAK_DFL_SYMTAB_SIZE;
|
||||||
hak_setoption (hak, HAK_SYMTAB_SIZE, &tab_size);
|
hak_setoption (hak, HAK_OPT_SYMTAB_SIZE, &tab_size);
|
||||||
tab_size = HAK_DFL_SYSDIC_SIZE;
|
tab_size = HAK_DFL_SYSDIC_SIZE;
|
||||||
hak_setoption (hak, HAK_SYSDIC_SIZE, &tab_size);
|
hak_setoption (hak, HAK_OPT_SYSDIC_SIZE, &tab_size);
|
||||||
tab_size = HAK_DFL_PROCSTK_SIZE; /* TODO: choose a better stack size or make this user specifiable */
|
tab_size = HAK_DFL_PROCSTK_SIZE; /* TODO: choose a better stack size or make this user specifiable */
|
||||||
hak_setoption (hak, HAK_PROCSTK_SIZE, &tab_size);
|
hak_setoption (hak, HAK_OPT_PROCSTK_SIZE, &tab_size);
|
||||||
tab_size = HAK_DFL_EXSTK_SIZE; /* TODO: choose a better stack size or make this user specifiable */
|
tab_size = HAK_DFL_EXSTK_SIZE; /* TODO: choose a better stack size or make this user specifiable */
|
||||||
hak_setoption (hak, HAK_EXSTK_SIZE, &tab_size);
|
hak_setoption (hak, HAK_OPT_EXSTK_SIZE, &tab_size);
|
||||||
tab_size = HAK_DFL_CLSTK_SIZE; /* TODO: choose a better stack size or make this user specifiable */
|
tab_size = HAK_DFL_CLSTK_SIZE; /* TODO: choose a better stack size or make this user specifiable */
|
||||||
hak_setoption (hak, HAK_CLSTK_SIZE, &tab_size);
|
hak_setoption (hak, HAK_OPT_CLSTK_SIZE, &tab_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -997,34 +1004,29 @@ int main (int argc, char* argv[])
|
|||||||
/*trait |= HAK_TRAIT_NOGC;*/
|
/*trait |= HAK_TRAIT_NOGC;*/
|
||||||
trait |= HAK_TRAIT_AWAIT_PROCS;
|
trait |= HAK_TRAIT_AWAIT_PROCS;
|
||||||
trait |= HAK_TRAIT_LANG_ENABLE_EOL;
|
trait |= HAK_TRAIT_LANG_ENABLE_EOL;
|
||||||
hak_setoption (hak, HAK_TRAIT, &trait);
|
hak_setoption (hak, HAK_OPT_TRAIT, &trait);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incdirs)
|
||||||
|
{
|
||||||
|
/* the option is stored in both encodings, so the byte form from
|
||||||
|
* the command line goes in as is - no conversion needed here. */
|
||||||
|
if (hak_setoption(hak, HAK_OPT_INCDIRS_BCSTR, incdirs) <= -1)
|
||||||
|
{
|
||||||
|
hak_logbfmt(hak, HAK_LOG_STDERR,"ERROR: cannot set incdirs - [%d] %js\n", hak_geterrnum(hak), hak_geterrmsg(hak));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modlibdirs)
|
if (modlibdirs)
|
||||||
{
|
{
|
||||||
#if defined(HAK_OOCH_IS_UCH)
|
/* the option is stored in both encodings, so the byte form from
|
||||||
hak_ooch_t* tmp;
|
* the command line goes in as is - no conversion needed here. */
|
||||||
tmp = hak_dupbtoucstr(hak, modlibdirs, HAK_NULL);
|
if (hak_setoption(hak, HAK_OPT_MODLIBDIRS_BCSTR, modlibdirs) <= -1)
|
||||||
if (HAK_UNLIKELY(!tmp))
|
|
||||||
{
|
|
||||||
hak_logbfmt(hak, HAK_LOG_STDERR,"ERROR: cannot duplicate modlibdirs - [%d] %js\n", hak_geterrnum(hak), hak_geterrmsg(hak));
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hak_setoption(hak, HAK_MOD_LIBDIRS, tmp) <= -1)
|
|
||||||
{
|
|
||||||
hak_logbfmt(hak, HAK_LOG_STDERR,"ERROR: cannot set modlibdirs - [%d] %js\n", hak_geterrnum(hak), hak_geterrmsg(hak));
|
|
||||||
hak_freemem(hak, tmp);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
hak_freemem(hak, tmp);
|
|
||||||
#else
|
|
||||||
if (hak_setoption(hak, HAK_MOD_LIBDIRS, modlibdirs) <= -1)
|
|
||||||
{
|
{
|
||||||
hak_logbfmt(hak, HAK_LOG_STDERR,"ERROR: cannot set modlibdirs - [%d] %js\n", hak_geterrnum(hak), hak_geterrmsg(hak));
|
hak_logbfmt(hak, HAK_LOG_STDERR,"ERROR: cannot set modlibdirs - [%d] %js\n", hak_geterrnum(hak), hak_geterrmsg(hak));
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (&hakcb, 0, HAK_SIZEOF(hakcb));
|
memset (&hakcb, 0, HAK_SIZEOF(hakcb));
|
||||||
@@ -1095,9 +1097,9 @@ int main (int argc, char* argv[])
|
|||||||
// in the non-INTERACTIVE mode, the compiler generates MAKE_BLOCK for lambda functions.
|
// in the non-INTERACTIVE mode, the compiler generates MAKE_BLOCK for lambda functions.
|
||||||
{
|
{
|
||||||
hak_bitmask_t trait;
|
hak_bitmask_t trait;
|
||||||
hak_getoption(hak, HAK_TRAIT, &trait);
|
hak_getoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
trait |= HAK_TRAIT_INTERACTIVE;
|
trait |= HAK_TRAIT_INTERACTIVE;
|
||||||
hak_setoption(hak, HAK_TRAIT, &trait);
|
hak_setoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+216
-15
@@ -4,8 +4,10 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hak"
|
"hak"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
//"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -18,6 +20,9 @@ import (
|
|||||||
`))
|
`))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* 0 means no pre-allocated heap, as in bin/hak.c */
|
||||||
|
const DEFAULT_HEAPSIZE uint = 0
|
||||||
|
|
||||||
/* to be set in build time */
|
/* to be set in build time */
|
||||||
var BINDIR = "."
|
var BINDIR = "."
|
||||||
var SBINDIR = "."
|
var SBINDIR = "."
|
||||||
@@ -25,10 +30,14 @@ var LIBDIR = "."
|
|||||||
var SYSCONFDIR = "."
|
var SYSCONFDIR = "."
|
||||||
|
|
||||||
type Param struct {
|
type Param struct {
|
||||||
log_file string
|
log_target string
|
||||||
|
log_mask hak.BitMask
|
||||||
input_file string
|
input_file string
|
||||||
heapsize uint
|
heapsize uint
|
||||||
modlibdirs string
|
modlibdirs string
|
||||||
|
incdirs string
|
||||||
|
verbose bool
|
||||||
|
show_info bool
|
||||||
fs_usage func()
|
fs_usage func()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +45,93 @@ func empty_usage() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the filter names accepted after the comma in --log, mirroring the xtab
|
||||||
|
* table in handle_logopt() of bin/hak.c. 'and' marks the entries that clear
|
||||||
|
* bits instead of setting them. */
|
||||||
|
type log_filter struct {
|
||||||
|
name string
|
||||||
|
and bool
|
||||||
|
mask hak.BitMask
|
||||||
|
}
|
||||||
|
|
||||||
|
var log_filters = []log_filter{
|
||||||
|
{"", false, 0},
|
||||||
|
|
||||||
|
{"app", false, hak.LOG_APP},
|
||||||
|
{"compiler", false, hak.LOG_COMPILER},
|
||||||
|
{"vm", false, hak.LOG_VM},
|
||||||
|
{"mnemonic", false, hak.LOG_MNEMONIC},
|
||||||
|
{"gc", false, hak.LOG_GC},
|
||||||
|
{"ic", false, hak.LOG_IC},
|
||||||
|
{"primitive", false, hak.LOG_PRIMITIVE},
|
||||||
|
|
||||||
|
/* a specific level */
|
||||||
|
{"fatal", false, hak.LOG_FATAL},
|
||||||
|
{"error", false, hak.LOG_ERROR},
|
||||||
|
{"warn", false, hak.LOG_WARN},
|
||||||
|
{"info", false, hak.LOG_INFO},
|
||||||
|
{"debug", false, hak.LOG_DEBUG},
|
||||||
|
|
||||||
|
/* a specific level or higher */
|
||||||
|
{"fatal+", false, hak.LOG_FATAL},
|
||||||
|
{"error+", false, hak.LOG_FATAL | hak.LOG_ERROR},
|
||||||
|
{"warn+", false, hak.LOG_FATAL | hak.LOG_ERROR | hak.LOG_WARN},
|
||||||
|
{"info+", false, hak.LOG_FATAL | hak.LOG_ERROR | hak.LOG_WARN | hak.LOG_INFO},
|
||||||
|
{"debug+", false, hak.LOG_FATAL | hak.LOG_ERROR | hak.LOG_WARN | hak.LOG_INFO | hak.LOG_DEBUG},
|
||||||
|
|
||||||
|
/* a specific level or lower */
|
||||||
|
{"fatal-", false, hak.LOG_FATAL | hak.LOG_ERROR | hak.LOG_WARN | hak.LOG_INFO | hak.LOG_DEBUG},
|
||||||
|
{"error-", false, hak.LOG_ERROR | hak.LOG_WARN | hak.LOG_INFO | hak.LOG_DEBUG},
|
||||||
|
{"warn-", false, hak.LOG_WARN | hak.LOG_INFO | hak.LOG_DEBUG},
|
||||||
|
{"info-", false, hak.LOG_INFO | hak.LOG_DEBUG},
|
||||||
|
{"debug-", false, hak.LOG_DEBUG},
|
||||||
|
|
||||||
|
/* exclude a specific level */
|
||||||
|
{"-fatal", true, ^hak.LOG_FATAL},
|
||||||
|
{"-error", true, ^hak.LOG_ERROR},
|
||||||
|
{"-warn", true, ^hak.LOG_WARN},
|
||||||
|
{"-info", true, ^hak.LOG_INFO},
|
||||||
|
{"-debug", true, ^hak.LOG_DEBUG},
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split "path,filter,filter" into a target and a log mask. with no comma the
|
||||||
|
* whole string is the target and every level and type is enabled. */
|
||||||
|
func parse_logopt(logstr string) (string, hak.BitMask, error) {
|
||||||
|
var comma int = strings.Index(logstr, ",")
|
||||||
|
var mask hak.BitMask
|
||||||
|
|
||||||
|
if comma < 0 {
|
||||||
|
return logstr, hak.LOG_ALL_LEVELS | hak.LOG_ALL_TYPES, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range strings.Split(logstr[comma+1:], ",") {
|
||||||
|
var i int
|
||||||
|
for i = 0; i < len(log_filters); i++ {
|
||||||
|
if log_filters[i].name == f {
|
||||||
|
if log_filters[i].and {
|
||||||
|
mask &= log_filters[i].mask
|
||||||
|
} else {
|
||||||
|
mask |= log_filters[i].mask
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i >= len(log_filters) {
|
||||||
|
return "", 0, fmt.Errorf("unrecognized log filter - %s - in %s", f, logstr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nothing selected in a category means everything in that category */
|
||||||
|
if (mask & hak.LOG_ALL_TYPES) == 0 {
|
||||||
|
mask |= hak.LOG_ALL_TYPES
|
||||||
|
}
|
||||||
|
if (mask & hak.LOG_ALL_LEVELS) == 0 {
|
||||||
|
mask |= hak.LOG_ALL_LEVELS
|
||||||
|
}
|
||||||
|
|
||||||
|
return logstr[0:comma], mask, nil
|
||||||
|
}
|
||||||
|
|
||||||
func handle_arguments(param *Param) error {
|
func handle_arguments(param *Param) error {
|
||||||
/*
|
/*
|
||||||
var nargs int = len(os.Args)
|
var nargs int = len(os.Args)
|
||||||
@@ -64,34 +160,110 @@ func handle_arguments(param *Param) error {
|
|||||||
var fs *flag.FlagSet
|
var fs *flag.FlagSet
|
||||||
var heapsize *uint
|
var heapsize *uint
|
||||||
var modlibdirs *string
|
var modlibdirs *string
|
||||||
|
var incdirs *string
|
||||||
var log *string
|
var log *string
|
||||||
|
var verbose *bool
|
||||||
|
var show_info *bool
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
fs = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
fs = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||||
|
|
||||||
heapsize = fs.Uint("heapsize", 0, "specify heap size")
|
/* the same set bin/hak.c accepts. the flag package treats -x and --x
|
||||||
modlibdirs = fs.String("modlibdirs", "", "specify module library directories")
|
* alike, so registering both spellings of a short option is enough to
|
||||||
log = fs.String("log", "", "specify log file")
|
* give -I and --incdirs the same destination. */
|
||||||
|
heapsize = fs.Uint("heapsize", DEFAULT_HEAPSIZE, "specify the heap size in bytes")
|
||||||
|
incdirs = fs.String("incdirs", "", "specify the list of include directories")
|
||||||
|
fs.StringVar(incdirs, "I", "", "specify the list of include directories")
|
||||||
|
log = fs.String("log", "", "specify the log file path and options")
|
||||||
|
fs.StringVar(log, "l", "", "specify the log file path and options")
|
||||||
|
modlibdirs = fs.String("modlibdirs", "", "specify directories to load modules from")
|
||||||
|
verbose = fs.Bool("v", false, "show verbose messages")
|
||||||
|
show_info = fs.Bool("info", false, "show build information")
|
||||||
|
|
||||||
param.fs_usage = fs.Usage
|
param.fs_usage = fs.Usage
|
||||||
fs.Usage = empty_usage // i don't want fs.Parse() print the usage
|
fs.Usage = empty_usage // i don't want fs.Parse() print the usage
|
||||||
|
fs.SetOutput(io.Discard) // nor its own copy of the error, which we report ourselves
|
||||||
err = fs.Parse(os.Args[1:])
|
err = fs.Parse(os.Args[1:])
|
||||||
fs.Usage = param.fs_usage // restore it
|
fs.Usage = param.fs_usage // restore it
|
||||||
|
fs.SetOutput(os.Stderr) // so the restored usage still prints
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("command line error - %s", err.Error())
|
return fmt.Errorf("command line error - %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param.heapsize = *heapsize
|
||||||
|
param.incdirs = *incdirs
|
||||||
|
param.modlibdirs = *modlibdirs
|
||||||
|
param.verbose = *verbose
|
||||||
|
param.show_info = *show_info
|
||||||
|
|
||||||
|
if *log != "" {
|
||||||
|
param.log_target, param.log_mask, err = parse_logopt(*log)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --info answers on its own and needs no script */
|
||||||
|
if param.show_info {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if fs.NArg() < 1 {
|
if fs.NArg() < 1 {
|
||||||
return fmt.Errorf("no input file specified")
|
return fmt.Errorf("no input file specified")
|
||||||
} else if fs.NArg() > 1 {
|
} else if fs.NArg() > 1 {
|
||||||
|
/* bin/hak.c also takes an optional output file as the second
|
||||||
|
* argument, but the go binding attaches the user data streams
|
||||||
|
* through handler objects rather than a path, so there is nothing
|
||||||
|
* to pass it to yet. */
|
||||||
return fmt.Errorf("too many input files specified")
|
return fmt.Errorf("too many input files specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
param.input_file = fs.Arg(0);
|
param.input_file = fs.Arg(0)
|
||||||
param.log_file = *log // TODO: parse the option part (e.g. --log /dev/stderr,debug+)
|
return nil
|
||||||
param.heapsize = *heapsize // TODO: set this to hak
|
}
|
||||||
param.modlibdirs = *modlibdirs // TODO: set this to hak
|
|
||||||
return nil;
|
func start_ticker(x *hak.Hak) func() {
|
||||||
|
var ticker *time.Ticker
|
||||||
|
var ticker_stop chan bool
|
||||||
|
var ticker_done chan bool
|
||||||
|
var stopper func()
|
||||||
|
|
||||||
|
ticker = time.NewTicker(20 * time.Millisecond)
|
||||||
|
ticker_done = make(chan bool)
|
||||||
|
ticker_stop = make(chan bool)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <- ticker_stop:
|
||||||
|
goto done
|
||||||
|
case <- ticker.C:
|
||||||
|
x.RaiseTick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
ticker.Stop()
|
||||||
|
ticker_done <- true
|
||||||
|
}()
|
||||||
|
x.RcvTick(true)
|
||||||
|
|
||||||
|
stopper = func() {
|
||||||
|
x.RcvTick(false)
|
||||||
|
ticker_stop <- true
|
||||||
|
<- ticker_done // wait for the ticker to stop
|
||||||
|
|
||||||
|
// if i don't close the the two channels below, the multiple calls to the
|
||||||
|
// returned stopper function wouldn't cause immediate panic for writing
|
||||||
|
// on a closed channel. but i would still close them as i don't want to
|
||||||
|
// cater for generic use of this function and this function wasn't
|
||||||
|
// written to be generic. i don't care to use any other more advanced
|
||||||
|
// mechanisms. the caller must ensure to call this stopper only once.
|
||||||
|
close(ticker_stop)
|
||||||
|
close(ticker_done)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stopper
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -99,6 +271,7 @@ func main() {
|
|||||||
var x *hak.Hak = nil
|
var x *hak.Hak = nil
|
||||||
var err error = nil
|
var err error = nil
|
||||||
var param Param
|
var param Param
|
||||||
|
var stop_ticker func()
|
||||||
|
|
||||||
var rfh hak.CciFileHandler
|
var rfh hak.CciFileHandler
|
||||||
var sfh hak.UdiFileHandler
|
var sfh hak.UdiFileHandler
|
||||||
@@ -111,20 +284,39 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if param.show_info {
|
||||||
|
fmt.Println(hak.BuildInfo())
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
x, err = hak.New()
|
x, err = hak.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: failed to instantiate hak - %s\n", err.Error())
|
fmt.Printf("ERROR: failed to instantiate hak - %s\n", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if param.log_file != "" {
|
if param.log_target != "" {
|
||||||
x.SetLogMask(^hak.BitMask(0))
|
/* honour both halves of --log. the previous code discarded the path
|
||||||
x.SetLogTarget("/dev/stderr")
|
* and always logged everything to /dev/stderr. */
|
||||||
|
x.SetLogMask(param.log_mask)
|
||||||
|
err = x.SetLogTarget(param.log_target)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR: failed to set log target - %s\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if param.incdirs != "" {
|
||||||
|
x.SetIncDirs(param.incdirs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if param.modlibdirs != "" {
|
||||||
|
x.SetModLibDirs(param.modlibdirs)
|
||||||
}
|
}
|
||||||
|
|
||||||
x.SetTrait(x.GetTrait() | hak.TRAIT_LANG_ENABLE_EOL)
|
x.SetTrait(x.GetTrait() | hak.TRAIT_LANG_ENABLE_EOL)
|
||||||
|
|
||||||
err = x.Ignite(1000000)
|
err = x.Ignite(uintptr(param.heapsize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: failed to ignite - %s\n", err.Error())
|
fmt.Printf("ERROR: failed to ignite - %s\n", err.Error())
|
||||||
goto oops
|
goto oops
|
||||||
@@ -169,16 +361,25 @@ func main() {
|
|||||||
goto oops
|
goto oops
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Decode() writes the bytecode mnemonics through the log, so it only
|
||||||
|
* produces anything when --log selects the mnemonic type. the log mask
|
||||||
|
* is no longer cleared afterwards - doing that silenced --log for the
|
||||||
|
* whole of Execute(). */
|
||||||
x.Decode()
|
x.Decode()
|
||||||
x.SetLogMask(0)
|
|
||||||
|
|
||||||
|
stop_ticker = start_ticker(x)
|
||||||
err = x.Execute()
|
err = x.Execute()
|
||||||
|
stop_ticker()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//fmt.Printf("ERROR: %s[%d:%d] - %s\n", herr.File, herr.Line, herr.Colm, herr.Msg)
|
//fmt.Printf("ERROR: %s[%d:%d] - %s\n", herr.File, herr.Line, herr.Colm, herr.Msg)
|
||||||
fmt.Printf("ERROR: %s\n", err.Error())
|
fmt.Printf("ERROR: %s\n", err.Error())
|
||||||
goto oops
|
goto oops
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if param.verbose {
|
||||||
|
fmt.Printf("EXECUTION OK - %s\n", param.input_file)
|
||||||
|
}
|
||||||
|
|
||||||
x.Close()
|
x.Close()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -96,6 +97,8 @@ func hak_go_cci_handler(c *C.hak_t, cmd C.hak_io_cmd_t, arg unsafe.Pointer) C.in
|
|||||||
var (
|
var (
|
||||||
ioarg *C.hak_io_cciarg_t
|
ioarg *C.hak_io_cciarg_t
|
||||||
name string
|
name string
|
||||||
|
raw string
|
||||||
|
try_incdirs bool
|
||||||
fd int
|
fd int
|
||||||
tptr unsafe.Pointer
|
tptr unsafe.Pointer
|
||||||
tlen C.size_t
|
tlen C.size_t
|
||||||
@@ -110,33 +113,64 @@ func hak_go_cci_handler(c *C.hak_t, cmd C.hak_io_cmd_t, arg unsafe.Pointer) C.in
|
|||||||
// actual included stream
|
// actual included stream
|
||||||
var includer_name string
|
var includer_name string
|
||||||
|
|
||||||
name = string(ucstr_to_rune_slice(ioarg.name))
|
raw = string(ucstr_to_rune_slice(ioarg.name))
|
||||||
|
|
||||||
tptr = ioarg.includer.handle
|
tptr = ioarg.includer.handle
|
||||||
tlen = *(*C.size_t)(unsafe.Pointer(uintptr(tptr) + unsafe.Sizeof(fd)))
|
tlen = *(*C.size_t)(unsafe.Pointer(uintptr(tptr) + unsafe.Sizeof(fd)))
|
||||||
|
|
||||||
includer_name = C.GoStringN((*C.char)(unsafe.Pointer(uintptr(tptr)+unsafe.Sizeof(fd)+unsafe.Sizeof(tlen))), C.int(tlen))
|
includer_name = C.GoStringN((*C.char)(unsafe.Pointer(uintptr(tptr)+unsafe.Sizeof(fd)+unsafe.Sizeof(tlen))), C.int(tlen))
|
||||||
name = filepath.Join(path.Dir(includer_name), name)
|
name = filepath.Join(path.Dir(includer_name), raw)
|
||||||
|
|
||||||
|
// a name anchored by the author - absolute, or explicitly ./ or
|
||||||
|
// ../ - is meant to resolve against the includer alone. anything
|
||||||
|
// else may fall back to the include directories. this mirrors
|
||||||
|
// what open_cci_stream() does in lib/std.c.
|
||||||
|
try_incdirs = !filepath.IsAbs(raw) &&
|
||||||
|
!strings.HasPrefix(raw, "./") && !strings.HasPrefix(raw, "../")
|
||||||
|
}
|
||||||
|
|
||||||
|
// [NOTE] the open has to happen before the allocation below, because
|
||||||
|
// the include-directory search can settle on a different (and
|
||||||
|
// longer) path than the one first tried, and the block is
|
||||||
|
// sized from the name it ends up storing.
|
||||||
|
if ioarg.includer == nil {
|
||||||
|
fd = -1
|
||||||
|
} else {
|
||||||
|
fd, err = g.io.cci.Open(g, name)
|
||||||
|
if err != nil && try_incdirs {
|
||||||
|
// walk the colon-separated include directories, as the C
|
||||||
|
// reader does. an empty entry means the current directory.
|
||||||
|
for _, dir := range strings.Split(g.GetIncDirs(), ":") {
|
||||||
|
var cand string = filepath.Join(dir, raw)
|
||||||
|
var fd2 int
|
||||||
|
var err2 error
|
||||||
|
|
||||||
|
fd2, err2 = g.io.cci.Open(g, cand)
|
||||||
|
if err2 == nil {
|
||||||
|
// the stored name becomes the includer path for
|
||||||
|
// anything this file includes in turn, so it has to
|
||||||
|
// be the path that actually opened
|
||||||
|
fd, err, name = fd2, nil, cand
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
g.set_errmsg(C.HAK_EIOERR, err.Error())
|
||||||
|
return -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tlen = C.size_t(len(name)) // number of bytes in the string
|
tlen = C.size_t(len(name)) // number of bytes in the string
|
||||||
tptr = C.hak_allocmem(c, C.size_t(unsafe.Sizeof(fd)) + C.size_t(unsafe.Sizeof(tlen)) + tlen)
|
tptr = C.hak_allocmem(c, C.size_t(unsafe.Sizeof(fd)) + C.size_t(unsafe.Sizeof(tlen)) + tlen)
|
||||||
if tptr == nil {
|
if tptr == nil {
|
||||||
|
if ioarg.includer != nil {
|
||||||
|
g.io.cci.Close(fd)
|
||||||
|
}
|
||||||
g.set_errmsg(C.HAK_ESYSMEM, "cci name allocation failure")
|
g.set_errmsg(C.HAK_ESYSMEM, "cci name allocation failure")
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ioarg.includer == nil {
|
|
||||||
fd = -1
|
|
||||||
} else {
|
|
||||||
fd, err = g.io.cci.Open(g, name)
|
|
||||||
if err != nil {
|
|
||||||
g.set_errmsg(C.HAK_EIOERR, err.Error())
|
|
||||||
C.hak_freemem(c, tptr)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// | fd | length | name bytes of the length |
|
// | fd | length | name bytes of the length |
|
||||||
*(*int)(tptr) = fd;
|
*(*int)(tptr) = fd;
|
||||||
*(*C.size_t)(unsafe.Pointer(uintptr(tptr)+unsafe.Sizeof(fd))) = tlen;
|
*(*C.size_t)(unsafe.Pointer(uintptr(tptr)+unsafe.Sizeof(fd))) = tlen;
|
||||||
|
|||||||
@@ -76,6 +76,38 @@ type BitMask C.hak_bitmask_t
|
|||||||
|
|
||||||
const TRAIT_LANG_ENABLE_EOL BitMask = C.HAK_TRAIT_LANG_ENABLE_EOL
|
const TRAIT_LANG_ENABLE_EOL BitMask = C.HAK_TRAIT_LANG_ENABLE_EOL
|
||||||
|
|
||||||
|
/* log levels */
|
||||||
|
const (
|
||||||
|
LOG_DEBUG BitMask = C.HAK_LOG_DEBUG
|
||||||
|
LOG_INFO BitMask = C.HAK_LOG_INFO
|
||||||
|
LOG_WARN BitMask = C.HAK_LOG_WARN
|
||||||
|
LOG_ERROR BitMask = C.HAK_LOG_ERROR
|
||||||
|
LOG_FATAL BitMask = C.HAK_LOG_FATAL
|
||||||
|
)
|
||||||
|
|
||||||
|
/* log types */
|
||||||
|
const (
|
||||||
|
LOG_UNTYPED BitMask = C.HAK_LOG_UNTYPED
|
||||||
|
LOG_COMPILER BitMask = C.HAK_LOG_COMPILER
|
||||||
|
LOG_VM BitMask = C.HAK_LOG_VM
|
||||||
|
LOG_MNEMONIC BitMask = C.HAK_LOG_MNEMONIC
|
||||||
|
LOG_GC BitMask = C.HAK_LOG_GC
|
||||||
|
LOG_IC BitMask = C.HAK_LOG_IC
|
||||||
|
LOG_PRIMITIVE BitMask = C.HAK_LOG_PRIMITIVE
|
||||||
|
LOG_APP BitMask = C.HAK_LOG_APP
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LOG_ALL_LEVELS BitMask = C.HAK_LOG_ALL_LEVELS
|
||||||
|
LOG_ALL_TYPES BitMask = C.HAK_LOG_ALL_TYPES
|
||||||
|
)
|
||||||
|
|
||||||
|
/* BuildInfo answers how the underlying C library was configured. it mirrors
|
||||||
|
* what bin/hak.c prints for --info. */
|
||||||
|
func BuildInfo() string {
|
||||||
|
return fmt.Sprintf("Configured with: %s %s", C.HAK_CONFIGURE_CMD, C.HAK_CONFIGURE_ARGS)
|
||||||
|
}
|
||||||
|
|
||||||
func deregister_instance(g *Hak) {
|
func deregister_instance(g *Hak) {
|
||||||
if g.inst_no >= 0 {
|
if g.inst_no >= 0 {
|
||||||
inst_table.delete_instance(g.inst_no)
|
inst_table.delete_instance(g.inst_no)
|
||||||
@@ -142,7 +174,7 @@ func (hak *Hak) GetTrait() BitMask {
|
|||||||
var x C.int
|
var x C.int
|
||||||
var log_mask BitMask = 0
|
var log_mask BitMask = 0
|
||||||
|
|
||||||
x = C.hak_getoption(hak.c, C.HAK_TRAIT, unsafe.Pointer(&log_mask))
|
x = C.hak_getoption(hak.c, C.HAK_OPT_TRAIT, unsafe.Pointer(&log_mask))
|
||||||
if x <= -1 {
|
if x <= -1 {
|
||||||
// this must not happen
|
// this must not happen
|
||||||
panic(fmt.Errorf("unable to get log mask - %s", hak.get_errmsg()))
|
panic(fmt.Errorf("unable to get log mask - %s", hak.get_errmsg()))
|
||||||
@@ -154,7 +186,7 @@ func (hak *Hak) GetTrait() BitMask {
|
|||||||
func (hak *Hak) SetTrait(log_mask BitMask) {
|
func (hak *Hak) SetTrait(log_mask BitMask) {
|
||||||
var x C.int
|
var x C.int
|
||||||
|
|
||||||
x = C.hak_setoption(hak.c, C.HAK_TRAIT, unsafe.Pointer(&log_mask))
|
x = C.hak_setoption(hak.c, C.HAK_OPT_TRAIT, unsafe.Pointer(&log_mask))
|
||||||
if x <= -1 {
|
if x <= -1 {
|
||||||
// this must not happen
|
// this must not happen
|
||||||
panic(fmt.Errorf("unable to set log mask - %s", hak.get_errmsg()))
|
panic(fmt.Errorf("unable to set log mask - %s", hak.get_errmsg()))
|
||||||
@@ -165,7 +197,7 @@ func (hak *Hak) GetLogMask() BitMask {
|
|||||||
var x C.int
|
var x C.int
|
||||||
var log_mask BitMask = 0
|
var log_mask BitMask = 0
|
||||||
|
|
||||||
x = C.hak_getoption(hak.c, C.HAK_LOG_MASK, unsafe.Pointer(&log_mask))
|
x = C.hak_getoption(hak.c, C.HAK_OPT_LOG_MASK, unsafe.Pointer(&log_mask))
|
||||||
if x <= -1 {
|
if x <= -1 {
|
||||||
// this must not happen
|
// this must not happen
|
||||||
panic(fmt.Errorf("unable to get log mask - %s", hak.get_errmsg()))
|
panic(fmt.Errorf("unable to get log mask - %s", hak.get_errmsg()))
|
||||||
@@ -177,7 +209,7 @@ func (hak *Hak) GetLogMask() BitMask {
|
|||||||
func (hak *Hak) SetLogMask(log_mask BitMask) {
|
func (hak *Hak) SetLogMask(log_mask BitMask) {
|
||||||
var x C.int
|
var x C.int
|
||||||
|
|
||||||
x = C.hak_setoption(hak.c, C.HAK_LOG_MASK, unsafe.Pointer(&log_mask))
|
x = C.hak_setoption(hak.c, C.HAK_OPT_LOG_MASK, unsafe.Pointer(&log_mask))
|
||||||
if x <= -1 {
|
if x <= -1 {
|
||||||
// this must not happen
|
// this must not happen
|
||||||
panic(fmt.Errorf("unable to set log mask - %s", hak.get_errmsg()))
|
panic(fmt.Errorf("unable to set log mask - %s", hak.get_errmsg()))
|
||||||
@@ -188,27 +220,78 @@ func (hak *Hak) GetLogTarget() string {
|
|||||||
var x C.int
|
var x C.int
|
||||||
var tgt *C.char
|
var tgt *C.char
|
||||||
|
|
||||||
x = C.hak_getoption(hak.c, C.HAK_LOG_TARGET_BCSTR, unsafe.Pointer(&tgt))
|
x = C.hak_getoption(hak.c, C.HAK_OPT_LOG_TARGET_BCSTR, unsafe.Pointer(&tgt))
|
||||||
if x <= -1 {
|
if x <= -1 {
|
||||||
// this must not happen
|
// this must not happen
|
||||||
panic(fmt.Errorf("unable to set log target - %s", hak.get_errmsg()))
|
panic(fmt.Errorf("unable to get log target - %s", hak.get_errmsg()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return C.GoString(tgt)
|
return C.GoString(tgt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hak *Hak) SetLogTarget(target string) {
|
func (hak *Hak) SetLogTarget(target string) error {
|
||||||
var x C.int
|
var x C.int
|
||||||
var tgt *C.char
|
var tgt *C.char
|
||||||
|
|
||||||
tgt = C.CString(target) // TODO: need error check?
|
tgt = C.CString(target) // TODO: need error check?
|
||||||
defer C.free(unsafe.Pointer(tgt))
|
defer C.free(unsafe.Pointer(tgt))
|
||||||
|
|
||||||
x = C.hak_setoption(hak.c, C.HAK_LOG_TARGET_BCSTR, unsafe.Pointer(tgt))
|
x = C.hak_setoption(hak.c, C.HAK_OPT_LOG_TARGET_BCSTR, unsafe.Pointer(tgt))
|
||||||
|
if x <= -1 { return hak.make_errinfo() }
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hak *Hak) GetIncDirs() string {
|
||||||
|
var x C.int
|
||||||
|
var tgt *C.char
|
||||||
|
|
||||||
|
x = C.hak_getoption(hak.c, C.HAK_OPT_INCDIRS_BCSTR, unsafe.Pointer(&tgt))
|
||||||
if x <= -1 {
|
if x <= -1 {
|
||||||
// this must not happen
|
// this must not happen
|
||||||
panic(fmt.Errorf("unable to set log target - %s", hak.get_errmsg()))
|
panic(fmt.Errorf("unable to get include directories - %s", hak.get_errmsg()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return C.GoString(tgt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hak *Hak) SetIncDirs(target string) error {
|
||||||
|
var x C.int
|
||||||
|
var tgt *C.char
|
||||||
|
|
||||||
|
tgt = C.CString(target) // TODO: need error check?
|
||||||
|
defer C.free(unsafe.Pointer(tgt))
|
||||||
|
|
||||||
|
x = C.hak_setoption(hak.c, C.HAK_OPT_INCDIRS_BCSTR, unsafe.Pointer(tgt))
|
||||||
|
if x <= -1 { return hak.make_errinfo() }
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hak *Hak) GetModLibDirs() string {
|
||||||
|
var x C.int
|
||||||
|
var tgt *C.char
|
||||||
|
|
||||||
|
x = C.hak_getoption(hak.c, C.HAK_OPT_MODLIBDIRS_BCSTR, unsafe.Pointer(&tgt))
|
||||||
|
if x <= -1 {
|
||||||
|
// this must not happen
|
||||||
|
panic(fmt.Errorf("unable to get module library directories - %s", hak.get_errmsg()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return C.GoString(tgt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hak *Hak) SetModLibDirs(target string) error {
|
||||||
|
var x C.int
|
||||||
|
var tgt *C.char
|
||||||
|
|
||||||
|
tgt = C.CString(target) // TODO: need error check?
|
||||||
|
defer C.free(unsafe.Pointer(tgt))
|
||||||
|
|
||||||
|
x = C.hak_setoption(hak.c, C.HAK_OPT_MODLIBDIRS_BCSTR, unsafe.Pointer(tgt))
|
||||||
|
if x <= -1 { return hak.make_errinfo() }
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hak *Hak) Ignite(memsize uintptr) error {
|
func (hak *Hak) Ignite(memsize uintptr) error {
|
||||||
@@ -399,6 +482,16 @@ func (hak *Hak) Decode() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hak *Hak) RcvTick(enabled bool) {
|
||||||
|
var i C.int
|
||||||
|
if enabled { i = 1 } else { i = 0 }
|
||||||
|
C.hak_rcvtick(hak.c, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hak *Hak) RaiseTick() {
|
||||||
|
C.hak_raisetick(hak.c)
|
||||||
|
}
|
||||||
|
|
||||||
func (hak *Hak) get_errmsg() string {
|
func (hak *Hak) get_errmsg() string {
|
||||||
return C.GoString(C.hak_geterrbmsg(hak.c))
|
return C.GoString(C.hak_geterrbmsg(hak.c))
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-1
@@ -1341,7 +1341,6 @@ static void yield_process (hak_t* hak, hak_oop_process_t proc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int async_signal_semaphore (hak_t* hak, hak_oop_semaphore_t sem)
|
static int async_signal_semaphore (hak_t* hak, hak_oop_semaphore_t sem)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -5640,6 +5639,11 @@ hak_pfrc_t hak_pf_process_resume (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
|||||||
return HAK_PF_FAILURE;
|
return HAK_PF_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [SPECIAL CASE]
|
||||||
|
* resume_process changes the the active process.
|
||||||
|
* calling this after resume_process() pollutes a wrong stack. place it here */
|
||||||
|
HAK_STACK_SETRET(hak, nargs, prc);
|
||||||
|
|
||||||
resume_process(hak, prc);
|
resume_process(hak, prc);
|
||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -5662,6 +5666,11 @@ hak_pfrc_t hak_pf_process_suspend (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
|||||||
prc = hak->processor->active;
|
prc = hak->processor->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [SPECIAL CASE]
|
||||||
|
* suspend_process changes the the active process.
|
||||||
|
* calling this after suspend_process() pollutes a wrong stack. place it here */
|
||||||
|
HAK_STACK_SETRET(hak, nargs, prc);
|
||||||
|
|
||||||
suspend_process(hak, prc);
|
suspend_process(hak, prc);
|
||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -5684,18 +5693,33 @@ hak_pfrc_t hak_pf_process_terminate (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs
|
|||||||
prc = hak->processor->active;
|
prc = hak->processor->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [SPECIAL CASE]
|
||||||
|
* terminate_process changes the the active process.
|
||||||
|
* calling this after terminate_process() pollutes a wrong stack. place it here */
|
||||||
|
HAK_STACK_SETRET(hak, nargs, prc);
|
||||||
|
|
||||||
terminate_process(hak, prc);
|
terminate_process(hak, prc);
|
||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
hak_pfrc_t hak_pf_process_terminate_all (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_process_terminate_all (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
|
/* [SPECIAL CASE]
|
||||||
|
* terminate_all_processes changes the the active process.
|
||||||
|
* calling this after terminate_all_processes() pollutes a wrong stack. place it here */
|
||||||
|
HAK_STACK_SETRET(hak, nargs, hak->_nil);
|
||||||
|
|
||||||
terminate_all_processes(hak);
|
terminate_all_processes(hak);
|
||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
hak_pfrc_t hak_pf_process_yield (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_process_yield (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
|
/* [SPECIAL CASE]
|
||||||
|
* yield_process changes the the active process.
|
||||||
|
* calling this after yield_process() pollutes a wrong stack. place it here */
|
||||||
|
HAK_STACK_SETRET(hak, nargs, hak->_nil);
|
||||||
|
|
||||||
yield_process(hak, hak->processor->active);
|
yield_process(hak, hak->processor->active);
|
||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -5715,7 +5739,22 @@ hak_pfrc_t hak_pf_semaphore_new (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
|||||||
return HAK_PF_FAILURE;
|
return HAK_PF_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nargs >= 1)
|
||||||
|
{
|
||||||
|
hak_oop_t tmp;
|
||||||
|
tmp = (hak_oop_semaphore_t)HAK_STACK_GETARG(hak, nargs, 0);
|
||||||
|
if (!HAK_OOP_IS_SMOOI(tmp))
|
||||||
|
{
|
||||||
|
hak_seterrbfmt(hak, HAK_EINVAL, "invalid semaphore count - %O", tmp);
|
||||||
|
return HAK_PF_FAILURE;
|
||||||
|
}
|
||||||
|
sem->count = tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
sem->count = HAK_SMOOI_TO_OOP(0);
|
sem->count = HAK_SMOOI_TO_OOP(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: sem->signal_action? */
|
/* TODO: sem->signal_action? */
|
||||||
/* other fields are all set to nil */
|
/* other fields are all set to nil */
|
||||||
|
|
||||||
|
|||||||
@@ -2248,6 +2248,8 @@ hak_pfrc_t hak_pf_nqv (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
|||||||
hak_pfrc_t hak_pf_nql (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_nql (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
hak_pfrc_t hak_pf_nqk (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_nqk (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
|
||||||
|
hak_pfrc_t hak_pf_object_new (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
|
||||||
hak_pfrc_t hak_pf_process_current (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_process_current (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
hak_pfrc_t hak_pf_process_fork (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_process_fork (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
hak_pfrc_t hak_pf_process_resume (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_process_resume (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
@@ -2270,6 +2272,15 @@ hak_pfrc_t hak_pf_semaphore_group_add_semaphore (hak_t* hak, hak_mod_t* mod, hak
|
|||||||
hak_pfrc_t hak_pf_semaphore_group_remove_semaphore (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_semaphore_group_remove_semaphore (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
hak_pfrc_t hak_pf_semaphore_group_wait (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
hak_pfrc_t hak_pf_semaphore_group_wait (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
|
||||||
|
/* the signal primitives live in prim.c but are registered by the sys module,
|
||||||
|
* which reaches them as sys.sig-getfd, sys.sig-get, sys.sig-set, sys.sig-catch
|
||||||
|
* and sys.sig-uncatch */
|
||||||
|
hak_pfrc_t hak_pf_system_get_sigfd (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
hak_pfrc_t hak_pf_system_get_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
hak_pfrc_t hak_pf_system_set_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
hak_pfrc_t hak_pf_system_catch_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
hak_pfrc_t hak_pf_system_uncatch_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs);
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
/* std.c */
|
/* std.c */
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|||||||
@@ -369,9 +369,39 @@ void hak_fini (hak_t* hak)
|
|||||||
hak->option.log_target_b = HAK_NULL;
|
hak->option.log_target_b = HAK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* destroy dynamically allocated options */
|
||||||
for (i = 0; i < HAK_COUNTOF(hak->option.mod); i++)
|
for (i = 0; i < HAK_COUNTOF(hak->option.mod); i++)
|
||||||
{
|
{
|
||||||
if (hak->option.mod[i].ptr) hak_freemem(hak, hak->option.mod[i].ptr);
|
if (hak->option.mod[i].ptr)
|
||||||
|
{
|
||||||
|
hak_freemem(hak, hak->option.mod[i].ptr);
|
||||||
|
hak->option.mod[i].ptr = HAK_NULL;
|
||||||
|
hak->option.mod[i].len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hak->option.modlibdirs_b)
|
||||||
|
{
|
||||||
|
hak_freemem(hak, hak->option.modlibdirs_b);
|
||||||
|
hak->option.modlibdirs_b = HAK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hak->option.modlibdirs_u)
|
||||||
|
{
|
||||||
|
hak_freemem(hak, hak->option.modlibdirs_u);
|
||||||
|
hak->option.modlibdirs_u = HAK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hak->option.incdirs_b)
|
||||||
|
{
|
||||||
|
hak_freemem(hak, hak->option.incdirs_b);
|
||||||
|
hak->option.incdirs_b = HAK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hak->option.incdirs_u)
|
||||||
|
{
|
||||||
|
hak_freemem(hak, hak->option.incdirs_u);
|
||||||
|
hak->option.incdirs_u = HAK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hak->inttostr.xbuf.ptr)
|
if (hak->inttostr.xbuf.ptr)
|
||||||
@@ -449,28 +479,74 @@ static int dup_str_opt (hak_t* hak, const hak_ooch_t* value, hak_oocs_t* tmp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store a string option in both representations at once.
|
||||||
|
*
|
||||||
|
* The consumers of these options are byte oriented - dlopen() and fopen() -
|
||||||
|
* so the bch form is what gets used, and converting once here saves a
|
||||||
|
* conversion on every module load and every include attempt. The uch form is
|
||||||
|
* kept so getoption can answer in either encoding without allocating.
|
||||||
|
*
|
||||||
|
* Both conversions are done before either slot is replaced, so a failure
|
||||||
|
* leaves the previous value in place rather than half-updating it. */
|
||||||
|
static int set_dual_str_opt (hak_t* hak, const void* value, int value_is_bch, hak_bch_t** bp, hak_uch_t** up)
|
||||||
|
{
|
||||||
|
hak_bch_t* v_b;
|
||||||
|
hak_uch_t* v_u;
|
||||||
|
|
||||||
|
if (value_is_bch)
|
||||||
|
{
|
||||||
|
v_b = hak_dupbcstr(hak, (const hak_bch_t*)value, HAK_NULL);
|
||||||
|
if (HAK_UNLIKELY(!v_b)) return -1;
|
||||||
|
|
||||||
|
v_u = hak_dupbtoucstr(hak, (const hak_bch_t*)value, HAK_NULL);
|
||||||
|
if (HAK_UNLIKELY(!v_u))
|
||||||
|
{
|
||||||
|
hak_freemem(hak, v_b);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v_u = hak_dupucstr(hak, (const hak_uch_t*)value, HAK_NULL);
|
||||||
|
if (HAK_UNLIKELY(!v_u)) return -1;
|
||||||
|
|
||||||
|
v_b = hak_duputobcstr(hak, (const hak_uch_t*)value, HAK_NULL);
|
||||||
|
if (HAK_UNLIKELY(!v_b))
|
||||||
|
{
|
||||||
|
hak_freemem(hak, v_u);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*bp) hak_freemem(hak, *bp);
|
||||||
|
if (*up) hak_freemem(hak, *up);
|
||||||
|
*bp = v_b;
|
||||||
|
*up = v_u;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
||||||
{
|
{
|
||||||
hak_cb_t* cb;
|
hak_cb_t* cb;
|
||||||
|
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case HAK_TRAIT:
|
case HAK_OPT_TRAIT:
|
||||||
hak->option.trait = *(const hak_bitmask_t*)value;
|
hak->option.trait = *(const hak_bitmask_t*)value;
|
||||||
#if defined(HAK_BUILD_DEBUG)
|
#if defined(HAK_BUILD_DEBUG)
|
||||||
hak->option.karatsuba_cutoff = ((hak->option.trait & HAK_TRAIT_DEBUG_BIGINT)? HAK_KARATSUBA_CUTOFF_DEBUG: HAK_KARATSUBA_CUTOFF);
|
hak->option.karatsuba_cutoff = ((hak->option.trait & HAK_TRAIT_DEBUG_BIGINT)? HAK_KARATSUBA_CUTOFF_DEBUG: HAK_KARATSUBA_CUTOFF);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HAK_LOG_MASK:
|
case HAK_OPT_LOG_MASK:
|
||||||
hak->option.log_mask = *(const hak_bitmask_t*)value;
|
hak->option.log_mask = *(const hak_bitmask_t*)value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HAK_LOG_MAXCAPA:
|
case HAK_OPT_LOG_MAXCAPA:
|
||||||
hak->option.log_maxcapa = *(hak_oow_t*)value;
|
hak->option.log_maxcapa = *(hak_oow_t*)value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HAK_LOG_TARGET_BCSTR:
|
case HAK_OPT_LOG_TARGET_BCSTR:
|
||||||
{
|
{
|
||||||
hak_bch_t* v1;
|
hak_bch_t* v1;
|
||||||
hak_uch_t* v2;
|
hak_uch_t* v2;
|
||||||
@@ -490,7 +566,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_LOG_TARGET_UCSTR:
|
case HAK_OPT_LOG_TARGET_UCSTR:
|
||||||
{
|
{
|
||||||
hak_uch_t* v1;
|
hak_uch_t* v1;
|
||||||
hak_bch_t* v2;
|
hak_bch_t* v2;
|
||||||
@@ -510,7 +586,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_LOG_TARGET_BCS:
|
case HAK_OPT_LOG_TARGET_BCS:
|
||||||
{
|
{
|
||||||
hak_bch_t* v1;
|
hak_bch_t* v1;
|
||||||
hak_uch_t* v2;
|
hak_uch_t* v2;
|
||||||
@@ -531,7 +607,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_LOG_TARGET_UCS:
|
case HAK_OPT_LOG_TARGET_UCS:
|
||||||
{
|
{
|
||||||
hak_uch_t* v1;
|
hak_uch_t* v1;
|
||||||
hak_bch_t* v2;
|
hak_bch_t* v2;
|
||||||
@@ -552,7 +628,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_SYMTAB_SIZE:
|
case HAK_OPT_SYMTAB_SIZE:
|
||||||
{
|
{
|
||||||
hak_oow_t w;
|
hak_oow_t w;
|
||||||
|
|
||||||
@@ -563,7 +639,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_SYSDIC_SIZE:
|
case HAK_OPT_SYSDIC_SIZE:
|
||||||
{
|
{
|
||||||
hak_oow_t w;
|
hak_oow_t w;
|
||||||
|
|
||||||
@@ -574,7 +650,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_PROCSTK_SIZE:
|
case HAK_OPT_PROCSTK_SIZE:
|
||||||
{
|
{
|
||||||
hak_oow_t w;
|
hak_oow_t w;
|
||||||
|
|
||||||
@@ -585,7 +661,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_EXSTK_SIZE:
|
case HAK_OPT_EXSTK_SIZE:
|
||||||
{
|
{
|
||||||
hak_oow_t w;
|
hak_oow_t w;
|
||||||
|
|
||||||
@@ -596,7 +672,7 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_CLSTK_SIZE:
|
case HAK_OPT_CLSTK_SIZE:
|
||||||
{
|
{
|
||||||
hak_oow_t w;
|
hak_oow_t w;
|
||||||
|
|
||||||
@@ -607,26 +683,41 @@ int hak_setoption (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_MOD_LIBDIRS:
|
case HAK_OPT_MODLIBDIRS_BCSTR:
|
||||||
case HAK_MOD_PREFIX:
|
if (set_dual_str_opt(hak, value, 1, &hak->option.modlibdirs_b, &hak->option.modlibdirs_u) <= -1) return -1;
|
||||||
case HAK_MOD_POSTFIX:
|
break;
|
||||||
|
|
||||||
|
case HAK_OPT_MODLIBDIRS_UCSTR:
|
||||||
|
if (set_dual_str_opt(hak, value, 0, &hak->option.modlibdirs_b, &hak->option.modlibdirs_u) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HAK_OPT_MODPREFIX:
|
||||||
|
case HAK_OPT_MODPOSTFIX:
|
||||||
{
|
{
|
||||||
hak_oocs_t tmp;
|
hak_oocs_t tmp;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
if (dup_str_opt(hak, (const hak_ooch_t*)value, &tmp) <= -1) return -1;
|
if (dup_str_opt(hak, (const hak_ooch_t*)value, &tmp) <= -1) return -1;
|
||||||
|
|
||||||
idx = id - HAK_MOD_LIBDIRS;
|
idx = id - HAK_OPT_MODPREFIX;
|
||||||
if (hak->option.mod[idx].ptr) hak_freemem(hak, hak->option.mod[idx].ptr);
|
if (hak->option.mod[idx].ptr) hak_freemem(hak, hak->option.mod[idx].ptr);
|
||||||
|
|
||||||
hak->option.mod[idx] = tmp;
|
hak->option.mod[idx] = tmp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HAK_MOD_INCTX:
|
case HAK_OPT_MODINCTX:
|
||||||
hak->option.mod_inctx = *(void**)value;
|
hak->option.mod_inctx = *(void**)value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HAK_OPT_INCDIRS_BCSTR:
|
||||||
|
if (set_dual_str_opt(hak, value, 1, &hak->option.incdirs_b, &hak->option.incdirs_u) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HAK_OPT_INCDIRS_UCSTR:
|
||||||
|
if (set_dual_str_opt(hak, value, 0, &hak->option.incdirs_b, &hak->option.incdirs_u) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto einval;
|
goto einval;
|
||||||
}
|
}
|
||||||
@@ -647,65 +738,80 @@ int hak_getoption (hak_t* hak, hak_option_t id, void* value)
|
|||||||
{
|
{
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case HAK_TRAIT:
|
case HAK_OPT_TRAIT:
|
||||||
*(hak_bitmask_t*)value = hak->option.trait;
|
*(hak_bitmask_t*)value = hak->option.trait;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_LOG_MASK:
|
case HAK_OPT_LOG_MASK:
|
||||||
*(hak_bitmask_t*)value = hak->option.log_mask;
|
*(hak_bitmask_t*)value = hak->option.log_mask;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_LOG_MAXCAPA:
|
case HAK_OPT_LOG_MAXCAPA:
|
||||||
*(hak_oow_t*)value = hak->option.log_maxcapa;
|
*(hak_oow_t*)value = hak->option.log_maxcapa;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_LOG_TARGET_BCSTR:
|
case HAK_OPT_LOG_TARGET_BCSTR:
|
||||||
*(hak_bch_t**)value = hak->option.log_target_b;
|
*(hak_bch_t**)value = hak->option.log_target_b;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_LOG_TARGET_UCSTR:
|
case HAK_OPT_LOG_TARGET_UCSTR:
|
||||||
*(hak_uch_t**)value = hak->option.log_target_u;
|
*(hak_uch_t**)value = hak->option.log_target_u;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_LOG_TARGET_BCS:
|
case HAK_OPT_LOG_TARGET_BCS:
|
||||||
((hak_bcs_t*)value)->ptr = hak->option.log_target_b;
|
((hak_bcs_t*)value)->ptr = hak->option.log_target_b;
|
||||||
((hak_bcs_t*)value)->len = hak_count_bcstr(hak->option.log_target_b);
|
((hak_bcs_t*)value)->len = hak_count_bcstr(hak->option.log_target_b);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_LOG_TARGET_UCS:
|
case HAK_OPT_LOG_TARGET_UCS:
|
||||||
((hak_ucs_t*)value)->ptr = hak->option.log_target_u;
|
((hak_ucs_t*)value)->ptr = hak->option.log_target_u;
|
||||||
((hak_ucs_t*)value)->len = hak_count_ucstr(hak->option.log_target_u);
|
((hak_ucs_t*)value)->len = hak_count_ucstr(hak->option.log_target_u);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_SYMTAB_SIZE:
|
case HAK_OPT_SYMTAB_SIZE:
|
||||||
*(hak_oow_t*)value = hak->option.dfl_symtab_size;
|
*(hak_oow_t*)value = hak->option.dfl_symtab_size;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_SYSDIC_SIZE:
|
case HAK_OPT_SYSDIC_SIZE:
|
||||||
*(hak_oow_t*)value = hak->option.dfl_sysdic_size;
|
*(hak_oow_t*)value = hak->option.dfl_sysdic_size;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_PROCSTK_SIZE:
|
case HAK_OPT_PROCSTK_SIZE:
|
||||||
*(hak_oow_t*)value = hak->option.dfl_procstk_size;
|
*(hak_oow_t*)value = hak->option.dfl_procstk_size;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_EXSTK_SIZE:
|
case HAK_OPT_EXSTK_SIZE:
|
||||||
*(hak_oow_t*)value = hak->option.dfl_exstk_size;
|
*(hak_oow_t*)value = hak->option.dfl_exstk_size;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_CLSTK_SIZE:
|
case HAK_OPT_CLSTK_SIZE:
|
||||||
*(hak_oow_t*)value = hak->option.dfl_clstk_size;
|
*(hak_oow_t*)value = hak->option.dfl_clstk_size;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_MOD_LIBDIRS:
|
case HAK_OPT_MODLIBDIRS_BCSTR:
|
||||||
case HAK_MOD_PREFIX:
|
*(const hak_bch_t**)value = hak->option.modlibdirs_b;
|
||||||
case HAK_MOD_POSTFIX:
|
|
||||||
*(const hak_ooch_t**)value = hak->option.mod[id - HAK_MOD_LIBDIRS].ptr;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HAK_MOD_INCTX:
|
case HAK_OPT_MODLIBDIRS_UCSTR:
|
||||||
|
*(const hak_uch_t**)value = hak->option.modlibdirs_u;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case HAK_OPT_MODPREFIX:
|
||||||
|
case HAK_OPT_MODPOSTFIX:
|
||||||
|
*(const hak_ooch_t**)value = hak->option.mod[id - HAK_OPT_MODPREFIX].ptr;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case HAK_OPT_MODINCTX:
|
||||||
*(void**)value = hak->option.mod_inctx;
|
*(void**)value = hak->option.mod_inctx;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case HAK_OPT_INCDIRS_BCSTR:
|
||||||
|
*(const hak_bch_t**)value = hak->option.incdirs_b;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case HAK_OPT_INCDIRS_UCSTR:
|
||||||
|
*(const hak_uch_t**)value = hak->option.incdirs_u;
|
||||||
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
hak_seterrnum(hak, HAK_EINVAL);
|
hak_seterrnum(hak, HAK_EINVAL);
|
||||||
|
|||||||
@@ -241,35 +241,50 @@ typedef hak_errbinf_t hak_errinf_t;
|
|||||||
|
|
||||||
enum hak_option_t
|
enum hak_option_t
|
||||||
{
|
{
|
||||||
HAK_TRAIT,
|
HAK_OPT_TRAIT,
|
||||||
HAK_LOG_MASK,
|
HAK_OPT_LOG_MASK,
|
||||||
HAK_LOG_MAXCAPA,
|
HAK_OPT_LOG_MAXCAPA,
|
||||||
|
|
||||||
HAK_LOG_TARGET_BCSTR,
|
HAK_OPT_LOG_TARGET_BCSTR,
|
||||||
HAK_LOG_TARGET_UCSTR,
|
HAK_OPT_LOG_TARGET_UCSTR,
|
||||||
HAK_LOG_TARGET_BCS,
|
HAK_OPT_LOG_TARGET_BCS,
|
||||||
HAK_LOG_TARGET_UCS,
|
HAK_OPT_LOG_TARGET_UCS,
|
||||||
#if defined(HAK_OOCH_IS_UCH)
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
# define HAK_LOG_TARGET HAK_LOG_TARGET_UCSTR
|
# define HAK_OPT_LOG_TARGET HAK_OPT_LOG_TARGET_UCSTR
|
||||||
# define HAK_LOG_TARGET_OOCSTR HAK_LOG_TARGET_UCSTR
|
# define HAK_OPT_LOG_TARGET_OOCSTR HAK_OPT_LOG_TARGET_UCSTR
|
||||||
# define HAK_LOG_TARGET_OOCS HAK_LOG_TARGET_UCS
|
# define HAK_OPT_LOG_TARGET_OOCS HAK_OPT_LOG_TARGET_UCS
|
||||||
#else
|
#else
|
||||||
# define HAK_LOG_TARGET HAK_LOG_TARGET_BCSTR
|
# define HAK_OPT_LOG_TARGET HAK_OPT_LOG_TARGET_BCSTR
|
||||||
# define HAK_LOG_TARGET_OOCSTR HAK_LOG_TARGET_BCSTR
|
# define HAK_OPT_LOG_TARGET_OOCSTR HAK_OPT_LOG_TARGET_BCSTR
|
||||||
# define HAK_LOG_TARGET_OOCS HAK_LOG_TARGET_BCS
|
# define HAK_OPT_LOG_TARGET_OOCS HAK_OPT_LOG_TARGET_BCS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HAK_SYMTAB_SIZE, /* default system table size */
|
HAK_OPT_SYMTAB_SIZE, /* default system table size */
|
||||||
HAK_SYSDIC_SIZE, /* default system dictionary size */
|
HAK_OPT_SYSDIC_SIZE, /* default system dictionary size */
|
||||||
HAK_PROCSTK_SIZE, /* default process stack size */
|
HAK_OPT_PROCSTK_SIZE, /* default process stack size */
|
||||||
HAK_EXSTK_SIZE, /* default exception stack size */
|
HAK_OPT_EXSTK_SIZE, /* default exception stack size */
|
||||||
HAK_CLSTK_SIZE, /* default class stack size */
|
HAK_OPT_CLSTK_SIZE, /* default class stack size */
|
||||||
|
|
||||||
HAK_MOD_LIBDIRS,
|
HAK_OPT_MODLIBDIRS_BCSTR,
|
||||||
HAK_MOD_PREFIX,
|
HAK_OPT_MODLIBDIRS_UCSTR,
|
||||||
HAK_MOD_POSTFIX,
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
|
# define HAK_OPT_MODLIBDIRS HAK_OPT_MODLIBDIRS_UCSTR
|
||||||
|
#else
|
||||||
|
# define HAK_OPT_MODLIBDIRS HAK_OPT_MODLIBDIRS_BCSTR
|
||||||
|
#endif
|
||||||
|
|
||||||
HAK_MOD_INCTX
|
HAK_OPT_MODPREFIX,
|
||||||
|
HAK_OPT_MODPOSTFIX,
|
||||||
|
|
||||||
|
HAK_OPT_MODINCTX,
|
||||||
|
|
||||||
|
HAK_OPT_INCDIRS_BCSTR,
|
||||||
|
HAK_OPT_INCDIRS_UCSTR
|
||||||
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
|
# define HAK_OPT_INCDIRS HAK_OPT_INCDIRS_UCSTR
|
||||||
|
#else
|
||||||
|
# define HAK_OPT_INCDIRS HAK_OPT_INCDIRS_BCSTR
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
typedef enum hak_option_t hak_option_t;
|
typedef enum hak_option_t hak_option_t;
|
||||||
|
|
||||||
@@ -1786,7 +1801,18 @@ struct hak_t
|
|||||||
hak_oow_t dfl_clstk_size;
|
hak_oow_t dfl_clstk_size;
|
||||||
void* mod_inctx;
|
void* mod_inctx;
|
||||||
|
|
||||||
hak_oocs_t mod[3];
|
/* both representations are kept for the two options whose consumers
|
||||||
|
* are byte oriented: dl_open() feeds dlopen() and open_cci_stream()
|
||||||
|
* feeds fopen(), so the bch form is what actually gets used, while the
|
||||||
|
* uch form serves getoption and %js. converting once at set time beats
|
||||||
|
* converting on every module load and every include attempt. */
|
||||||
|
hak_bch_t* modlibdirs_b;
|
||||||
|
hak_uch_t* modlibdirs_u;
|
||||||
|
hak_bch_t* incdirs_b;
|
||||||
|
hak_uch_t* incdirs_u;
|
||||||
|
|
||||||
|
/* prefix and postfix only - indexed by (id - HAK_OPT_MODPREFIX) */
|
||||||
|
hak_oocs_t mod[2];
|
||||||
|
|
||||||
#if defined(HAK_BUILD_DEBUG)
|
#if defined(HAK_BUILD_DEBUG)
|
||||||
/* set automatically when trait is set */
|
/* set automatically when trait is set */
|
||||||
|
|||||||
+2
-2
@@ -952,7 +952,7 @@ hak_json_t* hak_json_open (hak_mmgr_t* mmgr, hak_oow_t xtnsize, hak_json_prim_t*
|
|||||||
/* the dummy hak is used for this json to perform primitive operations
|
/* the dummy hak is used for this json to perform primitive operations
|
||||||
* such as getting system time or logging. so the heap size doesn't
|
* such as getting system time or logging. so the heap size doesn't
|
||||||
* need to be changed from the tiny value set above. */
|
* need to be changed from the tiny value set above. */
|
||||||
hak_setoption(json->dummy_hak, HAK_LOG_MASK, &json->cfg.logmask);
|
hak_setoption(json->dummy_hak, HAK_OPT_LOG_MASK, &json->cfg.logmask);
|
||||||
hak_setcmgr(json->dummy_hak, json->cmgr);
|
hak_setcmgr(json->dummy_hak, json->cmgr);
|
||||||
|
|
||||||
|
|
||||||
@@ -987,7 +987,7 @@ int hak_json_setoption (hak_json_t* json, hak_json_option_t id, const void* valu
|
|||||||
* existing hak instances inside worker threads won't get
|
* existing hak instances inside worker threads won't get
|
||||||
* affected. new hak instances to be created later
|
* affected. new hak instances to be created later
|
||||||
* is supposed to use the new value */
|
* is supposed to use the new value */
|
||||||
hak_setoption(json->dummy_hak, HAK_LOG_MASK, value);
|
hak_setoption(json->dummy_hak, HAK_OPT_LOG_MASK, value);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-41
@@ -1220,7 +1220,7 @@ static hak_pfrc_t pf_va_get (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static hak_pfrc_t pf_object_new (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_object_new (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
hak_oop_t obj;
|
hak_oop_t obj;
|
||||||
hak_oop_t _class;
|
hak_oop_t _class;
|
||||||
@@ -1256,7 +1256,7 @@ static hak_pfrc_t pf_object_new (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static hak_pfrc_t pf_system_get_sigfd (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_system_get_sigfd (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
hak_ooi_t fd;
|
hak_ooi_t fd;
|
||||||
hak_hnd_t* hnd;
|
hak_hnd_t* hnd;
|
||||||
@@ -1264,7 +1264,7 @@ static hak_pfrc_t pf_system_get_sigfd (hak_t* hak, hak_mod_t* mod, hak_ooi_t nar
|
|||||||
fd = hak->vmprim.vm_getsigfd(hak);
|
fd = hak->vmprim.vm_getsigfd(hak);
|
||||||
|
|
||||||
/* hand back a system handle id rather than the descriptor itself, so that
|
/* hand back a system handle id rather than the descriptor itself, so that
|
||||||
* the result can be given to sem-signal-on-input - which resolves handle
|
* the result can be given to core.sem-signal-on-input - which resolves handle
|
||||||
* ids, not descriptors. wrapped HAK_HND_OPEN_KEEPOPEN because the VM owns
|
* ids, not descriptors. wrapped HAK_HND_OPEN_KEEPOPEN because the VM owns
|
||||||
* this descriptor and manages its blocking mode; the table must never
|
* this descriptor and manages its blocking mode; the table must never
|
||||||
* close it. wrapfd_once() keeps the id stable across calls. */
|
* close it. wrapfd_once() keeps the id stable across calls. */
|
||||||
@@ -1275,7 +1275,7 @@ static hak_pfrc_t pf_system_get_sigfd (hak_t* hak, hak_mod_t* mod, hak_ooi_t nar
|
|||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hak_pfrc_t pf_system_get_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_system_get_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
hak_uint8_t sig;
|
hak_uint8_t sig;
|
||||||
int n;
|
int n;
|
||||||
@@ -1289,12 +1289,12 @@ static hak_pfrc_t pf_system_get_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs
|
|||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (system-catch-sig signo) - route an operating system signal into the
|
/* (sys.sig-catch signo) - route an operating system signal into the signal
|
||||||
* signal descriptor, where hak code can wait for
|
* descriptor, where hak code can wait for it with
|
||||||
* it with sem-signal-on-input
|
* core.sem-signal-on-input
|
||||||
* (system-uncatch-sig signo) - release it again
|
* (sys.sig-uncatch signo) - release it again
|
||||||
*
|
*
|
||||||
* Note the difference from system-set-sig, which does not touch the operating
|
* Note the difference from sys.sig-set, which does not touch the operating
|
||||||
* system at all: that one injects a number into the descriptor directly, as a
|
* system at all: that one injects a number into the descriptor directly, as a
|
||||||
* way for hak code to post a synthetic signal to itself.
|
* way for hak code to post a synthetic signal to itself.
|
||||||
*/
|
*/
|
||||||
@@ -1323,17 +1323,17 @@ static hak_pfrc_t __system_catch_sig (hak_t* hak, hak_ooi_t nargs, int enable)
|
|||||||
return HAK_PF_SUCCESS;
|
return HAK_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hak_pfrc_t pf_system_catch_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_system_catch_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
return __system_catch_sig(hak, nargs, 1);
|
return __system_catch_sig(hak, nargs, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static hak_pfrc_t pf_system_uncatch_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_system_uncatch_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
return __system_catch_sig(hak, nargs, 0);
|
return __system_catch_sig(hak, nargs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static hak_pfrc_t pf_system_set_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
hak_pfrc_t hak_pf_system_set_sig (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
||||||
{
|
{
|
||||||
hak_oop_t tmp;
|
hak_oop_t tmp;
|
||||||
hak_uint8_t sig;
|
hak_uint8_t sig;
|
||||||
@@ -1366,11 +1366,10 @@ static pf_t builtin_prims[] =
|
|||||||
{ 1, HAK_TYPE_MAX(hak_oow_t), pf_scanf, 5, { 's','c','a','n','f' } },
|
{ 1, HAK_TYPE_MAX(hak_oow_t), pf_scanf, 5, { 's','c','a','n','f' } },
|
||||||
{ 1, HAK_TYPE_MAX(hak_oow_t), pf_sprintf, 7, { 's','p','r','i','n','t','f' } },
|
{ 1, HAK_TYPE_MAX(hak_oow_t), pf_sprintf, 7, { 's','p','r','i','n','t','f' } },
|
||||||
|
|
||||||
{ 0, 0, pf_system_get_sigfd, 16, { 's','y','s','t','e','m','-','g','e','t','-','s','i','g','f','d' } },
|
/* the signal primitives are registered by the sys module instead - see
|
||||||
{ 0, 0, pf_system_get_sig, 14, { 's','y','s','t','e','m','-','g','e','t','-','s','i','g' } },
|
* pfinfos[] in mod/sys.c. they are reached as sys.sig-getfd, sys.sig-get,
|
||||||
{ 1, 1, pf_system_set_sig, 14, { 's','y','s','t','e','m','-','s','e','t','-','s','i','g' } },
|
* sys.sig-set, sys.sig-catch and sys.sig-uncatch. the implementations stay
|
||||||
{ 1, 1, pf_system_catch_sig, 16, { 's','y','s','t','e','m','-','c','a','t','c','h','-','s','i','g' } },
|
* here and are declared in lib/hak-prv.h. */
|
||||||
{ 1, 1, pf_system_uncatch_sig, 18, { 's','y','s','t','e','m','-','u','n','c','a','t','c','h','-','s','i','g' } },
|
|
||||||
|
|
||||||
{ 0, 0, pf_gc, 2, { 'g','c' } },
|
{ 0, 0, pf_gc, 2, { 'g','c' } },
|
||||||
|
|
||||||
@@ -1435,30 +1434,7 @@ static pf_t builtin_prims[] =
|
|||||||
|
|
||||||
{ 0, 0, pf_va_context, 10, { 'v','a','-','c','o','n','t','e','x','t' } },
|
{ 0, 0, pf_va_context, 10, { 'v','a','-','c','o','n','t','e','x','t' } },
|
||||||
{ 0, 1, pf_va_count, 8, { 'v','a','-','c','o','u','n','t' } },
|
{ 0, 1, pf_va_count, 8, { 'v','a','-','c','o','u','n','t' } },
|
||||||
{ 1, 2, pf_va_get, 6, { 'v','a','-','g','e','t' } },
|
{ 1, 2, pf_va_get, 6, { 'v','a','-','g','e','t' } }
|
||||||
|
|
||||||
{ 1, 2, pf_object_new, 10, { 'o','b','j','e','c','t','-','n','e','w' } },
|
|
||||||
|
|
||||||
{ 0, 0, hak_pf_process_current, 15, { 'c','u','r','r','e','n','t','-','p','r','o','c','e','s','s'} },
|
|
||||||
{ 1, HAK_TYPE_MAX(hak_oow_t), hak_pf_process_fork, 4, { 'f','o','r','k'} },
|
|
||||||
{ 1, 1, hak_pf_process_resume, 6, { 'r','e','s','u','m','e' } },
|
|
||||||
{ 0, 1, hak_pf_process_suspend, 7, { 's','u','s','p','e','n','d' } },
|
|
||||||
{ 0, 1, hak_pf_process_terminate, 9, { 't','e','r','m','i','n','a','t','e' } },
|
|
||||||
{ 0, 0, hak_pf_process_terminate_all, 13, { 't','e','r','m','i','n','a','t','e','-','a','l','l' } },
|
|
||||||
{ 0, 0, hak_pf_process_yield, 5, { 'y','i','e','l','d'} },
|
|
||||||
|
|
||||||
|
|
||||||
{ 0, 0, hak_pf_semaphore_new, 7, { 's','e','m','-','n','e','w'} },
|
|
||||||
{ 1, 1, hak_pf_semaphore_wait, 8, { 's','e','m','-','w','a','i','t'} },
|
|
||||||
{ 1, 3, hak_pf_semaphore_signal, 10, { 's','e','m','-','s','i','g','n','a','l'} },
|
|
||||||
{ 2, 2, hak_pf_semaphore_signal_on_input, 19, { 's','e','m','-','s','i','g','n','a','l','-','o','n','-','i','n','p','u','t'} },
|
|
||||||
{ 2, 2, hak_pf_semaphore_signal_on_output, 20, { 's','e','m','-','s','i','g','n','a','l','-','o','n','-','o','u','t','p','u','t'} },
|
|
||||||
{ 1, 1, hak_pf_semaphore_unsignal, 12, { 's','e','m','-','u','n','s','i','g','n','a','l'} },
|
|
||||||
|
|
||||||
{ 0, 0, hak_pf_semaphore_group_new, 9, { 's','e','m','g','r','-','n','e','w'} },
|
|
||||||
{ 1, 2, hak_pf_semaphore_group_add_semaphore, 9, { 's','e','m','g','r','-','a','d','d'} },
|
|
||||||
{ 1, 2, hak_pf_semaphore_group_remove_semaphore, 12, { 's','e','m','g','r','-','r','e','m','o','v','e'} },
|
|
||||||
{ 1, 1, hak_pf_semaphore_group_wait, 10, { 's','e','m','g','r','-','w','a','i','t'} }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int hak_addbuiltinprims (hak_t* hak)
|
int hak_addbuiltinprims (hak_t* hak)
|
||||||
|
|||||||
@@ -356,7 +356,7 @@
|
|||||||
* about async-signal-safety - the spinlock is built out of atomics and is safe
|
* about async-signal-safety - the spinlock is built out of atomics and is safe
|
||||||
* by that measure - but about reentrancy: a signal delivered to the thread
|
* by that measure - but about reentrancy: a signal delivered to the thread
|
||||||
* that already holds the lock would spin, or block, on a lock that thread can
|
* that already holds the lock would spin, or block, on a lock that thread can
|
||||||
* no longer reach the end of. post_sig_to_all_haks() therefore walk the chain without it.
|
* no longer reach the end of. post_sig_to_all_haks() therefore walks the chain without it.
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#if defined(USE_THREAD)
|
#if defined(USE_THREAD)
|
||||||
@@ -2104,6 +2104,8 @@ kqueue_syserr:
|
|||||||
#elif defined(USE_SELECT)
|
#elif defined(USE_SELECT)
|
||||||
# define MUXEVT_FD(e) ((e).fd)
|
# define MUXEVT_FD(e) ((e).fd)
|
||||||
# define MUXEVT_MASK(e) ((e).events)
|
# define MUXEVT_MASK(e) ((e).events)
|
||||||
|
#else
|
||||||
|
# error UNSUPPORTED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Drop multiplexer events already sitting in the buffer for this descriptor.
|
/* Drop multiplexer events already sitting in the buffer for this descriptor.
|
||||||
@@ -2453,20 +2455,7 @@ static void vm_muxwait (hak_t* hak, const hak_ntime_t* dur, hak_vmprim_muxwait_c
|
|||||||
{
|
{
|
||||||
--n;
|
--n;
|
||||||
|
|
||||||
#if defined(USE_DEVPOLL)
|
if (MUXEVT_FD(xtn->ev.buf[n]) == xtn->iothr.p[0])
|
||||||
if (xtn->ev.buf[n].fd == xtn->iothr.p[0])
|
|
||||||
#elif defined(USE_KQUEUE)
|
|
||||||
if (xtn->ev.buf[n].ident == xtn->iothr.p[0])
|
|
||||||
#elif defined(USE_EPOLL)
|
|
||||||
/*if (xtn->ev.buf[n].data.ptr == (void*)HAK_TYPE_MAX(hak_oow_t))*/
|
|
||||||
if (xtn->ev.buf[n].data.fd == xtn->iothr.p[0])
|
|
||||||
#elif defined(USE_POLL)
|
|
||||||
if (xtn->ev.buf[n].fd == xtn->iothr.p[0])
|
|
||||||
#elif defined(USE_SELECT)
|
|
||||||
if (xtn->ev.buf[n].fd == xtn->iothr.p[0])
|
|
||||||
#else
|
|
||||||
# error UNSUPPORTED
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
hak_uint8_t u8;
|
hak_uint8_t u8;
|
||||||
while (read(xtn->iothr.p[0], &u8, HAK_SIZEOF(u8)) > 0)
|
while (read(xtn->iothr.p[0], &u8, HAK_SIZEOF(u8)) > 0)
|
||||||
@@ -2480,21 +2469,15 @@ static void vm_muxwait (hak_t* hak, const hak_ntime_t* dur, hak_vmprim_muxwait_c
|
|||||||
int revents;
|
int revents;
|
||||||
hak_ooi_t mask;
|
hak_ooi_t mask;
|
||||||
|
|
||||||
#if defined(USE_DEVPOLL)
|
#if defined(USE_KQUEUE)
|
||||||
revents = xtn->ev.buf[n].revents;
|
|
||||||
#elif defined(USE_KQUEUE)
|
|
||||||
revents = 0;
|
revents = 0;
|
||||||
/* it's "if .. else if" because kqueue filter is either READ or WRITE. */
|
/* it's "if .. else if" because kqueue filter is either READ or WRITE. */
|
||||||
if (xtn->ev.buf[n].filter == EVFILT_READ) revents |= XPOLLIN;
|
if (xtn->ev.buf[n].filter == EVFILT_READ) revents |= XPOLLIN;
|
||||||
else if (xtn->ev.buf[n].filter == EVFILT_WRITE) revents |= XPOLLOUT;
|
else if (xtn->ev.buf[n].filter == EVFILT_WRITE) revents |= XPOLLOUT;
|
||||||
if (xtn->ev.buf[n].flags & EV_EOF) revents |= XPOLLHUP;
|
if (xtn->ev.buf[n].flags & EV_EOF) revents |= XPOLLHUP;
|
||||||
if (xtn->ev.buf[n].flags & EV_ERROR) revents |= XPOLLERR;
|
if (xtn->ev.buf[n].flags & EV_ERROR) revents |= XPOLLERR;
|
||||||
#elif defined(USE_EPOLL)
|
#else
|
||||||
revents = xtn->ev.buf[n].events;
|
revents = MUXEVT_MASK(xtn->ev.buf[n]);
|
||||||
#elif defined(USE_POLL)
|
|
||||||
revents = xtn->ev.buf[n].revents;
|
|
||||||
#elif defined(USE_SELECT)
|
|
||||||
revents = xtn->ev.buf[n].events;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mask = 0;
|
mask = 0;
|
||||||
@@ -2503,19 +2486,7 @@ static void vm_muxwait (hak_t* hak, const hak_ntime_t* dur, hak_vmprim_muxwait_c
|
|||||||
if (revents & XPOLLERR) mask |= HAK_SEMAPHORE_IO_MASK_ERROR;
|
if (revents & XPOLLERR) mask |= HAK_SEMAPHORE_IO_MASK_ERROR;
|
||||||
if (revents & XPOLLHUP) mask |= HAK_SEMAPHORE_IO_MASK_HANGUP;
|
if (revents & XPOLLHUP) mask |= HAK_SEMAPHORE_IO_MASK_HANGUP;
|
||||||
|
|
||||||
#if defined(USE_DEVPOLL)
|
muxwcb(hak, MUXEVT_FD(xtn->ev.buf[n]), mask);
|
||||||
muxwcb(hak, xtn->ev.buf[n].fd, mask);
|
|
||||||
#elif defined(USE_KQUEUE)
|
|
||||||
muxwcb(hak, xtn->ev.buf[n].ident, mask);
|
|
||||||
#elif defined(USE_EPOLL)
|
|
||||||
muxwcb(hak, xtn->ev.buf[n].data.fd, mask);
|
|
||||||
#elif defined(USE_POLL)
|
|
||||||
muxwcb(hak, xtn->ev.buf[n].fd, mask);
|
|
||||||
#elif defined(USE_SELECT)
|
|
||||||
muxwcb(hak, xtn->ev.buf[n].fd, mask);
|
|
||||||
#else
|
|
||||||
# error UNSUPPORTED
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (n > 0);
|
while (n > 0);
|
||||||
@@ -2864,6 +2835,7 @@ static void dispatch_siginfo (int sig, siginfo_t* si, void* ctx)
|
|||||||
if (g_sig_state[sig].handler != (hak_uintptr_t)SIG_IGN &&
|
if (g_sig_state[sig].handler != (hak_uintptr_t)SIG_IGN &&
|
||||||
g_sig_state[sig].handler != (hak_uintptr_t)SIG_DFL)
|
g_sig_state[sig].handler != (hak_uintptr_t)SIG_DFL)
|
||||||
{
|
{
|
||||||
|
/* execute the current handler */
|
||||||
((sig_handler_t)g_sig_state[sig].handler)(sig);
|
((sig_handler_t)g_sig_state[sig].handler)(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2871,6 +2843,9 @@ static void dispatch_siginfo (int sig, siginfo_t* si, void* ctx)
|
|||||||
g_sig_state[sig].old_handler != (hak_uintptr_t)SIG_IGN &&
|
g_sig_state[sig].old_handler != (hak_uintptr_t)SIG_IGN &&
|
||||||
g_sig_state[sig].old_handler != (hak_uintptr_t)SIG_DFL)
|
g_sig_state[sig].old_handler != (hak_uintptr_t)SIG_DFL)
|
||||||
{
|
{
|
||||||
|
/* execute the original remembered handler */
|
||||||
|
/* TODO: if the runtime has installed its own signal handler, proably this one must not be called.
|
||||||
|
* when the runtime registers a single handler, it may optionally request that the previous one should also be invoked? */
|
||||||
((void(*)(int, siginfo_t*, void*))g_sig_state[sig].old_handler)(sig, si, ctx);
|
((void(*)(int, siginfo_t*, void*))g_sig_state[sig].old_handler)(sig, si, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3137,8 +3112,10 @@ static HAK_INLINE void post_sig_to_all_haks (int signo)
|
|||||||
{
|
{
|
||||||
xtn_t* xtn = GET_XTN(hak);
|
xtn_t* xtn = GET_XTN(hak);
|
||||||
hak_uint8_t u8;
|
hak_uint8_t u8;
|
||||||
/*hak_abortstd(hak);*/
|
|
||||||
u8 = signo & 0xFF;
|
u8 = signo & 0xFF;
|
||||||
|
/* write a byte of signal number. vm_getsig() reads this when
|
||||||
|
* it's invoked by the vm */
|
||||||
write(xtn->sigfd.p[1], &u8, HAK_SIZEOF(u8));
|
write(xtn->sigfd.p[1], &u8, HAK_SIZEOF(u8));
|
||||||
hak = xtn->next;
|
hak = xtn->next;
|
||||||
}
|
}
|
||||||
@@ -3535,7 +3512,6 @@ static HAK_INLINE int start_ticker (void)
|
|||||||
nanosleep(&ts, HAK_NULL);
|
nanosleep(&ts, HAK_NULL);
|
||||||
#elif defined(HAVE_USLEEP)
|
#elif defined(HAVE_USLEEP)
|
||||||
usleep(HAK_TICKER_INTERVAL_USECS * 2);
|
usleep(HAK_TICKER_INTERVAL_USECS * 2);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error UNDEFINED SLEEP
|
# error UNDEFINED SLEEP
|
||||||
#endif
|
#endif
|
||||||
@@ -3712,11 +3688,17 @@ static void dl_cleanup (hak_t* hak)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* dlopen_pfmod (hak_t* hak, const hak_ooch_t* name, const hak_ooch_t* dirptr, const hak_oow_t dirlen, hak_bch_t* bufptr, hak_oow_t bufcapa)
|
/* [NOTE] dirptr/dirlen is a byte string - it is a segment of the modlibdirs
|
||||||
|
* option, which is stored in the byte form precisely because it ends up
|
||||||
|
* here and in dlopen(). only 'name' still needs converting. */
|
||||||
|
static void* dlopen_pfmod (hak_t* hak, const hak_ooch_t* name, const hak_bch_t* dirptr, const hak_oow_t dirlen, hak_bch_t* bufptr, hak_oow_t bufcapa)
|
||||||
{
|
{
|
||||||
void* handle;
|
void* handle;
|
||||||
hak_oow_t len, i, xlen, dlen;
|
hak_oow_t len, i, xlen, dlen;
|
||||||
hak_oow_t ucslen, bcslen;
|
hak_oow_t bcslen;
|
||||||
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
|
hak_oow_t ucslen;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* opening a primitive function module - mostly libhak-xxxx.
|
/* opening a primitive function module - mostly libhak-xxxx.
|
||||||
* if PFMODPREFIX is absolute, never use PFMODDIR */
|
* if PFMODPREFIX is absolute, never use PFMODDIR */
|
||||||
@@ -3727,13 +3709,7 @@ static void* dlopen_pfmod (hak_t* hak, const hak_ooch_t* name, const hak_ooch_t*
|
|||||||
}
|
}
|
||||||
else if (dirptr)
|
else if (dirptr)
|
||||||
{
|
{
|
||||||
xlen = dirlen;
|
|
||||||
dlen = bufcapa;
|
|
||||||
#if defined(HAK_OOCH_IS_UCH)
|
|
||||||
if (hak_convootobchars(hak, dirptr, &xlen, bufptr, &dlen) <= -1) return HAK_NULL;
|
|
||||||
#else
|
|
||||||
dlen = hak_copy_bchars_to_bcstr(bufptr, bufcapa, dirptr, dirlen);
|
dlen = hak_copy_bchars_to_bcstr(bufptr, bufcapa, dirptr, dirlen);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dlen > 0 && bufptr[dlen - 1] != HAK_DFL_PATH_SEP)
|
if (dlen > 0 && bufptr[dlen - 1] != HAK_DFL_PATH_SEP)
|
||||||
{
|
{
|
||||||
@@ -3869,25 +3845,28 @@ static void* dl_open (hak_t* hak, const hak_ooch_t* name, int flags)
|
|||||||
{
|
{
|
||||||
#if defined(USE_LTDL) || defined(USE_DLFCN) || defined(USE_MACH_O_DYLD)
|
#if defined(USE_LTDL) || defined(USE_DLFCN) || defined(USE_MACH_O_DYLD)
|
||||||
hak_bch_t stabuf[128], * bufptr;
|
hak_bch_t stabuf[128], * bufptr;
|
||||||
hak_oow_t ucslen, bcslen, bufcapa;
|
|
||||||
void* handle = HAK_NULL;
|
void* handle = HAK_NULL;
|
||||||
|
hak_oow_t bufcapa;
|
||||||
|
const hak_bch_t* modlibdirs;
|
||||||
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
|
hak_oow_t ucslen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
modlibdirs = hak->option.modlibdirs_b;
|
||||||
|
|
||||||
#if defined(HAK_OOCH_IS_UCH)
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
if (hak_convootobcstr(hak, name, &ucslen, HAK_NULL, &bufcapa) <= -1) return HAK_NULL;
|
if (hak_convootobcstr(hak, name, &ucslen, HAK_NULL, &bufcapa) <= -1) return HAK_NULL;
|
||||||
|
|
||||||
if (hak->option.mod[0].len > 0)
|
|
||||||
{
|
|
||||||
/* multiple directories separated by a colon can be specified for HAK_MOD_LIBDIRS
|
|
||||||
* however, use the total length to secure space just for simplicity */
|
|
||||||
ucslen = hak->option.mod[0].len;
|
|
||||||
if (hak_convootobchars(hak, hak->option.mod[0].ptr, &ucslen, HAK_NULL, &bcslen) <= -1) return HAK_NULL;
|
|
||||||
bufcapa += bcslen;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
bufcapa = hak_count_bcstr(name);
|
bufcapa = hak_count_bcstr(name);
|
||||||
bufcapa += (hak->option.mod[0].len > 0)? hak->option.mod[0].len: HAK_COUNTOF(HAK_DEFAULT_PFMODDIR);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* modlibdirs is stored in the byte form too, so no conversion is needed
|
||||||
|
* here. multiple directories separated by a colon can be specified for
|
||||||
|
* HAK_OPT_MODLIBDIRS - use the total length to secure space, for
|
||||||
|
* simplicity. */
|
||||||
|
bufcapa += (modlibdirs && modlibdirs[0] != '\0')?
|
||||||
|
hak_count_bcstr(modlibdirs): HAK_COUNTOF(HAK_DEFAULT_PFMODDIR);
|
||||||
|
|
||||||
/* HAK_COUNTOF(HAK_DEFAULT_PFMODPREFIX) and HAK_COUNTOF(HAK_DEFAULT_PFMODPOSTIFX)
|
/* HAK_COUNTOF(HAK_DEFAULT_PFMODPREFIX) and HAK_COUNTOF(HAK_DEFAULT_PFMODPOSTIFX)
|
||||||
* include the terminating nulls. Never mind about the extra 2 characters. */
|
* include the terminating nulls. Never mind about the extra 2 characters. */
|
||||||
bufcapa += HAK_COUNTOF(HAK_DEFAULT_PFMODPREFIX) + HAK_COUNTOF(HAK_DEFAULT_PFMODPOSTFIX) + 1;
|
bufcapa += HAK_COUNTOF(HAK_DEFAULT_PFMODPREFIX) + HAK_COUNTOF(HAK_DEFAULT_PFMODPOSTFIX) + 1;
|
||||||
@@ -3901,12 +3880,12 @@ static void* dl_open (hak_t* hak, const hak_ooch_t* name, int flags)
|
|||||||
|
|
||||||
if (flags & HAK_VMPRIM_DLOPEN_PFMOD)
|
if (flags & HAK_VMPRIM_DLOPEN_PFMOD)
|
||||||
{
|
{
|
||||||
if (hak->option.mod[0].len > 0)
|
if (modlibdirs && modlibdirs[0] != '\0')
|
||||||
{
|
{
|
||||||
const hak_ooch_t* ptr, * end, * seg;
|
const hak_bch_t* ptr, * end, * seg;
|
||||||
|
|
||||||
ptr = hak->option.mod[0].ptr;
|
ptr = modlibdirs;
|
||||||
end = hak->option.mod[0].ptr + hak->option.mod[0].len;
|
end = modlibdirs + hak_count_bcstr(modlibdirs);
|
||||||
seg = ptr;
|
seg = ptr;
|
||||||
|
|
||||||
while (ptr <= end)
|
while (ptr <= end)
|
||||||
@@ -4109,8 +4088,8 @@ static void cb_on_option (hak_t* hak, hak_option_t id, const void* value)
|
|||||||
xtn_t* xtn = GET_XTN(hak);
|
xtn_t* xtn = GET_XTN(hak);
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (id != HAK_LOG_TARGET_BCSTR && id != HAK_LOG_TARGET_UCSTR &&
|
if (id != HAK_OPT_LOG_TARGET_BCSTR && id != HAK_OPT_LOG_TARGET_UCSTR &&
|
||||||
id != HAK_LOG_TARGET_BCS && id != HAK_LOG_TARGET_UCS) return; /* return success. not interested */
|
id != HAK_OPT_LOG_TARGET_BCS && id != HAK_OPT_LOG_TARGET_UCS) return; /* return success. not interested */
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#if defined(HAK_OOCH_IS_UCH) && (HAK_SIZEOF_UCH_T == HAK_SIZEOF_WCHAR_T)
|
#if defined(HAK_OOCH_IS_UCH) && (HAK_SIZEOF_UCH_T == HAK_SIZEOF_WCHAR_T)
|
||||||
@@ -4663,12 +4642,13 @@ static HAK_INLINE int open_cci_stream (hak_t* hak, hak_io_cciarg_t* arg)
|
|||||||
xtn_t* xtn = GET_XTN(hak);
|
xtn_t* xtn = GET_XTN(hak);
|
||||||
bb_t* bb = HAK_NULL;
|
bb_t* bb = HAK_NULL;
|
||||||
|
|
||||||
/* TOOD: support predefined include directory as well */
|
|
||||||
if (arg->includer)
|
if (arg->includer)
|
||||||
{
|
{
|
||||||
/* includee */
|
/* includee */
|
||||||
hak_oow_t ucslen, bcslen, parlen;
|
hak_oow_t ucslen, bcslen, parlen;
|
||||||
const hak_bch_t* fn, * fb;
|
const hak_bch_t* fn, * fb;
|
||||||
|
int attempt_incdirs;
|
||||||
|
const hak_bch_t* incdirs_ptr;
|
||||||
|
|
||||||
#if defined(HAK_OOCH_IS_UCH)
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
if (hak_convootobcstr(hak, arg->name, &ucslen, HAK_NULL, &bcslen) <= -1) goto oops;
|
if (hak_convootobcstr(hak, arg->name, &ucslen, HAK_NULL, &bcslen) <= -1) goto oops;
|
||||||
@@ -4682,27 +4662,63 @@ static HAK_INLINE int open_cci_stream (hak_t* hak, hak_io_cciarg_t* arg)
|
|||||||
{
|
{
|
||||||
fb = "";
|
fb = "";
|
||||||
parlen = 0;
|
parlen = 0;
|
||||||
|
attempt_incdirs = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fb = hak_get_base_name_from_bcstr_path(fn);
|
fb = hak_get_base_name_from_bcstr_path(fn);
|
||||||
parlen = fb - fn;
|
parlen = fb - fn;
|
||||||
|
attempt_incdirs = !((arg->name[0] == '.' && arg->name[1] == '/') || (arg->name[0] == '.' && arg->name[1] == '.' && arg->name[2] == '/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
bb = (bb_t*)hak_callocmem(hak, HAK_SIZEOF(*bb) + (HAK_SIZEOF(hak_bch_t) * (parlen + bcslen + 1)));
|
bb = (bb_t*)hak_callocmem(hak, HAK_SIZEOF(*bb) + (HAK_SIZEOF(hak_bch_t) * (parlen + bcslen + 1)));
|
||||||
if (!bb) goto oops;
|
if (HAK_UNLIKELY(!bb)) goto oops;
|
||||||
|
|
||||||
bb->fn = (hak_bch_t*)(bb + 1);
|
bb->fn = (hak_bch_t*)(bb + 1);
|
||||||
hak_copy_bchars (bb->fn, fn, parlen);
|
hak_copy_bchars(bb->fn, fn, parlen);
|
||||||
#if defined(HAK_OOCH_IS_UCH)
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
hak_convootobcstr(hak, arg->name, &ucslen, &bb->fn[parlen], &bcslen);
|
hak_convootobcstr(hak, arg->name, &ucslen, &bb->fn[parlen], &bcslen);
|
||||||
#else
|
#else
|
||||||
hak_copy_bcstr(&bb->fn[parlen], bcslen + 1, arg->name);
|
hak_copy_bcstr(&bb->fn[parlen], bcslen + 1, arg->name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
incdirs_ptr = hak->option.incdirs_b;
|
||||||
|
retry:
|
||||||
bb->fp = fopen(bb->fn, FOPEN_R_FLAGS);
|
bb->fp = fopen(bb->fn, FOPEN_R_FLAGS);
|
||||||
if (!bb->fp)
|
if (!bb->fp)
|
||||||
{
|
{
|
||||||
|
if ((errno == ENOENT || errno == ENOTDIR) && attempt_incdirs && incdirs_ptr && incdirs_ptr[0] != '\0')
|
||||||
|
{
|
||||||
|
hak_oow_t incdir_bcslen;
|
||||||
|
const hak_bch_t* colon;
|
||||||
|
|
||||||
|
hak_freemem(hak, bb); bb = HAK_NULL;
|
||||||
|
|
||||||
|
/* incdirs is kept in the byte form as well, so the directory part
|
||||||
|
* needs no conversion here - only the include name does. */
|
||||||
|
colon = hak_find_bchar_in_bcstr(incdirs_ptr, ':');
|
||||||
|
incdir_bcslen = colon? (hak_oow_t)(colon - incdirs_ptr): hak_count_bcstr(incdirs_ptr);
|
||||||
|
|
||||||
|
bb = (bb_t*)hak_callocmem(hak, HAK_SIZEOF(*bb) + (HAK_SIZEOF(hak_bch_t) * (incdir_bcslen + bcslen + 2)));
|
||||||
|
if (HAK_UNLIKELY(!bb)) goto oops;
|
||||||
|
|
||||||
|
bb->fn = (hak_bch_t*)(bb + 1);
|
||||||
|
|
||||||
|
/* TODO: i need to support different directory separator */
|
||||||
|
hak_copy_bchars(bb->fn, incdirs_ptr, incdir_bcslen);
|
||||||
|
if (incdir_bcslen > 0 && bb->fn[incdir_bcslen - 1] != '/') bb->fn[incdir_bcslen++] = '/';
|
||||||
|
#if defined(HAK_OOCH_IS_UCH)
|
||||||
|
hak_convootobcstr(hak, arg->name, &ucslen, &bb->fn[incdir_bcslen], &bcslen);
|
||||||
|
#else
|
||||||
|
hak_copy_bcstr(&bb->fn[incdir_bcslen], bcslen + 1, arg->name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
incdirs_ptr = colon? colon + 1: HAK_NULL;
|
||||||
|
|
||||||
|
/*printf("RETRYING bb->fn [%s]\n", bb->fn);*/
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
hak_seterrbfmt(hak, HAK_EIOERR, "unable to open %hs", bb->fn);
|
hak_seterrbfmt(hak, HAK_EIOERR, "unable to open %hs", bb->fn);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
@@ -4710,6 +4726,15 @@ static HAK_INLINE int open_cci_stream (hak_t* hak, hak_io_cciarg_t* arg)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* main stream */
|
/* main stream */
|
||||||
|
|
||||||
|
/* [NOTE]
|
||||||
|
* in the current implementation, the main stream is rarely used read
|
||||||
|
* because the input the the reader/compiler is fed via hak_feed() and its relatives.
|
||||||
|
* this part doesn't really open the specified file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: make if hak_feed() is going to be used or not.
|
||||||
|
* if it's not used, it can open it as usual as xtn->cci_path point to the file name anyways */
|
||||||
hak_oow_t pathlen;
|
hak_oow_t pathlen;
|
||||||
|
|
||||||
pathlen = xtn->cci_path? hak_count_bcstr(xtn->cci_path): 0;
|
pathlen = xtn->cci_path? hak_count_bcstr(xtn->cci_path): 0;
|
||||||
@@ -4822,7 +4847,7 @@ static HAK_INLINE int read_cci_stream (hak_t* hak, hak_io_cciarg_t* arg)
|
|||||||
#else
|
#else
|
||||||
bcslen = (bb->len < HAK_COUNTOF(arg->buf.c))? bb->len: HAK_COUNTOF(arg->buf.c);
|
bcslen = (bb->len < HAK_COUNTOF(arg->buf.c))? bb->len: HAK_COUNTOF(arg->buf.c);
|
||||||
ucslen = bcslen;
|
ucslen = bcslen;
|
||||||
hak_copy_bchars (arg->buf.c, bb->buf, bcslen);
|
hak_copy_bchars(arg->buf.c, bb->buf, bcslen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
remlen = bb->len - bcslen;
|
remlen = bb->len - bcslen;
|
||||||
@@ -4973,7 +4998,7 @@ static HAK_INLINE int read_udi_stream (hak_t* hak, hak_io_udiarg_t* arg)
|
|||||||
#else
|
#else
|
||||||
bcslen = (bb->len < HAK_COUNTOF(arg->buf.c))? bb->len: HAK_COUNTOF(arg->buf.c);
|
bcslen = (bb->len < HAK_COUNTOF(arg->buf.c))? bb->len: HAK_COUNTOF(arg->buf.c);
|
||||||
ucslen = bcslen;
|
ucslen = bcslen;
|
||||||
hak_copy_bchars (arg->buf.c, bb->buf, bcslen);
|
hak_copy_bchars(arg->buf.c, bb->buf, bcslen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
remlen = bb->len - bcslen;
|
remlen = bb->len - bcslen;
|
||||||
@@ -5016,7 +5041,7 @@ static HAK_INLINE int read_udi_stream_bytes (hak_t* hak, hak_io_udiarg_t* arg)
|
|||||||
|
|
||||||
bcslen = (bb->len < HAK_COUNTOF(arg->buf.b))? bb->len: HAK_COUNTOF(arg->buf.b);
|
bcslen = (bb->len < HAK_COUNTOF(arg->buf.b))? bb->len: HAK_COUNTOF(arg->buf.b);
|
||||||
ucslen = bcslen;
|
ucslen = bcslen;
|
||||||
hak_copy_bchars ((hak_bch_t*)arg->buf.b, bb->buf, bcslen);
|
hak_copy_bchars((hak_bch_t*)arg->buf.b, bb->buf, bcslen);
|
||||||
|
|
||||||
remlen = bb->len - bcslen;
|
remlen = bb->len - bcslen;
|
||||||
if (remlen > 0) HAK_MEMMOVE(bb->buf, &bb->buf[bcslen], remlen);
|
if (remlen > 0) HAK_MEMMOVE(bb->buf, &bb->buf[bcslen], remlen);
|
||||||
@@ -5113,7 +5138,7 @@ static HAK_INLINE int write_udo_stream (hak_t* hak, hak_io_udoarg_t* arg)
|
|||||||
ucslen = arg->len - donelen;
|
ucslen = arg->len - donelen;
|
||||||
if (ucslen > bcslen) ucslen = bcslen;
|
if (ucslen > bcslen) ucslen = bcslen;
|
||||||
else if (ucslen < bcslen) bcslen = ucslen;
|
else if (ucslen < bcslen) bcslen = ucslen;
|
||||||
hak_copy_bchars (bcsbuf, &ptr[donelen], bcslen);
|
hak_copy_bchars(bcsbuf, &ptr[donelen], bcslen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fwrite(bcsbuf, HAK_SIZEOF(bcsbuf[0]), bcslen, (FILE*)arg->handle) < bcslen)
|
if (fwrite(bcsbuf, HAK_SIZEOF(bcsbuf[0]), bcslen, (FILE*)arg->handle) < bcslen)
|
||||||
|
|||||||
+2
-2
@@ -212,7 +212,7 @@ hak_client_t* hak_client_open (hak_mmgr_t* mmgr, hak_oow_t xtnsize, hak_client_p
|
|||||||
/* the dummy hak is used for this client to perform primitive operations
|
/* the dummy hak is used for this client to perform primitive operations
|
||||||
* such as getting system time or logging. so the heap size doesn't
|
* such as getting system time or logging. so the heap size doesn't
|
||||||
* need to be changed from the tiny value set above. */
|
* need to be changed from the tiny value set above. */
|
||||||
hak_setoption (client->dummy_hak, HAK_LOG_MASK, &client->cfg.logmask);
|
hak_setoption (client->dummy_hak, HAK_OPT_LOG_MASK, &client->cfg.logmask);
|
||||||
hak_setcmgr (client->dummy_hak, client->_cmgr);
|
hak_setcmgr (client->dummy_hak, client->_cmgr);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
@@ -258,7 +258,7 @@ int hak_client_setoption (hak_client_t* client, hak_client_option_t id, const vo
|
|||||||
* existing hak instances inside worker threads won't get
|
* existing hak instances inside worker threads won't get
|
||||||
* affected. new hak instances to be created later
|
* affected. new hak instances to be created later
|
||||||
* is supposed to use the new value */
|
* is supposed to use the new value */
|
||||||
hak_setoption (client->dummy_hak, HAK_LOG_MASK, value);
|
hak_setoption (client->dummy_hak, HAK_OPT_LOG_MASK, value);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -1177,14 +1177,14 @@ hak_server_t* hak_server_open (hak_mmgr_t* mmgr, hak_oow_t xtnsize, hak_server_p
|
|||||||
/* the dummy hak is used for this server to perform primitive operations
|
/* the dummy hak is used for this server to perform primitive operations
|
||||||
* such as getting system time or logging. so the heap size doesn't
|
* such as getting system time or logging. so the heap size doesn't
|
||||||
* need to be changed from the tiny value set above. */
|
* need to be changed from the tiny value set above. */
|
||||||
hak_setoption (server->dummy_hak, HAK_LOG_MASK, &server->cfg.logmask);
|
hak_setoption (server->dummy_hak, HAK_OPT_LOG_MASK, &server->cfg.logmask);
|
||||||
hak_setcmgr (server->dummy_hak, hak_server_getcmgr(server));
|
hak_setcmgr (server->dummy_hak, hak_server_getcmgr(server));
|
||||||
hak_getoption (server->dummy_hak, HAK_TRAIT, &trait);
|
hak_getoption (server->dummy_hak, HAK_OPT_TRAIT, &trait);
|
||||||
#if defined(HAK_BUILD_DEBUG)
|
#if defined(HAK_BUILD_DEBUG)
|
||||||
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_GC) trait |= HAK_TRAIT_DEBUG_GC;
|
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_GC) trait |= HAK_TRAIT_DEBUG_GC;
|
||||||
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_BIGINT) trait |= HAK_TRAIT_DEBUG_BIGINT;
|
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_BIGINT) trait |= HAK_TRAIT_DEBUG_BIGINT;
|
||||||
#endif
|
#endif
|
||||||
hak_setoption (server->dummy_hak, HAK_TRAIT, &trait);
|
hak_setoption (server->dummy_hak, HAK_OPT_TRAIT, &trait);
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
|
|
||||||
@@ -1517,17 +1517,17 @@ static int init_worker_hak (hak_server_worker_t* worker)
|
|||||||
xtn = (worker_hak_xtn_t*)hak_getxtn(hak);
|
xtn = (worker_hak_xtn_t*)hak_getxtn(hak);
|
||||||
xtn->worker = worker;
|
xtn->worker = worker;
|
||||||
|
|
||||||
hak_setoption(hak, HAK_MOD_INCTX, &server->cfg.module_inctx);
|
hak_setoption(hak, HAK_OPT_MODINCTX, &server->cfg.module_inctx);
|
||||||
hak_setoption(hak, HAK_LOG_MASK, &server->cfg.logmask);
|
hak_setoption(hak, HAK_OPT_LOG_MASK, &server->cfg.logmask);
|
||||||
hak_setcmgr(hak, hak_server_getcmgr(server));
|
hak_setcmgr(hak, hak_server_getcmgr(server));
|
||||||
|
|
||||||
hak_getoption(hak, HAK_TRAIT, &trait);
|
hak_getoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
#if defined(HAK_BUILD_DEBUG)
|
#if defined(HAK_BUILD_DEBUG)
|
||||||
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_GC) trait |= HAK_TRAIT_DEBUG_GC;
|
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_GC) trait |= HAK_TRAIT_DEBUG_GC;
|
||||||
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_BIGINT) trait |= HAK_TRAIT_DEBUG_BIGINT;
|
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_BIGINT) trait |= HAK_TRAIT_DEBUG_BIGINT;
|
||||||
#endif
|
#endif
|
||||||
trait |= HAK_TRAIT_LANG_ENABLE_EOL;
|
trait |= HAK_TRAIT_LANG_ENABLE_EOL;
|
||||||
hak_setoption(hak, HAK_TRAIT, &trait);
|
hak_setoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
|
|
||||||
HAK_MEMSET(&hakcb, 0, HAK_SIZEOF(hakcb));
|
HAK_MEMSET(&hakcb, 0, HAK_SIZEOF(hakcb));
|
||||||
/*hakcb.fini = fini_hak;
|
/*hakcb.fini = fini_hak;
|
||||||
@@ -2050,12 +2050,12 @@ int hak_server_setoption (hak_server_t* server, hak_server_option_t id, const vo
|
|||||||
* is supposed to use the new value */
|
* is supposed to use the new value */
|
||||||
hak_bitmask_t trait;
|
hak_bitmask_t trait;
|
||||||
|
|
||||||
hak_getoption (server->dummy_hak, HAK_TRAIT, &trait);
|
hak_getoption (server->dummy_hak, HAK_OPT_TRAIT, &trait);
|
||||||
#if defined(HAK_BUILD_DEBUG)
|
#if defined(HAK_BUILD_DEBUG)
|
||||||
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_GC) trait |= HAK_TRAIT_DEBUG_GC;
|
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_GC) trait |= HAK_TRAIT_DEBUG_GC;
|
||||||
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_BIGINT) trait |= HAK_TRAIT_DEBUG_BIGINT;
|
if (server->cfg.trait & HAK_SERVER_TRAIT_DEBUG_BIGINT) trait |= HAK_TRAIT_DEBUG_BIGINT;
|
||||||
#endif
|
#endif
|
||||||
hak_setoption (server->dummy_hak, HAK_TRAIT, &trait);
|
hak_setoption (server->dummy_hak, HAK_OPT_TRAIT, &trait);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -2067,7 +2067,7 @@ int hak_server_setoption (hak_server_t* server, hak_server_option_t id, const vo
|
|||||||
* existing hak instances inside worker threads won't get
|
* existing hak instances inside worker threads won't get
|
||||||
* affected. new hak instances to be created later
|
* affected. new hak instances to be created later
|
||||||
* is supposed to use the new value */
|
* is supposed to use the new value */
|
||||||
hak_setoption (server->dummy_hak, HAK_LOG_MASK, value);
|
hak_setoption (server->dummy_hak, HAK_OPT_LOG_MASK, value);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
+25
@@ -605,21 +605,46 @@ static hak_pfinfo_t pfinfos[] =
|
|||||||
{ "classRespondsTo", { HAK_PFBASE_FUNC, pf_core_class_responds_to, 2, 2 } },
|
{ "classRespondsTo", { HAK_PFBASE_FUNC, pf_core_class_responds_to, 2, 2 } },
|
||||||
{ "cons", { HAK_PFBASE_FUNC, pf_core_cons, 2, 2 } },
|
{ "cons", { HAK_PFBASE_FUNC, pf_core_cons, 2, 2 } },
|
||||||
|
|
||||||
|
{ "current-process", { HAK_PFBASE_FUNC, hak_pf_process_current, 0, 0 } },
|
||||||
|
|
||||||
{ "eqk?", { HAK_PFBASE_FUNC, hak_pf_eqk, 2, 2 } },
|
{ "eqk?", { HAK_PFBASE_FUNC, hak_pf_eqk, 2, 2 } },
|
||||||
{ "eql?", { HAK_PFBASE_FUNC, hak_pf_eql, 2, 2 } },
|
{ "eql?", { HAK_PFBASE_FUNC, hak_pf_eql, 2, 2 } },
|
||||||
{ "eqv?", { HAK_PFBASE_FUNC, hak_pf_eqv, 2, 2 } },
|
{ "eqv?", { HAK_PFBASE_FUNC, hak_pf_eqv, 2, 2 } },
|
||||||
|
|
||||||
|
{ "fork", { HAK_PFBASE_FUNC, hak_pf_process_fork, 1, HAK_TYPE_MAX(hak_oow_t) } },
|
||||||
{ "instRespondsTo", { HAK_PFBASE_FUNC, pf_core_inst_responds_to, 2, 2 } },
|
{ "instRespondsTo", { HAK_PFBASE_FUNC, pf_core_inst_responds_to, 2, 2 } },
|
||||||
|
|
||||||
{ "nqk?", { HAK_PFBASE_FUNC, hak_pf_nqk, 2, 2 } },
|
{ "nqk?", { HAK_PFBASE_FUNC, hak_pf_nqk, 2, 2 } },
|
||||||
{ "nql?", { HAK_PFBASE_FUNC, hak_pf_nql, 2, 2 } },
|
{ "nql?", { HAK_PFBASE_FUNC, hak_pf_nql, 2, 2 } },
|
||||||
{ "nqv?", { HAK_PFBASE_FUNC, hak_pf_nqv, 2, 2 } },
|
{ "nqv?", { HAK_PFBASE_FUNC, hak_pf_nqv, 2, 2 } },
|
||||||
|
|
||||||
|
{ "object-new", { HAK_PFBASE_FUNC, hak_pf_object_new, 1, 2 } },
|
||||||
|
|
||||||
{ "primAt", { HAK_PFBASE_FUNC, pf_core_prim_at, 2, 2 } },
|
{ "primAt", { HAK_PFBASE_FUNC, pf_core_prim_at, 2, 2 } },
|
||||||
{ "primAtPut", { HAK_PFBASE_FUNC, pf_core_prim_at_put, 3, 3 } },
|
{ "primAtPut", { HAK_PFBASE_FUNC, pf_core_prim_at_put, 3, 3 } },
|
||||||
|
|
||||||
|
{ "resume", { HAK_PFBASE_FUNC, hak_pf_process_resume, 1, 1 } },
|
||||||
|
|
||||||
|
{ "sem-new", { HAK_PFBASE_FUNC, hak_pf_semaphore_new, 0, 1 } },
|
||||||
|
{ "sem-signal", { HAK_PFBASE_FUNC, hak_pf_semaphore_signal, 1, 3 } },
|
||||||
|
{ "sem-signal-on-input", { HAK_PFBASE_FUNC, hak_pf_semaphore_signal_on_input, 2, 2 } },
|
||||||
|
{ "sem-signal-on-output", { HAK_PFBASE_FUNC, hak_pf_semaphore_signal_on_output, 2, 2 } },
|
||||||
|
{ "sem-unsignal", { HAK_PFBASE_FUNC, hak_pf_semaphore_unsignal, 1, 1 } },
|
||||||
|
{ "sem-wait", { HAK_PFBASE_FUNC, hak_pf_semaphore_wait, 1, 1 } },
|
||||||
|
{ "semgr-add", { HAK_PFBASE_FUNC, hak_pf_semaphore_group_add_semaphore, 1, 2 } },
|
||||||
|
{ "semgr-new", { HAK_PFBASE_FUNC, hak_pf_semaphore_group_new, 0, 0 } },
|
||||||
|
{ "semgr-remove", { HAK_PFBASE_FUNC, hak_pf_semaphore_group_remove_semaphore, 1, 2 } },
|
||||||
|
{ "semgr-wait", { HAK_PFBASE_FUNC, hak_pf_semaphore_group_wait, 1, 1 } },
|
||||||
|
|
||||||
{ "slice", { HAK_PFBASE_FUNC, pf_core_slice, 3, 3 } },
|
{ "slice", { HAK_PFBASE_FUNC, pf_core_slice, 3, 3 } },
|
||||||
{ "smooiToChar", { HAK_PFBASE_FUNC, pf_core_smooi_to_char, 1, 1 } },
|
{ "smooiToChar", { HAK_PFBASE_FUNC, pf_core_smooi_to_char, 1, 1 } },
|
||||||
{ "sqrt", { HAK_PFBASE_FUNC, hak_pf_number_sqrt, 1, 1 } },
|
{ "sqrt", { HAK_PFBASE_FUNC, hak_pf_number_sqrt, 1, 1 } },
|
||||||
|
|
||||||
|
{ "suspend", { HAK_PFBASE_FUNC, hak_pf_process_suspend, 0, 1 } },
|
||||||
|
{ "terminate", { HAK_PFBASE_FUNC, hak_pf_process_terminate, 0, 1 } },
|
||||||
|
{ "terminate-all", { HAK_PFBASE_FUNC, hak_pf_process_terminate_all, 0, 0 } },
|
||||||
|
{ "yield", { HAK_PFBASE_FUNC, hak_pf_process_yield, 0, 0 } },
|
||||||
|
|
||||||
{ "~=", { HAK_PFBASE_FUNC, hak_pf_number_ne, 2, 2 } },
|
{ "~=", { HAK_PFBASE_FUNC, hak_pf_number_ne, 2, 2 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "_sys.h"
|
#include "_sys.h"
|
||||||
#include <hak-hnd.h>
|
#include "../lib/hak-prv.h"
|
||||||
#include <hak-pio.h>
|
#include <hak-pio.h>
|
||||||
#include <hak-str.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
@@ -174,7 +173,7 @@ static hak_pfrc_t pf_sys_random (hak_t* hak, hak_mod_t* mod, hak_ooi_t nargs)
|
|||||||
* sys.read and sys.write follow the non-blocking contract: they return the
|
* sys.read and sys.write follow the non-blocking contract: they return the
|
||||||
* byte count, 0 at end of file, or -1 when the handle would have blocked.
|
* byte count, 0 at end of file, or -1 when the handle would have blocked.
|
||||||
* -1 is an ordinary outcome - the caller is expected to wait on a semaphore
|
* -1 is an ordinary outcome - the caller is expected to wait on a semaphore
|
||||||
* bound with sem-signal-on-input/-output and try again. Only a genuine
|
* bound with core.sem-signal-on-input/-output and try again. Only a genuine
|
||||||
* failure raises.
|
* failure raises.
|
||||||
* ------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
@@ -813,6 +812,13 @@ static hak_pfinfo_t pfinfos[] =
|
|||||||
{ "pwait", { HAK_PFBASE_FUNC, pf_sys_pwait, 1, 1 } },
|
{ "pwait", { HAK_PFBASE_FUNC, pf_sys_pwait, 1, 1 } },
|
||||||
{ "random", { HAK_PFBASE_FUNC, pf_sys_random, 0, 0 } },
|
{ "random", { HAK_PFBASE_FUNC, pf_sys_random, 0, 0 } },
|
||||||
{ "read", { HAK_PFBASE_FUNC, pf_sys_read, 2, 4 } },
|
{ "read", { HAK_PFBASE_FUNC, pf_sys_read, 2, 4 } },
|
||||||
|
|
||||||
|
{ "sig-catch", { HAK_PFBASE_FUNC, hak_pf_system_catch_sig, 1, 1 } },
|
||||||
|
{ "sig-get", { HAK_PFBASE_FUNC, hak_pf_system_get_sig, 0, 0 } },
|
||||||
|
{ "sig-getfd", { HAK_PFBASE_FUNC, hak_pf_system_get_sigfd, 0, 0 } },
|
||||||
|
{ "sig-set", { HAK_PFBASE_FUNC, hak_pf_system_set_sig, 1, 1 } },
|
||||||
|
{ "sig-uncatch", { HAK_PFBASE_FUNC, hak_pf_system_uncatch_sig, 1, 1 } },
|
||||||
|
|
||||||
{ "srandom", { HAK_PFBASE_FUNC, pf_sys_srandom, 1, 1 } },
|
{ "srandom", { HAK_PFBASE_FUNC, pf_sys_srandom, 1, 1 } },
|
||||||
{ "stime", { HAK_PFBASE_FUNC, pf_sys_stime, 1, 1 } },
|
{ "stime", { HAK_PFBASE_FUNC, pf_sys_stime, 1, 1 } },
|
||||||
{ "time", { HAK_PFBASE_FUNC, pf_sys_time, 0, 0 } },
|
{ "time", { HAK_PFBASE_FUNC, pf_sys_time, 0, 0 } },
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ class FixedSizedCollection: IndexedCollection {
|
|||||||
class[#varying] Array: FixedSizedCollection {
|
class[#varying] Array: FixedSizedCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class[#byte #varying] ByteArray: FixedSizedCollection {
|
||||||
|
}
|
||||||
|
|
||||||
class[#char #varying] String: FixedSizedCollection {
|
class[#char #varying] String: FixedSizedCollection {
|
||||||
fun[#class] initValue() {
|
fun[#class] initValue() {
|
||||||
##return '\0'
|
##return '\0'
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
class Apex {
|
||||||
|
fun isNil?() { return false }
|
||||||
|
fun notNil?() { return true }
|
||||||
|
|
||||||
|
fun[#class] basicNew(size) {
|
||||||
|
return (core.basicNew self size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun[#class] respondsTo(mthname) {
|
||||||
|
return (core.classRespondsTo self mthname)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun respondsTo(mthname) {
|
||||||
|
return (core.instRespondsTo self mthname)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun primAt(pos) {
|
||||||
|
return (core.primAt self pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun primtAtPut(pos value) {
|
||||||
|
return (core.primAtPut self pos value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun basicAt(pos) {
|
||||||
|
return (core.basicAt self pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun basicAtPut(pos value) {
|
||||||
|
return (core.basicAtPut self pos value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun basicSize() {
|
||||||
|
return (core.basicSize self)
|
||||||
|
}
|
||||||
|
|
||||||
|
## TODO: ...
|
||||||
|
fun == (oprnd) { return (== self oprnd) }
|
||||||
|
fun != (oprnd) { return (!= self oprnd) }
|
||||||
|
## TODO: fun perform(name ...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class[#uncopyable #varying #limited #final] Class: Apex (
|
||||||
|
_name
|
||||||
|
_mdic
|
||||||
|
_spec
|
||||||
|
_selfspec
|
||||||
|
_superclass
|
||||||
|
_nivars_super
|
||||||
|
_ibrand
|
||||||
|
_ivarnames
|
||||||
|
_cvarnames
|
||||||
|
) {
|
||||||
|
fun name() {
|
||||||
|
##return (core.className self)
|
||||||
|
return _class
|
||||||
|
}
|
||||||
|
|
||||||
|
fun instanceVariableNames() {
|
||||||
|
## TODO: this still returns nil as the acutal manipulation of the field has not been implemented
|
||||||
|
return _ivarnames
|
||||||
|
}
|
||||||
|
|
||||||
|
fun classVariableNames() {
|
||||||
|
## TODO: this still returns nil as the acutal manipulation of the field has not been implemented
|
||||||
|
return _cvarnames
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UndefinedObject: Apex {
|
||||||
|
fun isNil?() { return true }
|
||||||
|
fun notNil?() { return false }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Object: Apex {
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
class[#uncopyable] Semaphore: Object(
|
||||||
|
_waiting_first
|
||||||
|
_wait_last
|
||||||
|
_count
|
||||||
|
_subtype
|
||||||
|
_index
|
||||||
|
_ftime_sec_or_handle
|
||||||
|
_ftime_nsec_or_type
|
||||||
|
_signal_action
|
||||||
|
_group
|
||||||
|
_grm_prev
|
||||||
|
_grm_next
|
||||||
|
) {
|
||||||
|
fun[#class] new() {
|
||||||
|
return (core.sem-new 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun[#class] forMutex() {
|
||||||
|
return (core.sem-new 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun signal() {
|
||||||
|
return (core.sem-signal self 0 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun signalAfter(secs nsecs) {
|
||||||
|
return (core.sem-signal self secs nsecs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun signalOnInput(handle) {
|
||||||
|
return (core.sem-signal-on-input self handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun signalOnOutput(handle) {
|
||||||
|
return (core.sem-signal-on-output self handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unsignal() {
|
||||||
|
return (core.sem-unsignal self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun wait() {
|
||||||
|
return (core.sem-wait self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class[#uncopyable] SemaphoreGroup: Object(
|
||||||
|
_waiting_first
|
||||||
|
_waiting_last
|
||||||
|
_sem_unsig_first
|
||||||
|
_sem_unsig_last
|
||||||
|
_sem_sig_first
|
||||||
|
_sem_sig_last
|
||||||
|
_sem_io_count
|
||||||
|
_sem_count
|
||||||
|
) {
|
||||||
|
fun[#class] new() {
|
||||||
|
return (core.semgr-new)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(sem) {
|
||||||
|
return (core.semgr-add self sem)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(sem) {
|
||||||
|
return (core.semgr-remove self sem)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun wait() {
|
||||||
|
return (core.semgr-wait self)
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-79
@@ -1,84 +1,8 @@
|
|||||||
class Apex {
|
$include "Object.hak"
|
||||||
fun isNil?() { return false }
|
|
||||||
fun notNil?() { return true }
|
|
||||||
|
|
||||||
fun[#class] basicNew(size) {
|
|
||||||
return (core.basicNew self size)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun[#class] respondsTo(mthname) {
|
|
||||||
return (core.classRespondsTo self mthname)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun respondsTo(mthname) {
|
|
||||||
return (core.instRespondsTo self mthname)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun primAt(pos) {
|
|
||||||
return (core.primAt self pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun primtAtPut(pos value) {
|
|
||||||
return (core.primAtPut self pos value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun basicAt(pos) {
|
|
||||||
return (core.basicAt self pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun basicAtPut(pos value) {
|
|
||||||
return (core.basicAtPut self pos value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun basicSize() {
|
|
||||||
return (core.basicSize self)
|
|
||||||
}
|
|
||||||
|
|
||||||
## TODO: ...
|
|
||||||
fun == (oprnd) { return (== self oprnd) }
|
|
||||||
fun != (oprnd) { return (!= self oprnd) }
|
|
||||||
## TODO: fun perform(name ...) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
class[#uncopyable #varying #limited #final] Class: Apex (
|
|
||||||
_name
|
|
||||||
_mdic
|
|
||||||
_spec
|
|
||||||
_selfspec
|
|
||||||
_superclass
|
|
||||||
_nivars_super
|
|
||||||
_ibrand
|
|
||||||
_ivarnames
|
|
||||||
_cvarnames
|
|
||||||
) {
|
|
||||||
fun name() {
|
|
||||||
##return (core.className self)
|
|
||||||
return _class
|
|
||||||
}
|
|
||||||
|
|
||||||
fun instanceVariableNames() {
|
|
||||||
## TODO: this still returns nil as the acutal manipulation of the field has not been implemented
|
|
||||||
return _ivarnames
|
|
||||||
}
|
|
||||||
|
|
||||||
fun classVariableNames() {
|
|
||||||
## TODO: this still returns nil as the acutal manipulation of the field has not been implemented
|
|
||||||
return _cvarnames
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UndefinedObject: Apex {
|
|
||||||
fun isNil?() { return true }
|
|
||||||
fun notNil?() { return false }
|
|
||||||
}
|
|
||||||
|
|
||||||
class Object: Apex {
|
|
||||||
}
|
|
||||||
|
|
||||||
## ---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
$include "Magnitude.hak"
|
$include "Magnitude.hak"
|
||||||
$include "Collection.hak"
|
$include "Collection.hak"
|
||||||
|
$include "Semaphore.hak"
|
||||||
|
|
||||||
##$include "System.hak"
|
##$include "System.hak"
|
||||||
|
|
||||||
## ---------------------------------------------------------------------------------
|
## ---------------------------------------------------------------------------------
|
||||||
|
|||||||
+19
-19
@@ -37,9 +37,9 @@ class ChildGroup(
|
|||||||
sigsem ## the shared semaphore; only in shared mode
|
sigsem ## the shared semaphore; only in shared mode
|
||||||
) {
|
) {
|
||||||
fun[#ci] new() {
|
fun[#ci] new() {
|
||||||
set sg (semgr-new)
|
set sg (core.semgr-new)
|
||||||
set tmo (sem-new)
|
set tmo (core.sem-new)
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
set capa 8
|
set capa 8
|
||||||
set kids (core.basicNew Array 8)
|
set kids (core.basicNew Array 8)
|
||||||
set nkids 0
|
set nkids 0
|
||||||
@@ -107,16 +107,16 @@ class ChildGroup(
|
|||||||
## semaphore on the signal descriptor for the whole group, once.
|
## semaphore on the signal descriptor for the whole group, once.
|
||||||
if (not self.shared) {
|
if (not self.shared) {
|
||||||
set shared true
|
set shared true
|
||||||
system-catch-sig sys.SIGCHLD
|
sys.sig-catch sys.SIGCHLD
|
||||||
set sigsem (sem-new)
|
set sigsem (core.sem-new)
|
||||||
semgr-add self.sg self.sigsem
|
core.semgr-add self.sg self.sigsem
|
||||||
sem-signal-on-input self.sigsem (system-get-sigfd)
|
core.sem-signal-on-input self.sigsem (sys.sig-getfd)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
## A handle of its own, so a wakeup identifies this child directly.
|
## A handle of its own, so a wakeup identifies this child directly.
|
||||||
sem := (sem-new)
|
sem := (core.sem-new)
|
||||||
semgr-add self.sg sem
|
core.semgr-add self.sg sem
|
||||||
sem-signal-on-input sem xh
|
core.sem-signal-on-input sem xh
|
||||||
}
|
}
|
||||||
|
|
||||||
kid := (core.basicNew Array 6)
|
kid := (core.basicNew Array 6)
|
||||||
@@ -171,16 +171,16 @@ class ChildGroup(
|
|||||||
if (not (nil? kid)) { return kid }
|
if (not (nil? kid)) { return kid }
|
||||||
|
|
||||||
while true {
|
while true {
|
||||||
sem-signal self.tmo secs 0
|
core.sem-signal self.tmo secs 0
|
||||||
w := (semgr-wait self.sg)
|
w := (core.semgr-wait self.sg)
|
||||||
sem-unsignal self.tmo
|
core.sem-unsignal self.tmo
|
||||||
|
|
||||||
if (eqv? w self.tmo) { return nil }
|
if (eqv? w self.tmo) { return nil }
|
||||||
|
|
||||||
if self.shared {
|
if self.shared {
|
||||||
## the signal descriptor spoke: take the byte, then look at
|
## the signal descriptor spoke: take the byte, then look at
|
||||||
## everyone, since one SIGCHLD may stand for several exits
|
## everyone, since one SIGCHLD may stand for several exits
|
||||||
system-get-sig
|
sys.sig-get
|
||||||
kid := (self:finished)
|
kid := (self:finished)
|
||||||
if (not (nil? kid)) { return kid }
|
if (not (nil? kid)) { return kid }
|
||||||
## otherwise it was a SIGCHLD for a child of the host
|
## otherwise it was a SIGCHLD for a child of the host
|
||||||
@@ -188,7 +188,7 @@ class ChildGroup(
|
|||||||
} else {
|
} else {
|
||||||
kid := (self:kid-of-sem w)
|
kid := (self:kid-of-sem w)
|
||||||
if (not (nil? kid)) {
|
if (not (nil? kid)) {
|
||||||
sem-unsignal w
|
core.sem-unsignal w
|
||||||
return kid
|
return kid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,8 +210,8 @@ class ChildGroup(
|
|||||||
| sem |
|
| sem |
|
||||||
sem := (core.basicAt kid 5)
|
sem := (core.basicAt kid 5)
|
||||||
if (not (nil? sem)) {
|
if (not (nil? sem)) {
|
||||||
sem-unsignal sem
|
core.sem-unsignal sem
|
||||||
semgr-remove self.sg sem
|
core.semgr-remove self.sg sem
|
||||||
}
|
}
|
||||||
self:forget kid
|
self:forget kid
|
||||||
sys.pclose (core.basicAt kid 0)
|
sys.pclose (core.basicAt kid 0)
|
||||||
@@ -227,8 +227,8 @@ class ChildGroup(
|
|||||||
i := (+ i 1)
|
i := (+ i 1)
|
||||||
}
|
}
|
||||||
if self.shared {
|
if self.shared {
|
||||||
sem-unsignal self.sigsem
|
core.sem-unsignal self.sigsem
|
||||||
system-uncatch-sig sys.SIGCHLD
|
sys.sig-uncatch sys.SIGCHLD
|
||||||
set shared false
|
set shared false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ AM_CPPFLAGS = \
|
|||||||
-I$(abs_builddir)/../lib \
|
-I$(abs_builddir)/../lib \
|
||||||
-I$(abs_srcdir) \
|
-I$(abs_srcdir) \
|
||||||
-I$(abs_srcdir)/../lib \
|
-I$(abs_srcdir)/../lib \
|
||||||
-I$(includedir)
|
-I$(includedir) \
|
||||||
|
-DHAK_TEST_MODLIBDIRS='"@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs"'
|
||||||
LDADD = ../lib/libhak.la
|
LDADD = ../lib/libhak.la
|
||||||
|
|
||||||
check_SCRIPTS = \
|
check_SCRIPTS = \
|
||||||
|
|||||||
+2
-1
@@ -550,7 +550,8 @@ AM_CPPFLAGS = \
|
|||||||
-I$(abs_builddir)/../lib \
|
-I$(abs_builddir)/../lib \
|
||||||
-I$(abs_srcdir) \
|
-I$(abs_srcdir) \
|
||||||
-I$(abs_srcdir)/../lib \
|
-I$(abs_srcdir)/../lib \
|
||||||
-I$(includedir)
|
-I$(includedir) \
|
||||||
|
-DHAK_TEST_MODLIBDIRS='"@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs"'
|
||||||
|
|
||||||
LDADD = ../lib/libhak.la
|
LDADD = ../lib/libhak.la
|
||||||
check_SCRIPTS = \
|
check_SCRIPTS = \
|
||||||
|
|||||||
+17
-17
@@ -7,21 +7,21 @@ fun chk(ok msg) {
|
|||||||
else { printf "ERROR: %s\n" msg }
|
else { printf "ERROR: %s\n" msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
iosem := (sem-new)
|
iosem := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
semgr-add sg iosem
|
core.semgr-add sg iosem
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
fin := (sem-new)
|
fin := (core.sem-new)
|
||||||
|
|
||||||
## returns 1 when the handle became readable, 0 when the timeout won
|
## returns 1 when the handle became readable, 0 when the timeout won
|
||||||
fun waitin(h secs) {
|
fun waitin(h secs) {
|
||||||
| s |
|
| s |
|
||||||
sem-signal tmo secs 0
|
core.sem-signal tmo secs 0
|
||||||
sem-signal-on-input iosem h
|
core.sem-signal-on-input iosem h
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
sem-unsignal iosem
|
core.sem-unsignal iosem
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
if (eqv? s tmo) { return 0 } \
|
if (eqv? s tmo) { return 0 } \
|
||||||
else { return 1 }
|
else { return 1 }
|
||||||
}
|
}
|
||||||
@@ -46,12 +46,12 @@ fun reader() {
|
|||||||
n := (sys.read r buf)
|
n := (sys.read r buf)
|
||||||
if (>= n 0) {
|
if (>= n 0) {
|
||||||
got := n
|
got := n
|
||||||
sem-signal fin
|
core.sem-signal fin
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if (= (waitin r 5) 0) {
|
if (= (waitin r 5) 0) {
|
||||||
got := -1
|
got := -1
|
||||||
sem-signal fin
|
core.sem-signal fin
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ fun writer() {
|
|||||||
## so these ticks only happen if the VM is still scheduling
|
## so these ticks only happen if the VM is still scheduling
|
||||||
while (< ticks 4) {
|
while (< ticks 4) {
|
||||||
ticks := (+ ticks 1)
|
ticks := (+ ticks 1)
|
||||||
yield
|
core.yield
|
||||||
}
|
}
|
||||||
wb := (core.basicNew ByteArray 2)
|
wb := (core.basicNew ByteArray 2)
|
||||||
core.basicAtPut wb 0 120
|
core.basicAtPut wb 0 120
|
||||||
@@ -71,9 +71,9 @@ fun writer() {
|
|||||||
sys.write w wb
|
sys.write w wb
|
||||||
}
|
}
|
||||||
|
|
||||||
fork reader
|
core.fork reader
|
||||||
fork writer
|
core.fork writer
|
||||||
sem-wait fin
|
core.sem-wait fin
|
||||||
|
|
||||||
chk (= ticks 4) "other coprocesses ran while the reader was blocked"
|
chk (= ticks 4) "other coprocesses ran while the reader was blocked"
|
||||||
chk (= got 2) "the reader woke and read the data"
|
chk (= got 2) "the reader woke and read the data"
|
||||||
|
|||||||
+6
-6
@@ -2,13 +2,13 @@
|
|||||||
## stops hak code naming a descriptor it never opened - including hak's own
|
## stops hak code naming a descriptor it never opened - including hak's own
|
||||||
## multiplexer, signal and io-thread descriptors, and anything the host
|
## multiplexer, signal and io-thread descriptors, and anything the host
|
||||||
## application that embeds hak holds open.
|
## application that embeds hak holds open.
|
||||||
s := (sem-new)
|
s := (core.sem-new)
|
||||||
sem-signal-on-input s 0 ##ERROR: system handle 0
|
core.sem-signal-on-input s 0 ##ERROR: system handle 0
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
s := (sem-new)
|
s := (core.sem-new)
|
||||||
sem-signal-on-input s 4 ##ERROR: system handle 4
|
core.sem-signal-on-input s 4 ##ERROR: system handle 4
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ sys.read r (core.basicNew ByteArray 4) ##ERROR: system handle 0
|
|||||||
## a regular file is never accepted by the multiplexer: epoll refuses one
|
## a regular file is never accepted by the multiplexer: epoll refuses one
|
||||||
## outright, and poll() would report it permanently ready
|
## outright, and poll() would report it permanently ready
|
||||||
f := (sys.open "/etc/passwd" "r")
|
f := (sys.open "/etc/passwd" "r")
|
||||||
s := (sem-new)
|
s := (core.sem-new)
|
||||||
sem-signal-on-input s f ##ERROR: not of an acceptable kind
|
core.sem-signal-on-input s f ##ERROR: not of an acceptable kind
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ a := (b:get-a)
|
|||||||
if (a != 4) {printf "ERROR: a must be 4\n" } \
|
if (a != 4) {printf "ERROR: a must be 4\n" } \
|
||||||
else { printf "OK %d\n" a }
|
else { printf "OK %d\n" a }
|
||||||
|
|
||||||
c := (object-new A)
|
c := (core.object-new A)
|
||||||
a := (c:get-a)
|
a := (c:get-a)
|
||||||
if (a != nil) {printf "ERROR: a must be nil\n" } \
|
if (a != nil) {printf "ERROR: a must be nil\n" } \
|
||||||
else { printf "OK %O\n" a }
|
else { printf "OK %O\n" a }
|
||||||
|
|||||||
+10
-10
@@ -16,20 +16,20 @@ fun chk(ok msg) {
|
|||||||
else { printf "ERROR: %s\n" msg }
|
else { printf "ERROR: %s\n" msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
iosem := (sem-new)
|
iosem := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
semgr-add sg iosem
|
core.semgr-add sg iosem
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
|
|
||||||
## 1 when the handle became readable, 0 when the timer won instead
|
## 1 when the handle became readable, 0 when the timer won instead
|
||||||
fun waitin(h secs) {
|
fun waitin(h secs) {
|
||||||
| s |
|
| s |
|
||||||
sem-signal tmo secs 0
|
core.sem-signal tmo secs 0
|
||||||
sem-signal-on-input iosem h
|
core.sem-signal-on-input iosem h
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
sem-unsignal iosem
|
core.sem-unsignal iosem
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
if (eqv? s tmo) { return 0 } else { return 1 }
|
if (eqv? s tmo) { return 0 } else { return 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -15,15 +15,15 @@ fun chk(ok msg) {
|
|||||||
else { printf "ERROR: %s\n" msg }
|
else { printf "ERROR: %s\n" msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
sa := (sem-new)
|
sa := (core.sem-new)
|
||||||
sb := (sem-new)
|
sb := (core.sem-new)
|
||||||
sc := (sem-new)
|
sc := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
semgr-add sg sa
|
core.semgr-add sg sa
|
||||||
semgr-add sg sb
|
core.semgr-add sg sb
|
||||||
semgr-add sg sc
|
core.semgr-add sg sc
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
|
|
||||||
## staggered so the completion order is a, then b, then c
|
## staggered so the completion order is a, then b, then c
|
||||||
pa := (sys.popen "sleep 0.2; echo aaa" "r")
|
pa := (sys.popen "sleep 0.2; echo aaa" "r")
|
||||||
@@ -35,14 +35,14 @@ hb := (core.basicAt pb 2)
|
|||||||
hc := (core.basicAt pc 2)
|
hc := (core.basicAt pc 2)
|
||||||
|
|
||||||
## all three bound at the same time - three live tuple entries
|
## all three bound at the same time - three live tuple entries
|
||||||
sem-signal-on-input sa ha
|
core.sem-signal-on-input sa ha
|
||||||
sem-signal-on-input sb hb
|
core.sem-signal-on-input sb hb
|
||||||
sem-signal-on-input sc hc
|
core.sem-signal-on-input sc hc
|
||||||
sem-signal tmo 9 0
|
core.sem-signal tmo 9 0
|
||||||
|
|
||||||
fun expect(want h name) {
|
fun expect(want h name) {
|
||||||
| s buf got |
|
| s buf got |
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
chk (eqv? s want) name
|
chk (eqv? s want) name
|
||||||
buf := (core.basicNew ByteArray 8)
|
buf := (core.basicNew ByteArray 8)
|
||||||
got := (sys.read h buf)
|
got := (sys.read h buf)
|
||||||
@@ -52,15 +52,15 @@ fun expect(want h name) {
|
|||||||
## unbinding sa frees the first slot, so the last entry migrates into it and
|
## unbinding sa frees the first slot, so the last entry migrates into it and
|
||||||
## sb/sc must still resolve to their own handles afterwards
|
## sb/sc must still resolve to their own handles afterwards
|
||||||
expect sa ha "the first child woke its own semaphore"
|
expect sa ha "the first child woke its own semaphore"
|
||||||
sem-unsignal sa
|
core.sem-unsignal sa
|
||||||
|
|
||||||
expect sb hb "the second child woke its own semaphore after compaction"
|
expect sb hb "the second child woke its own semaphore after compaction"
|
||||||
sem-unsignal sb
|
core.sem-unsignal sb
|
||||||
|
|
||||||
expect sc hc "the third child woke its own semaphore after compaction"
|
expect sc hc "the third child woke its own semaphore after compaction"
|
||||||
sem-unsignal sc
|
core.sem-unsignal sc
|
||||||
|
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
sys.pclose (core.basicAt pa 0)
|
sys.pclose (core.basicAt pa 0)
|
||||||
sys.pclose (core.basicAt pb 0)
|
sys.pclose (core.basicAt pb 0)
|
||||||
sys.pclose (core.basicAt pc 0)
|
sys.pclose (core.basicAt pc 0)
|
||||||
|
|||||||
+22
-22
@@ -16,52 +16,52 @@ fun chk(ok msg) {
|
|||||||
else { printf "ERROR: %s\n" msg }
|
else { printf "ERROR: %s\n" msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
isem := (sem-new)
|
isem := (core.sem-new)
|
||||||
osem := (sem-new)
|
osem := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
semgr-add sg isem
|
core.semgr-add sg isem
|
||||||
semgr-add sg osem
|
core.semgr-add sg osem
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
|
|
||||||
p := (sys.pipe)
|
p := (sys.pipe)
|
||||||
r := (core.basicAt p 0)
|
r := (core.basicAt p 0)
|
||||||
w := (core.basicAt p 1)
|
w := (core.basicAt p 1)
|
||||||
|
|
||||||
## one descriptor, two directions - the tuple now carries both
|
## one descriptor, two directions - the tuple now carries both
|
||||||
sem-signal-on-input isem w
|
core.sem-signal-on-input isem w
|
||||||
sem-signal-on-output osem w
|
core.sem-signal-on-output osem w
|
||||||
|
|
||||||
## drop only the input direction. the output registration must survive, and so
|
## drop only the input direction. the output registration must survive, and so
|
||||||
## must any event already reported for it
|
## must any event already reported for it
|
||||||
sem-unsignal isem
|
core.sem-unsignal isem
|
||||||
|
|
||||||
sem-signal tmo 5 0
|
core.sem-signal tmo 5 0
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
chk (eqv? s osem) "the surviving direction still reports after a partial unbind"
|
chk (eqv? s osem) "the surviving direction still reports after a partial unbind"
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
|
|
||||||
## put the input direction back while the output one is still registered. this
|
## put the input direction back while the output one is still registered. this
|
||||||
## is the add branch of the modify path - the mirror of the drop above - and it
|
## is the add branch of the modify path - the mirror of the drop above - and it
|
||||||
## has to leave the output registration alone.
|
## has to leave the output registration alone.
|
||||||
sem-signal-on-input isem w
|
core.sem-signal-on-input isem w
|
||||||
|
|
||||||
## now drop the output direction instead, keeping input. a write end is never
|
## now drop the output direction instead, keeping input. a write end is never
|
||||||
## readable, so with input alone nothing can report and the timer must win. if
|
## readable, so with input alone nothing can report and the timer must win. if
|
||||||
## the modify path had left the output registration behind, its writability
|
## the modify path had left the output registration behind, its writability
|
||||||
## would be reported here and the timer would lose.
|
## would be reported here and the timer would lose.
|
||||||
sem-unsignal osem
|
core.sem-unsignal osem
|
||||||
sem-signal tmo 0 300000000
|
core.sem-signal tmo 0 300000000
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
chk (eqv? s tmo) "the dropped direction stops reporting after a partial unbind"
|
chk (eqv? s tmo) "the dropped direction stops reporting after a partial unbind"
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
|
|
||||||
## and the full unbind from that state really removes the registration
|
## and the full unbind from that state really removes the registration
|
||||||
sem-unsignal isem
|
core.sem-unsignal isem
|
||||||
sem-signal tmo 0 300000000
|
core.sem-signal tmo 0 300000000
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
chk (eqv? s tmo) "nothing reports once both directions are unbound"
|
chk (eqv? s tmo) "nothing reports once both directions are unbound"
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
|
|
||||||
sys.close r
|
sys.close r
|
||||||
sys.close w
|
sys.close w
|
||||||
|
|||||||
+14
-14
@@ -8,11 +8,11 @@ fun loop1() {
|
|||||||
while (< k 100) {
|
while (< k 100) {
|
||||||
printf "loop1 => %d\n" k
|
printf "loop1 => %d\n" k
|
||||||
k := (+ k 2)
|
k := (+ k 2)
|
||||||
yield
|
core.yield
|
||||||
}
|
}
|
||||||
|
|
||||||
z1 := k
|
z1 := k
|
||||||
sem-signal s1
|
core.sem-signal s1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loop2() {
|
fun loop2() {
|
||||||
@@ -22,26 +22,26 @@ fun loop2() {
|
|||||||
while (< k 100) {
|
while (< k 100) {
|
||||||
printf "loop2 => %d\n" k
|
printf "loop2 => %d\n" k
|
||||||
k := (+ k 2)
|
k := (+ k 2)
|
||||||
yield
|
core.yield
|
||||||
}
|
}
|
||||||
|
|
||||||
z2 := k
|
z2 := k
|
||||||
sem-signal s2
|
core.sem-signal s2
|
||||||
}
|
}
|
||||||
|
|
||||||
s1 := (sem-new)
|
s1 := (core.sem-new)
|
||||||
s2 := (sem-new)
|
s2 := (core.sem-new)
|
||||||
|
|
||||||
p1 := (fork loop1)
|
p1 := (core.fork loop1)
|
||||||
p2 := (fork loop2)
|
p2 := (core.fork loop2)
|
||||||
|
|
||||||
##suspend p1
|
##core.suspend p1
|
||||||
##suspend p2
|
##core.suspend p2
|
||||||
##resume p1
|
##core.resume p1
|
||||||
##resume p2
|
##core.resume p2
|
||||||
|
|
||||||
sem-wait s1
|
core.sem-wait s1
|
||||||
sem-wait s2
|
core.sem-wait s2
|
||||||
|
|
||||||
if (== z1 101) { printf "OK: z1 is %d\n" z1 } \
|
if (== z1 101) { printf "OK: z1 is %d\n" z1 } \
|
||||||
else { printf "ERROR: z1 is not 101 - %d\n" z1 }
|
else { printf "ERROR: z1 is not 101 - %d\n" z1 }
|
||||||
|
|||||||
+2
-2
@@ -22,10 +22,10 @@ ticks := 0
|
|||||||
fun ticker() {
|
fun ticker() {
|
||||||
while (< ticks 5) {
|
while (< ticks 5) {
|
||||||
ticks := (+ ticks 1)
|
ticks := (+ ticks 1)
|
||||||
yield
|
core.yield
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fork ticker
|
core.fork ticker
|
||||||
|
|
||||||
order := (core.basicNew Array 3)
|
order := (core.basicNew Array 3)
|
||||||
n := 0
|
n := 0
|
||||||
|
|||||||
+24
-24
@@ -27,23 +27,23 @@ sys.close (core.basicAt q 0)
|
|||||||
sys.close (core.basicAt q 1)
|
sys.close (core.basicAt q 1)
|
||||||
|
|
||||||
## --- catch and uncatch are idempotent ---
|
## --- catch and uncatch are idempotent ---
|
||||||
chk (= (system-catch-sig sys.SIGUSR1) sys.SIGUSR1) "system-catch-sig returns the signal number"
|
chk (= (sys.sig-catch sys.SIGUSR1) sys.SIGUSR1) "sys.sig-catch returns the signal number"
|
||||||
chk (= (system-catch-sig sys.SIGUSR1) sys.SIGUSR1) "catching an already caught signal is fine"
|
chk (= (sys.sig-catch sys.SIGUSR1) sys.SIGUSR1) "catching an already caught signal is fine"
|
||||||
chk (= (system-uncatch-sig sys.SIGUSR1) sys.SIGUSR1) "system-uncatch-sig returns the signal number"
|
chk (= (sys.sig-uncatch sys.SIGUSR1) sys.SIGUSR1) "sys.sig-uncatch returns the signal number"
|
||||||
chk (= (system-uncatch-sig sys.SIGUSR1) sys.SIGUSR1) "uncatching an uncaught signal is fine"
|
chk (= (sys.sig-uncatch sys.SIGUSR1) sys.SIGUSR1) "uncatching an uncaught signal is fine"
|
||||||
|
|
||||||
## --- a real signal reaches hak code, without stalling the coprocesses ---
|
## --- a real signal reaches hak code, without stalling the coprocesses ---
|
||||||
## SIGCHLD is used because a child exiting is something this test can arrange
|
## SIGCHLD is used because a child exiting is something this test can arrange
|
||||||
## on its own, with no outside help.
|
## on its own, with no outside help.
|
||||||
system-catch-sig sys.SIGCHLD
|
sys.sig-catch sys.SIGCHLD
|
||||||
|
|
||||||
h := (system-get-sigfd)
|
h := (sys.sig-getfd)
|
||||||
s := (sem-new)
|
s := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
semgr-add sg s
|
core.semgr-add sg s
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
fin := (sem-new)
|
fin := (core.sem-new)
|
||||||
ticks := 0
|
ticks := 0
|
||||||
signo := -1
|
signo := -1
|
||||||
|
|
||||||
@@ -52,14 +52,14 @@ proc := (core.basicAt pr 0)
|
|||||||
|
|
||||||
fun waiter() {
|
fun waiter() {
|
||||||
| w |
|
| w |
|
||||||
sem-signal tmo 20 0
|
core.sem-signal tmo 20 0
|
||||||
sem-signal-on-input s h
|
core.sem-signal-on-input s h
|
||||||
w := (semgr-wait sg)
|
w := (core.semgr-wait sg)
|
||||||
sem-unsignal s
|
core.sem-unsignal s
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
if (eqv? w tmo) { signo := -2 } \
|
if (eqv? w tmo) { signo := -2 } \
|
||||||
else { signo := (system-get-sig) }
|
else { signo := (sys.sig-get) }
|
||||||
sem-signal fin
|
core.sem-signal fin
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,16 +67,16 @@ fun ticker() {
|
|||||||
## the waiter is parked on the signal descriptor by now
|
## the waiter is parked on the signal descriptor by now
|
||||||
while (< ticks 4) {
|
while (< ticks 4) {
|
||||||
ticks := (+ ticks 1)
|
ticks := (+ ticks 1)
|
||||||
yield
|
core.yield
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fork waiter
|
core.fork waiter
|
||||||
fork ticker
|
core.fork ticker
|
||||||
sem-wait fin
|
core.sem-wait fin
|
||||||
|
|
||||||
chk (= ticks 4) "coprocesses ran while a coprocess waited on a signal"
|
chk (= ticks 4) "coprocesses ran while a coprocess waited on a signal"
|
||||||
chk (= signo sys.SIGCHLD) "the signal number came through the signal descriptor"
|
chk (= signo sys.SIGCHLD) "the signal number came through the signal descriptor"
|
||||||
chk (= (sys.pwait proc) 4) "and the child's exit status is readable"
|
chk (= (sys.pwait proc) 4) "and the child's exit status is readable"
|
||||||
sys.pclose proc
|
sys.pclose proc
|
||||||
system-uncatch-sig sys.SIGCHLD
|
sys.sig-uncatch sys.SIGCHLD
|
||||||
|
|||||||
+3
-3
@@ -54,8 +54,8 @@ chk (== sys.SIGTERM 15) "SIGTERM is 15"
|
|||||||
|
|
||||||
## and the constants behave: a routable one can be caught, an unroutable one
|
## and the constants behave: a routable one can be caught, an unroutable one
|
||||||
## cannot, whatever the numbers happen to be here
|
## cannot, whatever the numbers happen to be here
|
||||||
chk (== (system-catch-sig sys.SIGUSR1) sys.SIGUSR1) "SIGUSR1 is catchable"
|
chk (== (sys.sig-catch sys.SIGUSR1) sys.SIGUSR1) "SIGUSR1 is catchable"
|
||||||
chk (== (system-uncatch-sig sys.SIGUSR1) sys.SIGUSR1) "SIGUSR1 is uncatchable again"
|
chk (== (sys.sig-uncatch sys.SIGUSR1) sys.SIGUSR1) "SIGUSR1 is uncatchable again"
|
||||||
raised := false
|
raised := false
|
||||||
try { system-catch-sig sys.SIGKILL } catch (e) { raised := true }
|
try { sys.sig-catch sys.SIGKILL } catch (e) { raised := true }
|
||||||
chk raised "SIGKILL is refused"
|
chk raised "SIGKILL is refused"
|
||||||
|
|||||||
+10
-10
@@ -1,41 +1,41 @@
|
|||||||
## signals that cannot be caught
|
## signals that cannot be caught
|
||||||
system-catch-sig sys.SIGKILL ##ERROR: not routable
|
sys.sig-catch sys.SIGKILL ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig sys.SIGSTOP ##ERROR: not routable
|
sys.sig-catch sys.SIGSTOP ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## signals that indicate a crash: turning one into a byte on a pipe and
|
## signals that indicate a crash: turning one into a byte on a pipe and
|
||||||
## carrying on would hide the fault rather than report it
|
## carrying on would hide the fault rather than report it
|
||||||
system-catch-sig sys.SIGSEGV ##ERROR: not routable
|
sys.sig-catch sys.SIGSEGV ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig sys.SIGBUS ##ERROR: not routable
|
sys.sig-catch sys.SIGBUS ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig sys.SIGFPE ##ERROR: not routable
|
sys.sig-catch sys.SIGFPE ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig sys.SIGILL ##ERROR: not routable
|
sys.sig-catch sys.SIGILL ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## the timer signal hak itself uses to switch processes
|
## the timer signal hak itself uses to switch processes
|
||||||
system-catch-sig sys.SIGVTALRM ##ERROR: not routable
|
sys.sig-catch sys.SIGVTALRM ##ERROR: not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig 0 ##ERROR: 0 not routable
|
sys.sig-catch 0 ##ERROR: 0 not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig 9999 ##ERROR: 9999 not routable
|
sys.sig-catch 9999 ##ERROR: 9999 not routable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
system-catch-sig "two" ##ERROR: number not a small integer
|
sys.sig-catch "two" ##ERROR: number not a small integer
|
||||||
|
|||||||
+13
-13
@@ -5,19 +5,19 @@ fun chk(ok msg) {
|
|||||||
else { printf "ERROR: %s\n" msg }
|
else { printf "ERROR: %s\n" msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
iosem := (sem-new)
|
iosem := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
semgr-add sg iosem
|
core.semgr-add sg iosem
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
|
|
||||||
fun waitin(h secs) {
|
fun waitin(h secs) {
|
||||||
| s |
|
| s |
|
||||||
sem-signal tmo secs 0
|
core.sem-signal tmo secs 0
|
||||||
sem-signal-on-input iosem h
|
core.sem-signal-on-input iosem h
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
sem-unsignal iosem
|
core.sem-unsignal iosem
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
if (eqv? s tmo) { return 0 } else { return 1 }
|
if (eqv? s tmo) { return 0 } else { return 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,9 +38,9 @@ fun reap(proc) {
|
|||||||
while (< k 300) {
|
while (< k 300) {
|
||||||
n := (sys.pwait proc)
|
n := (sys.pwait proc)
|
||||||
if (not (= n 256)) { return n }
|
if (not (= n 256)) { return n }
|
||||||
sem-signal tmo 0 20000000
|
core.sem-signal tmo 0 20000000
|
||||||
semgr-wait sg
|
core.semgr-wait sg
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
k := (+ k 1)
|
k := (+ k 1)
|
||||||
}
|
}
|
||||||
return 256
|
return 256
|
||||||
|
|||||||
+16
-16
@@ -9,12 +9,12 @@ fun chk(ok msg) {
|
|||||||
else { printf "ERROR: %s\n" msg }
|
else { printf "ERROR: %s\n" msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
iosem := (sem-new)
|
iosem := (core.sem-new)
|
||||||
tmo := (sem-new)
|
tmo := (core.sem-new)
|
||||||
sg := (semgr-new)
|
sg := (core.semgr-new)
|
||||||
semgr-add sg iosem
|
core.semgr-add sg iosem
|
||||||
semgr-add sg tmo
|
core.semgr-add sg tmo
|
||||||
fin := (sem-new)
|
fin := (core.sem-new)
|
||||||
|
|
||||||
p := (sys.popen "sleep 1; exit 5" "r")
|
p := (sys.popen "sleep 1; exit 5" "r")
|
||||||
proc := (core.basicAt p 0)
|
proc := (core.basicAt p 0)
|
||||||
@@ -30,14 +30,14 @@ else {
|
|||||||
|
|
||||||
fun waiter() {
|
fun waiter() {
|
||||||
| s |
|
| s |
|
||||||
sem-signal tmo 20 0
|
core.sem-signal tmo 20 0
|
||||||
sem-signal-on-input iosem xh
|
core.sem-signal-on-input iosem xh
|
||||||
s := (semgr-wait sg)
|
s := (core.semgr-wait sg)
|
||||||
sem-unsignal iosem
|
core.sem-unsignal iosem
|
||||||
sem-unsignal tmo
|
core.sem-unsignal tmo
|
||||||
if (eqv? s tmo) { status := -1 } \
|
if (eqv? s tmo) { status := -1 } \
|
||||||
else { status := (sys.pwait proc) }
|
else { status := (sys.pwait proc) }
|
||||||
sem-signal fin
|
core.sem-signal fin
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,14 +46,14 @@ else {
|
|||||||
## happen if the VM went on scheduling instead of blocking
|
## happen if the VM went on scheduling instead of blocking
|
||||||
while (< ticks 4) {
|
while (< ticks 4) {
|
||||||
ticks := (+ ticks 1)
|
ticks := (+ ticks 1)
|
||||||
yield
|
core.yield
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chk (integer? xh) "sys.popen hands back an exit handle"
|
chk (integer? xh) "sys.popen hands back an exit handle"
|
||||||
fork waiter
|
core.fork waiter
|
||||||
fork ticker
|
core.fork ticker
|
||||||
sem-wait fin
|
core.sem-wait fin
|
||||||
|
|
||||||
chk (= ticks 4) "other coprocesses ran while the child was alive"
|
chk (= ticks 4) "other coprocesses ran while the child was alive"
|
||||||
chk (= status 5) "the exit handle woke the waiter and the status was read"
|
chk (= status 5) "the exit handle woke the waiter and the status was read"
|
||||||
|
|||||||
@@ -80,12 +80,12 @@ static void state_contract (void)
|
|||||||
|
|
||||||
static const char SRC[] =
|
static const char SRC[] =
|
||||||
"flag := 0\n"
|
"flag := 0\n"
|
||||||
"s := (sem-new)\n"
|
"s := (core.sem-new)\n"
|
||||||
"fun setter() { flag := 1 ; sem-signal s }\n"
|
"fun setter() { flag := 1 ; core.sem-signal s }\n"
|
||||||
"p := (fork setter)\n"
|
"p := (core.fork setter)\n"
|
||||||
"i := 0\n"
|
"i := 0\n"
|
||||||
"while (< i 300000) { if (== flag 1) { break } ; i := (+ i 1) }\n"
|
"while (< i 300000) { if (== flag 1) { break } ; i := (+ i 1) }\n"
|
||||||
"sem-wait s\n"
|
"core.sem-wait s\n"
|
||||||
"r := i\n";
|
"r := i\n";
|
||||||
|
|
||||||
static hak_oow_t bc_seen = 0;
|
static hak_oow_t bc_seen = 0;
|
||||||
@@ -105,6 +105,22 @@ static int on_cnode (hak_t* hak, hak_cnode_t* obj)
|
|||||||
return hak_compile(hak, obj, 0);
|
return hak_compile(hak, obj, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The script below reaches the process and semaphore primitives through the
|
||||||
|
* core module, which is where they are registered. A build configured with
|
||||||
|
* --enable-static-module links that module in and resolves it unaided, but one
|
||||||
|
* without it has to load the module from the build tree, and a bare
|
||||||
|
* hak_openstd() has nowhere to look. HAK_TEST_MODLIBDIRS comes from
|
||||||
|
* t/Makefile.am and names the same directories run.sh passes to the script
|
||||||
|
* tests via --modlibdirs. */
|
||||||
|
static int set_modlibdirs (hak_t* hak)
|
||||||
|
{
|
||||||
|
#if defined(HAK_TEST_MODLIBDIRS)
|
||||||
|
return hak_setoption(hak, HAK_OPT_MODLIBDIRS_BCSTR, HAK_TEST_MODLIBDIRS);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void preempts_a_spinner (void)
|
static void preempts_a_spinner (void)
|
||||||
{
|
{
|
||||||
hak_t* hak;
|
hak_t* hak;
|
||||||
@@ -117,9 +133,11 @@ static void preempts_a_spinner (void)
|
|||||||
OK (hak != HAK_NULL, "instantiation");
|
OK (hak != HAK_NULL, "instantiation");
|
||||||
if (!hak) return;
|
if (!hak) return;
|
||||||
|
|
||||||
hak_getoption(hak, HAK_TRAIT, &trait);
|
hak_getoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
trait |= HAK_TRAIT_AWAIT_PROCS | HAK_TRAIT_LANG_ENABLE_EOL;
|
trait |= HAK_TRAIT_AWAIT_PROCS | HAK_TRAIT_LANG_ENABLE_EOL;
|
||||||
hak_setoption(hak, HAK_TRAIT, &trait);
|
hak_setoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
|
|
||||||
|
OK (set_modlibdirs(hak) == 0, "module search path");
|
||||||
|
|
||||||
memset (&cb, 0, sizeof(cb));
|
memset (&cb, 0, sizeof(cb));
|
||||||
cb.vm_checkbc = cb_checkbc;
|
cb.vm_checkbc = cb_checkbc;
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ static int run_at_depth (int depth, int expect_overflow)
|
|||||||
OK (hak != HAK_NULL, "instantiation");
|
OK (hak != HAK_NULL, "instantiation");
|
||||||
if (!hak) goto done;
|
if (!hak) goto done;
|
||||||
|
|
||||||
hak_getoption(hak, HAK_TRAIT, &trait);
|
hak_getoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
trait |= HAK_TRAIT_LANG_ENABLE_EOL;
|
trait |= HAK_TRAIT_LANG_ENABLE_EOL;
|
||||||
hak_setoption(hak, HAK_TRAIT, &trait);
|
hak_setoption(hak, HAK_OPT_TRAIT, &trait);
|
||||||
|
|
||||||
stksize = STK_SLOTS;
|
stksize = STK_SLOTS;
|
||||||
OK (hak_setoption(hak, HAK_PROCSTK_SIZE, &stksize) == 0, "process stack size");
|
OK (hak_setoption(hak, HAK_OPT_PROCSTK_SIZE, &stksize) == 0, "process stack size");
|
||||||
|
|
||||||
OK (hak_ignite(hak, 0) == 0, "ignition");
|
OK (hak_ignite(hak, 0) == 0, "ignition");
|
||||||
OK (hak_addbuiltinprims(hak) == 0, "builtin primitives");
|
OK (hak_addbuiltinprims(hak) == 0, "builtin primitives");
|
||||||
|
|||||||
+2
-2
@@ -21,7 +21,7 @@ fun setter() { flag := 1 }
|
|||||||
|
|
||||||
## setter is runnable from here on, but it cannot run while this process holds
|
## setter is runnable from here on, but it cannot run while this process holds
|
||||||
## the CPU - and this process never calls yield.
|
## the CPU - and this process never calls yield.
|
||||||
p := (fork setter)
|
p := (core.fork setter)
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
while (< i 3000000) {
|
while (< i 3000000) {
|
||||||
@@ -38,7 +38,7 @@ chk (== flag 1) "a process that never yields is preempted so another can run"
|
|||||||
## process immediately: then setter would have run before the loop started and
|
## process immediately: then setter would have run before the loop started and
|
||||||
## i would be ~0, proving nothing about preemption. One tick is 20ms, which is
|
## i would be ~0, proving nothing about preemption. One tick is 20ms, which is
|
||||||
## a great many iterations.
|
## a great many iterations.
|
||||||
chk (> i 1000) "the switch came from the ticker, not from an eager fork"
|
chk (> i 1000) "the switch came from the ticker, not from an eager core.fork"
|
||||||
|
|
||||||
## The preempted process must be resumed, not abandoned - reaching here at all
|
## The preempted process must be resumed, not abandoned - reaching here at all
|
||||||
## means the scheduler came back to it.
|
## means the scheduler came back to it.
|
||||||
|
|||||||
Reference in New Issue
Block a user