2016-09-28 14:40:37 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2018-02-07 14:13:13 +00:00
|
|
|
Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved.
|
2016-09-28 14:40:37 +00:00
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2023-12-07 14:01:17 +00:00
|
|
|
#if defined(_WIN32)
|
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
#endif
|
|
|
|
|
2021-03-28 03:44:27 +00:00
|
|
|
#include <hcl.h>
|
2024-02-21 16:21:11 +00:00
|
|
|
#include <hcl-chr.h>
|
2021-03-28 03:44:27 +00:00
|
|
|
#include <hcl-utl.h>
|
|
|
|
#include <hcl-opt.h>
|
2016-09-28 14:40:37 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
2018-02-05 10:43:25 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <locale.h>
|
2016-09-28 14:40:37 +00:00
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
# include <windows.h>
|
|
|
|
# include <tchar.h>
|
2018-03-31 07:10:43 +00:00
|
|
|
# include <io.h>
|
|
|
|
# include <fcntl.h>
|
|
|
|
# include <time.h>
|
|
|
|
# include <signal.h>
|
2018-11-03 15:57:14 +00:00
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
#elif defined(__OS2__)
|
|
|
|
# define INCL_DOSMODULEMGR
|
|
|
|
# define INCL_DOSPROCESS
|
|
|
|
# define INCL_DOSERRORS
|
|
|
|
# include <os2.h>
|
2021-03-28 03:44:27 +00:00
|
|
|
# include <signal.h>
|
2018-11-03 15:57:14 +00:00
|
|
|
|
|
|
|
#elif defined(__DOS__)
|
2016-10-06 17:49:47 +00:00
|
|
|
# include <dos.h>
|
2016-10-25 13:44:38 +00:00
|
|
|
# include <time.h>
|
2023-12-09 05:01:03 +00:00
|
|
|
# include <signal.h>
|
2016-09-28 14:40:37 +00:00
|
|
|
#elif defined(macintosh)
|
2016-10-06 17:49:47 +00:00
|
|
|
# include <Timer.h>
|
2016-09-28 14:40:37 +00:00
|
|
|
#else
|
2018-02-09 01:13:11 +00:00
|
|
|
|
2018-11-03 15:57:14 +00:00
|
|
|
# include <sys/types.h>
|
|
|
|
# include <errno.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <fcntl.h>
|
2016-10-06 17:49:47 +00:00
|
|
|
|
|
|
|
# if defined(HAVE_TIME_H)
|
|
|
|
# include <time.h>
|
|
|
|
# endif
|
|
|
|
# if defined(HAVE_SYS_TIME_H)
|
|
|
|
# include <sys/time.h>
|
|
|
|
# endif
|
|
|
|
# if defined(HAVE_SIGNAL_H)
|
|
|
|
# include <signal.h>
|
|
|
|
# endif
|
2023-11-05 07:58:45 +00:00
|
|
|
#endif
|
2016-09-28 14:40:37 +00:00
|
|
|
|
2023-11-05 07:58:45 +00:00
|
|
|
#if defined(__DOS__) || defined(_WIN32) || defined(__OS2__)
|
|
|
|
#define FOPEN_R_FLAGS "rb"
|
|
|
|
#else
|
|
|
|
#define FOPEN_R_FLAGS "r"
|
2018-02-09 03:48:30 +00:00
|
|
|
#endif
|
2016-10-06 17:49:47 +00:00
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
typedef struct bb_t bb_t;
|
|
|
|
struct bb_t
|
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
hcl_oow_t pos;
|
|
|
|
hcl_oow_t len;
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
FILE* fp;
|
2018-02-05 10:43:25 +00:00
|
|
|
hcl_bch_t* fn;
|
2016-09-28 14:40:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct xtn_t xtn_t;
|
|
|
|
struct xtn_t
|
|
|
|
{
|
2023-11-05 13:31:33 +00:00
|
|
|
const char* cci_path; /* main source file */
|
2024-02-02 05:57:46 +00:00
|
|
|
/*const char* udi_path; */ /* not implemented as of snow */
|
2023-11-05 07:58:45 +00:00
|
|
|
const char* udo_path;
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2018-02-08 14:40:56 +00:00
|
|
|
int vm_running;
|
2024-02-21 16:21:11 +00:00
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
hcl_bch_t buf[1024];
|
|
|
|
hcl_oow_t len;
|
|
|
|
hcl_oow_t pos;
|
|
|
|
int eof;
|
2024-04-17 03:20:25 +00:00
|
|
|
hcl_oow_t ncompexprs; /* number of compiled expressions */
|
2024-02-21 16:21:11 +00:00
|
|
|
} feed;
|
2021-03-28 03:44:27 +00:00
|
|
|
/*hcl_oop_t sym_errstr;*/
|
2016-09-28 14:40:37 +00:00
|
|
|
};
|
|
|
|
|
2022-07-29 11:29:47 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
|
|
|
static hcl_t* g_hcl = HCL_NULL;
|
2016-09-28 14:40:37 +00:00
|
|
|
|
|
|
|
/* ========================================================================= */
|
|
|
|
|
2018-11-02 14:15:28 +00:00
|
|
|
static int vm_startup (hcl_t* hcl)
|
2018-03-10 17:53:44 +00:00
|
|
|
{
|
|
|
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
2018-02-08 14:40:56 +00:00
|
|
|
xtn->vm_running = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vm_cleanup (hcl_t* hcl)
|
|
|
|
{
|
2018-03-31 07:10:43 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
2018-11-02 14:15:28 +00:00
|
|
|
xtn->vm_running = 0;
|
2018-02-08 14:40:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-11 11:16:28 +00:00
|
|
|
/*
|
|
|
|
static void vm_checkbc (hcl_t* hcl, hcl_oob_t bcode)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2018-03-08 14:18:30 +00:00
|
|
|
static void gc_hcl (hcl_t* hcl)
|
|
|
|
{
|
2023-05-31 15:30:41 +00:00
|
|
|
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
|
2021-03-28 03:44:27 +00:00
|
|
|
/*if (xtn->sym_errstr) xtn->sym_errstr = hcl_moveoop(hcl, xtn->sym_errstr);*/
|
2018-03-08 14:18:30 +00:00
|
|
|
}
|
|
|
|
|
2018-03-10 17:53:44 +00:00
|
|
|
/* ========================================================================= */
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2021-07-19 18:59:17 +00:00
|
|
|
static int handle_logopt (hcl_t* hcl, const hcl_bch_t* logstr)
|
2018-02-05 10:43:25 +00:00
|
|
|
{
|
2023-12-09 05:01:03 +00:00
|
|
|
const hcl_bch_t* cm, * flt;
|
2018-04-26 04:39:20 +00:00
|
|
|
hcl_bitmask_t logmask;
|
2021-07-19 19:23:18 +00:00
|
|
|
hcl_oow_t tlen, i;
|
2021-07-19 18:59:17 +00:00
|
|
|
hcl_bcs_t fname;
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2021-07-19 19:23:18 +00:00
|
|
|
static struct
|
|
|
|
{
|
|
|
|
const char* name;
|
|
|
|
int op; /* 0: bitwise-OR, 1: bitwise-AND */
|
|
|
|
hcl_bitmask_t mask;
|
|
|
|
} xtab[] =
|
|
|
|
{
|
|
|
|
{ "", 0, 0 },
|
|
|
|
|
|
|
|
{ "app", 0, HCL_LOG_APP },
|
|
|
|
{ "compiler", 0, HCL_LOG_COMPILER },
|
|
|
|
{ "vm", 0, HCL_LOG_VM },
|
|
|
|
{ "mnemonic", 0, HCL_LOG_MNEMONIC },
|
|
|
|
{ "gc", 0, HCL_LOG_GC },
|
|
|
|
{ "ic", 0, HCL_LOG_IC },
|
|
|
|
{ "primitive", 0, HCL_LOG_PRIMITIVE },
|
|
|
|
|
2021-11-21 16:02:39 +00:00
|
|
|
/* select a specific level */
|
2021-07-19 19:23:18 +00:00
|
|
|
{ "fatal", 0, HCL_LOG_FATAL },
|
|
|
|
{ "error", 0, HCL_LOG_ERROR },
|
|
|
|
{ "warn", 0, HCL_LOG_WARN },
|
|
|
|
{ "info", 0, HCL_LOG_INFO },
|
|
|
|
{ "debug", 0, HCL_LOG_DEBUG },
|
|
|
|
|
2021-11-21 16:02:39 +00:00
|
|
|
/* select a specific level or higher */
|
2021-07-19 19:23:18 +00:00
|
|
|
{ "fatal+", 0, HCL_LOG_FATAL },
|
|
|
|
{ "error+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR },
|
|
|
|
{ "warn+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN },
|
|
|
|
{ "info+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO },
|
|
|
|
{ "debug+", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG },
|
|
|
|
|
2021-11-21 16:02:39 +00:00
|
|
|
/* select a specific level or lower */
|
2021-07-19 19:23:18 +00:00
|
|
|
{ "fatal-", 0, HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG },
|
|
|
|
{ "error-", 0, HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG },
|
|
|
|
{ "warn-", 0, HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG },
|
|
|
|
{ "info-", 0, HCL_LOG_INFO | HCL_LOG_DEBUG },
|
|
|
|
{ "debug-", 0, HCL_LOG_DEBUG },
|
|
|
|
|
2021-11-21 16:02:39 +00:00
|
|
|
/* exclude a specific level */
|
2024-04-06 07:52:53 +00:00
|
|
|
{ "-fatal", 1, ~(hcl_bitmask_t)HCL_LOG_FATAL },
|
|
|
|
{ "-error", 1, ~(hcl_bitmask_t)HCL_LOG_ERROR },
|
|
|
|
{ "-warn", 1, ~(hcl_bitmask_t)HCL_LOG_WARN },
|
|
|
|
{ "-info", 1, ~(hcl_bitmask_t)HCL_LOG_INFO },
|
|
|
|
{ "-debug", 1, ~(hcl_bitmask_t)HCL_LOG_DEBUG },
|
2021-07-19 19:23:18 +00:00
|
|
|
};
|
|
|
|
|
2021-07-19 18:59:17 +00:00
|
|
|
cm = hcl_find_bchar_in_bcstr(logstr, ',');
|
2021-03-28 03:44:27 +00:00
|
|
|
if (cm)
|
2018-02-05 10:43:25 +00:00
|
|
|
{
|
2021-07-19 18:59:17 +00:00
|
|
|
fname.len = cm - logstr;
|
2019-04-16 15:46:00 +00:00
|
|
|
logmask = 0;
|
2021-07-19 18:59:17 +00:00
|
|
|
|
2018-02-05 10:43:25 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
flt = cm + 1;
|
|
|
|
|
2021-07-19 18:59:17 +00:00
|
|
|
cm = hcl_find_bchar_in_bcstr(flt, ',');
|
|
|
|
tlen = (cm)? (cm - flt): hcl_count_bcstr(flt);
|
|
|
|
|
2021-07-19 19:23:18 +00:00
|
|
|
for (i = 0; i < HCL_COUNTOF(xtab); i++)
|
|
|
|
{
|
|
|
|
if (hcl_comp_bchars_bcstr(flt, tlen, xtab[i].name) == 0)
|
|
|
|
{
|
|
|
|
if (xtab[i].op) logmask &= xtab[i].mask;
|
|
|
|
else logmask |= xtab[i].mask;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i >= HCL_COUNTOF(xtab))
|
2018-02-05 10:43:25 +00:00
|
|
|
{
|
2021-07-19 19:23:18 +00:00
|
|
|
fprintf (stderr, "ERROR: unrecognized value - [%.*s] - [%s]\n", (int)tlen, flt, logstr);
|
2018-02-05 10:43:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (cm);
|
|
|
|
|
|
|
|
|
2018-03-17 11:57:02 +00:00
|
|
|
if (!(logmask & HCL_LOG_ALL_TYPES)) logmask |= HCL_LOG_ALL_TYPES; /* no types specified. force to all types */
|
|
|
|
if (!(logmask & HCL_LOG_ALL_LEVELS)) logmask |= HCL_LOG_ALL_LEVELS; /* no levels specified. force to all levels */
|
2018-02-05 10:43:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-03-17 11:57:02 +00:00
|
|
|
logmask = HCL_LOG_ALL_LEVELS | HCL_LOG_ALL_TYPES;
|
2021-07-19 18:59:17 +00:00
|
|
|
fname.len = hcl_count_bcstr(logstr);
|
2018-02-05 10:43:25 +00:00
|
|
|
}
|
|
|
|
|
2021-07-19 19:23:18 +00:00
|
|
|
fname.ptr = (hcl_bch_t*)logstr;
|
2021-07-19 18:59:17 +00:00
|
|
|
hcl_setoption (hcl, HCL_LOG_TARGET_BCS, &fname);
|
2019-04-16 15:46:00 +00:00
|
|
|
hcl_setoption (hcl, HCL_LOG_MASK, &logmask);
|
2018-02-05 10:43:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-21 09:30:18 +00:00
|
|
|
#if defined(HCL_BUILD_DEBUG)
|
2018-02-05 10:43:25 +00:00
|
|
|
static int handle_dbgopt (hcl_t* hcl, const hcl_bch_t* str)
|
|
|
|
{
|
2021-01-15 09:12:28 +00:00
|
|
|
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
|
2018-02-05 10:43:25 +00:00
|
|
|
const hcl_bch_t* cm, * flt;
|
|
|
|
hcl_oow_t len;
|
2018-04-26 04:39:20 +00:00
|
|
|
hcl_bitmask_t trait, dbgopt = 0;
|
2018-02-05 10:43:25 +00:00
|
|
|
|
|
|
|
cm = str - 1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
flt = cm + 1;
|
|
|
|
|
2018-04-07 15:54:16 +00:00
|
|
|
cm = hcl_find_bchar_in_bcstr(flt, ',');
|
|
|
|
len = cm? (cm - flt): hcl_count_bcstr(flt);
|
2024-03-07 15:23:52 +00:00
|
|
|
if (len == 0) continue;
|
|
|
|
else if (hcl_comp_bchars_bcstr(flt, len, "gc") == 0) dbgopt |= HCL_TRAIT_DEBUG_GC;
|
|
|
|
else if (hcl_comp_bchars_bcstr(flt, len, "bigint") == 0) dbgopt |= HCL_TRAIT_DEBUG_BIGINT;
|
2018-02-05 10:43:25 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf (stderr, "ERROR: unknown debug option value - %.*s\n", (int)len, flt);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (cm);
|
|
|
|
|
|
|
|
hcl_getoption (hcl, HCL_TRAIT, &trait);
|
|
|
|
trait |= dbgopt;
|
|
|
|
hcl_setoption (hcl, HCL_TRAIT, &trait);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
2016-10-06 17:49:47 +00:00
|
|
|
|
|
|
|
/* ========================================================================= */
|
|
|
|
|
2023-12-09 05:01:03 +00:00
|
|
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__) || defined(macintosh)
|
2018-03-10 17:53:44 +00:00
|
|
|
typedef void(*signal_handler_t)(int);
|
|
|
|
#elif defined(macintosh)
|
2018-03-31 07:10:43 +00:00
|
|
|
typedef void(*signal_handler_t)(int); /* TODO: */
|
2018-10-14 10:28:28 +00:00
|
|
|
#elif defined(SA_SIGINFO)
|
2018-03-10 17:53:44 +00:00
|
|
|
typedef void(*signal_handler_t)(int, siginfo_t*, void*);
|
2018-10-14 10:28:28 +00:00
|
|
|
#else
|
|
|
|
typedef void(*signal_handler_t)(int);
|
2018-03-10 17:53:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2023-12-09 05:01:03 +00:00
|
|
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
2018-03-31 07:10:43 +00:00
|
|
|
static void handle_sigint (int sig)
|
|
|
|
{
|
|
|
|
if (g_hcl) hcl_abort (g_hcl);
|
|
|
|
}
|
2018-03-10 17:53:44 +00:00
|
|
|
#elif defined(macintosh)
|
2018-03-31 07:10:43 +00:00
|
|
|
/* TODO */
|
2018-10-14 10:28:28 +00:00
|
|
|
#elif defined(SA_SIGINFO)
|
2018-03-10 17:53:44 +00:00
|
|
|
static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx)
|
|
|
|
{
|
|
|
|
if (g_hcl) hcl_abort (g_hcl);
|
|
|
|
}
|
2018-10-14 10:28:28 +00:00
|
|
|
#else
|
|
|
|
static void handle_sigint (int sig)
|
|
|
|
{
|
|
|
|
if (g_hcl) hcl_abort (g_hcl);
|
|
|
|
}
|
2018-03-10 17:53:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static void set_signal (int sig, signal_handler_t handler)
|
|
|
|
{
|
2023-12-09 05:01:03 +00:00
|
|
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
2018-03-31 07:10:43 +00:00
|
|
|
signal (sig, handler);
|
2018-03-10 17:53:44 +00:00
|
|
|
#elif defined(macintosh)
|
|
|
|
/* TODO: implement this */
|
|
|
|
#else
|
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
memset (&sa, 0, sizeof(sa));
|
|
|
|
/*sa.sa_handler = handler;*/
|
2018-10-14 10:28:28 +00:00
|
|
|
#if defined(SA_SIGINFO)
|
2018-03-10 17:53:44 +00:00
|
|
|
sa.sa_flags = SA_SIGINFO;
|
|
|
|
sa.sa_sigaction = handler;
|
2018-10-14 10:28:28 +00:00
|
|
|
#else
|
|
|
|
sa.sa_handler = handler;
|
|
|
|
#endif
|
2018-03-10 17:53:44 +00:00
|
|
|
sigemptyset (&sa.sa_mask);
|
|
|
|
|
|
|
|
sigaction (sig, &sa, NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void set_signal_to_default (int sig)
|
|
|
|
{
|
2023-12-09 05:01:03 +00:00
|
|
|
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
2018-03-31 07:10:43 +00:00
|
|
|
signal (sig, SIG_DFL);
|
2018-03-10 17:53:44 +00:00
|
|
|
#elif defined(macintosh)
|
|
|
|
/* TODO: implement this */
|
|
|
|
#else
|
2021-03-28 03:44:27 +00:00
|
|
|
struct sigaction sa;
|
2018-03-10 17:53:44 +00:00
|
|
|
|
|
|
|
memset (&sa, 0, sizeof(sa));
|
|
|
|
sa.sa_handler = SIG_DFL;
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sigemptyset (&sa.sa_mask);
|
|
|
|
|
|
|
|
sigaction (sig, &sa, NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2023-10-07 15:51:07 +00:00
|
|
|
static void print_info (void)
|
|
|
|
{
|
2023-12-07 14:01:17 +00:00
|
|
|
#if defined(HCL_CONFIGURE_CMD) && defined(HCL_CONFIGURE_ARGS)
|
2023-10-07 15:51:07 +00:00
|
|
|
printf ("Configured with: %s %s\n", HCL_CONFIGURE_CMD, HCL_CONFIGURE_ARGS);
|
2023-12-07 14:01:17 +00:00
|
|
|
#elif defined(_WIN32)
|
|
|
|
printf("Built for windows\n");
|
|
|
|
#else
|
|
|
|
/* TODO: improve this part */
|
|
|
|
#endif
|
2023-10-07 15:51:07 +00:00
|
|
|
}
|
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
static void print_synerr (hcl_t* hcl)
|
|
|
|
{
|
|
|
|
hcl_synerr_t synerr;
|
|
|
|
xtn_t* xtn;
|
|
|
|
|
2024-02-03 04:36:05 +00:00
|
|
|
xtn = (xtn_t*)hcl_getxtn(hcl);
|
2016-09-28 14:40:37 +00:00
|
|
|
hcl_getsynerr (hcl, &synerr);
|
|
|
|
|
2018-02-05 10:43:25 +00:00
|
|
|
hcl_logbfmt (hcl,HCL_LOG_STDERR, "ERROR: ");
|
2016-09-28 14:40:37 +00:00
|
|
|
if (synerr.loc.file)
|
2018-02-05 10:43:25 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "%js", synerr.loc.file);
|
2016-09-28 14:40:37 +00:00
|
|
|
else
|
2023-12-07 14:01:17 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "%hs", xtn->cci_path);
|
2016-09-28 14:40:37 +00:00
|
|
|
|
2021-03-28 03:44:27 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "[%zu,%zu] %js",
|
2018-02-07 13:55:22 +00:00
|
|
|
synerr.loc.line, synerr.loc.colm,
|
|
|
|
(hcl_geterrmsg(hcl) != hcl_geterrstr(hcl)? hcl_geterrmsg(hcl): hcl_geterrstr(hcl))
|
|
|
|
);
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
if (synerr.tgt.len > 0)
|
2021-01-22 14:43:47 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, " - %.*js", synerr.tgt.len, synerr.tgt.val);
|
2018-02-05 10:43:25 +00:00
|
|
|
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "\n");
|
2016-09-28 14:40:37 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 16:26:02 +00:00
|
|
|
static void print_other_error (hcl_t* hcl)
|
|
|
|
{
|
|
|
|
xtn_t* xtn;
|
|
|
|
hcl_loc_t loc;
|
|
|
|
|
|
|
|
xtn = (xtn_t*)hcl_getxtn(hcl);
|
|
|
|
hcl_geterrloc(hcl, &loc);
|
|
|
|
|
|
|
|
hcl_logbfmt (hcl,HCL_LOG_STDERR, "ERROR: ");
|
|
|
|
if (loc.file)
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "%js", loc.file);
|
|
|
|
else
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "%hs", xtn->cci_path);
|
|
|
|
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "[%zu,%zu] %js", loc.line, loc.colm, hcl_geterrmsg(hcl));
|
|
|
|
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "\n");
|
|
|
|
}
|
2024-02-20 13:57:30 +00:00
|
|
|
|
|
|
|
static void print_error (hcl_t* hcl, const hcl_bch_t* msghdr)
|
|
|
|
{
|
|
|
|
if (HCL_ERRNUM(hcl) == HCL_ESYNERR) print_synerr (hcl);
|
2024-04-04 16:26:02 +00:00
|
|
|
else print_other_error (hcl);
|
|
|
|
/*else hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: %hs - [%d] %js\n", msghdr, hcl_geterrnum(hcl), hcl_geterrmsg(hcl));*/
|
2024-02-20 13:57:30 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 02:40:40 +00:00
|
|
|
static void show_prompt (hcl_t* hcl, int level)
|
|
|
|
{
|
|
|
|
/* TODO: different prompt per level */
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDOUT, "HCL> ");
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDOUT, HCL_NULL); /* flushing */
|
|
|
|
}
|
2022-07-18 10:28:36 +00:00
|
|
|
|
2022-07-29 11:39:13 +00:00
|
|
|
static hcl_oop_t execute_in_interactive_mode (hcl_t* hcl)
|
|
|
|
{
|
|
|
|
hcl_oop_t retv;
|
|
|
|
|
2023-12-27 00:09:40 +00:00
|
|
|
hcl_decode (hcl, hcl_getcode(hcl), 0, hcl_getbclen(hcl));
|
2022-07-29 11:39:13 +00:00
|
|
|
HCL_LOG0 (hcl, HCL_LOG_MNEMONIC, "------------------------------------------\n");
|
|
|
|
g_hcl = hcl;
|
|
|
|
/*setup_tick ();*/
|
|
|
|
|
|
|
|
retv = hcl_execute(hcl);
|
|
|
|
|
|
|
|
/* flush pending output data in the interactive mode(e.g. printf without a newline) */
|
2023-11-05 07:58:45 +00:00
|
|
|
hcl_flushudio (hcl);
|
2022-07-29 11:39:13 +00:00
|
|
|
|
|
|
|
if (!retv)
|
|
|
|
{
|
2024-04-04 16:26:02 +00:00
|
|
|
print_error (hcl, "cannot execute");
|
2022-07-29 11:39:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* print the result in the interactive mode regardless 'verbose' */
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDOUT, "%O\n", retv); /* TODO: show this go to the output handler?? */
|
|
|
|
/*
|
|
|
|
* print the value of ERRSTR.
|
|
|
|
hcl_oop_cons_t cons = hcl_getatsysdic(hcl, xtn->sym_errstr);
|
|
|
|
if (cons)
|
|
|
|
{
|
|
|
|
HCL_ASSERT (hcl, HCL_IS_CONS(hcl, cons));
|
|
|
|
HCL_ASSERT (hcl, HCL_CONS_CAR(cons) == xtn->sym_errstr);
|
|
|
|
hcl_print (hcl, HCL_CONS_CDR(cons));
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
/*cancel_tick();*/
|
|
|
|
g_hcl = HCL_NULL;
|
|
|
|
|
|
|
|
return retv;
|
|
|
|
}
|
|
|
|
|
2023-12-23 03:43:26 +00:00
|
|
|
static hcl_oop_t execute_in_batch_mode(hcl_t* hcl, int verbose)
|
2022-07-29 11:39:13 +00:00
|
|
|
{
|
|
|
|
hcl_oop_t retv;
|
|
|
|
|
2023-12-27 00:09:40 +00:00
|
|
|
hcl_decode(hcl, hcl_getcode(hcl), 0, hcl_getbclen(hcl));
|
2023-12-23 03:43:26 +00:00
|
|
|
HCL_LOG3(hcl, HCL_LOG_MNEMONIC, "BYTECODES bclen=%zu lflen=%zu ngtmprs=%zu\n", hcl_getbclen(hcl), hcl_getlflen(hcl), hcl_getngtmprs(hcl));
|
2022-07-29 11:39:13 +00:00
|
|
|
g_hcl = hcl;
|
|
|
|
/*setup_tick ();*/
|
|
|
|
|
2023-12-27 00:09:40 +00:00
|
|
|
|
|
|
|
/* TESTING */
|
|
|
|
#if 0
|
|
|
|
{
|
2023-12-27 15:27:27 +00:00
|
|
|
hcl_code_t xcode;
|
2024-01-01 16:41:41 +00:00
|
|
|
hcl_ptlc_t mem;
|
2023-12-27 15:27:27 +00:00
|
|
|
|
|
|
|
memset (&xcode, 0, HCL_SIZEOF(xcode));
|
2024-01-01 16:41:41 +00:00
|
|
|
memset (&mem, 0, HCL_SIZEOF(mem));
|
2023-12-27 15:27:27 +00:00
|
|
|
|
2024-01-01 16:41:41 +00:00
|
|
|
hcl_marshalcodetomem(hcl, &hcl->code, &mem);
|
|
|
|
hcl_unmarshalcodefrommem(hcl, &xcode, (const hcl_ptl_t*)&mem);
|
|
|
|
hcl_freemem (hcl, mem.ptr);
|
2023-12-27 15:27:27 +00:00
|
|
|
|
|
|
|
hcl_decode(hcl, &xcode, 0, xcode.bc.len);
|
|
|
|
hcl_purgecode (hcl, &xcode);
|
2023-12-27 00:09:40 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* END TESTING */
|
|
|
|
|
2022-07-29 11:39:13 +00:00
|
|
|
retv = hcl_execute(hcl);
|
2023-11-05 07:58:45 +00:00
|
|
|
hcl_flushudio (hcl);
|
2022-07-29 11:39:13 +00:00
|
|
|
|
|
|
|
if (!retv)
|
|
|
|
{
|
2024-04-04 16:26:02 +00:00
|
|
|
print_error (hcl, "cannot execute");
|
2022-07-29 11:39:13 +00:00
|
|
|
}
|
|
|
|
else if (verbose)
|
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "EXECUTION OK - EXITED WITH %O\n", retv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*cancel_tick();*/
|
|
|
|
g_hcl = HCL_NULL;
|
|
|
|
/*hcl_dumpsymtab (hcl);*/
|
|
|
|
|
|
|
|
return retv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int on_fed_cnode_in_interactive_mode (hcl_t* hcl, hcl_cnode_t* obj)
|
|
|
|
{
|
2023-11-09 15:03:03 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
2024-02-21 16:21:11 +00:00
|
|
|
int flags = 0;
|
2024-02-20 13:57:30 +00:00
|
|
|
|
|
|
|
/* in the interactive, the compile error must not break the input loop.
|
2024-02-21 16:21:11 +00:00
|
|
|
* this function returns 0 to go on despite a compile-time error.
|
|
|
|
*
|
|
|
|
* if a single line or continued lines contain multiple expressions,
|
|
|
|
* execution is delayed until the last expression is compiled. */
|
|
|
|
|
2024-04-17 03:20:25 +00:00
|
|
|
if (xtn->feed.ncompexprs <= 0)
|
2024-02-21 16:21:11 +00:00
|
|
|
{
|
2024-02-25 04:55:03 +00:00
|
|
|
/* the first expression in the current user input line.
|
|
|
|
* arrange to clear byte-codes before compiling the expression. */
|
2024-02-21 16:21:11 +00:00
|
|
|
flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK;
|
|
|
|
}
|
2024-02-20 13:57:30 +00:00
|
|
|
|
|
|
|
if (hcl_compile(hcl, obj, flags) <= -1)
|
2024-02-21 16:21:11 +00:00
|
|
|
{
|
2024-05-16 10:40:43 +00:00
|
|
|
/*print_error(hcl, "failed to compile"); */
|
2024-02-21 16:21:11 +00:00
|
|
|
xtn->feed.pos = xtn->feed.len; /* arrange to discard the rest of the line */
|
2024-05-16 10:40:43 +00:00
|
|
|
return -1; /* this causes the feed function to fail and
|
|
|
|
the error hander for to print the error message */
|
2024-02-21 16:21:11 +00:00
|
|
|
}
|
2024-01-21 02:40:40 +00:00
|
|
|
|
2024-05-16 10:40:43 +00:00
|
|
|
xtn->feed.ncompexprs++;
|
2022-07-29 11:39:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-11-09 15:03:03 +00:00
|
|
|
static int on_fed_cnode_in_batch_mode (hcl_t* hcl, hcl_cnode_t* obj)
|
|
|
|
{
|
2024-02-21 16:21:11 +00:00
|
|
|
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
|
2024-01-18 10:16:05 +00:00
|
|
|
return hcl_compile(hcl, obj, 0);
|
2023-11-09 15:03:03 +00:00
|
|
|
}
|
|
|
|
|
2024-02-21 16:21:11 +00:00
|
|
|
static int get_line (hcl_t* hcl, xtn_t* xtn, FILE* fp)
|
|
|
|
{
|
|
|
|
if (xtn->feed.eof) return 0;
|
|
|
|
|
|
|
|
xtn->feed.pos = 0;
|
|
|
|
xtn->feed.len = 0;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
int ch = fgetc(fp);
|
|
|
|
if (ch == EOF)
|
|
|
|
{
|
|
|
|
if (ferror(fp))
|
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: failed to read - %hs - %hs\n", xtn->cci_path, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->feed.eof = 1;
|
2024-04-17 03:20:25 +00:00
|
|
|
if (xtn->feed.len <= 0) return 0;
|
|
|
|
|
2024-02-21 16:21:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->feed.buf[xtn->feed.len++] = (hcl_bch_t)(unsigned int)ch;
|
2024-04-17 03:20:25 +00:00
|
|
|
if (ch == '\n' || xtn->feed.len >= HCL_COUNTOF(xtn->feed.buf)) break;
|
2024-02-21 16:21:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-11-05 07:58:45 +00:00
|
|
|
static int feed_loop (hcl_t* hcl, xtn_t* xtn, int verbose)
|
2022-07-18 10:28:36 +00:00
|
|
|
{
|
2023-11-05 07:58:45 +00:00
|
|
|
FILE* fp = HCL_NULL;
|
|
|
|
int is_tty;
|
|
|
|
|
2023-12-07 14:01:17 +00:00
|
|
|
#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
|
2024-02-02 05:57:46 +00:00
|
|
|
errno_t err = fopen_s(&fp, xtn->cci_path, FOPEN_R_FLAGS);
|
2023-12-07 14:01:17 +00:00
|
|
|
if (err != 0)
|
|
|
|
{
|
|
|
|
hcl_logbfmt(hcl, HCL_LOG_STDERR, "ERROR: failed to open - %hs - %hs\n", xtn->cci_path, strerror(err));
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
#else
|
2023-11-05 13:31:33 +00:00
|
|
|
fp = fopen(xtn->cci_path, FOPEN_R_FLAGS);
|
2023-11-05 07:58:45 +00:00
|
|
|
if (!fp)
|
|
|
|
{
|
2023-11-05 13:31:33 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: failed to open - %hs - %hs\n", xtn->cci_path, strerror(errno));
|
2023-11-05 07:58:45 +00:00
|
|
|
goto oops;
|
|
|
|
}
|
2023-12-07 14:01:17 +00:00
|
|
|
#endif
|
2023-11-05 07:58:45 +00:00
|
|
|
|
2023-12-07 14:01:17 +00:00
|
|
|
#if defined(_WIN32)
|
|
|
|
is_tty = _isatty(_fileno(fp));
|
|
|
|
#else
|
2023-11-05 07:58:45 +00:00
|
|
|
is_tty = isatty(fileno(fp));
|
2023-12-07 14:01:17 +00:00
|
|
|
#endif
|
2023-11-05 07:58:45 +00:00
|
|
|
|
2023-05-18 01:24:01 +00:00
|
|
|
/* override the default cnode handler. the default one simply
|
|
|
|
* compiles the expression node without execution */
|
2023-11-09 15:03:03 +00:00
|
|
|
/*if (hcl_beginfeed(hcl, is_tty? on_fed_cnode_in_interactive_mode: HCL_NULL) <= -1)*/
|
|
|
|
if (hcl_beginfeed(hcl, is_tty? on_fed_cnode_in_interactive_mode: on_fed_cnode_in_batch_mode) <= -1)
|
2022-07-29 11:39:13 +00:00
|
|
|
{
|
2023-05-18 01:24:01 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot begin feed - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
|
|
|
goto oops;
|
2022-07-29 11:39:13 +00:00
|
|
|
}
|
2022-07-22 08:02:14 +00:00
|
|
|
|
2024-02-21 16:21:11 +00:00
|
|
|
if (is_tty)
|
2022-07-18 10:28:36 +00:00
|
|
|
{
|
2024-02-21 16:21:11 +00:00
|
|
|
show_prompt (hcl, 0);
|
|
|
|
|
|
|
|
while (1)
|
2023-11-05 07:58:45 +00:00
|
|
|
{
|
2024-02-21 16:21:11 +00:00
|
|
|
int n;
|
2024-04-15 04:14:49 +00:00
|
|
|
hcl_oow_t pos;
|
2024-04-16 17:00:28 +00:00
|
|
|
hcl_oow_t len;
|
2024-02-21 16:21:11 +00:00
|
|
|
|
2024-04-17 03:20:25 +00:00
|
|
|
/* read a line regardless of the actual expression */
|
2024-02-21 16:21:11 +00:00
|
|
|
n = get_line(hcl, xtn, fp);
|
|
|
|
if (n <= -1) goto oops;
|
|
|
|
if (n == 0) break;
|
|
|
|
|
|
|
|
/* feed the line */
|
2024-04-15 04:14:49 +00:00
|
|
|
pos = xtn->feed.pos;
|
|
|
|
/* do this before calling hcl_feedbchars() so that the callback sees the updated value */
|
|
|
|
xtn->feed.pos = xtn->feed.len;
|
2024-04-16 17:00:28 +00:00
|
|
|
len = xtn->feed.len - pos;
|
|
|
|
if (hcl_feedbchars(hcl, &xtn->feed.buf[pos], len) <= -1)
|
2024-04-15 04:14:49 +00:00
|
|
|
{
|
|
|
|
print_error (hcl, "failed to feed");
|
2024-04-17 03:20:25 +00:00
|
|
|
if (len > 0) show_prompt (hcl, 0);
|
2024-05-16 10:40:43 +00:00
|
|
|
|
|
|
|
/* clear the compiled code but not executed yet */
|
|
|
|
hcl_clearcode(hcl);
|
|
|
|
hcl_clearfnblks(hcl);
|
|
|
|
xtn->feed.ncompexprs = 0;
|
2024-04-15 04:14:49 +00:00
|
|
|
}
|
2024-04-16 17:00:28 +00:00
|
|
|
else
|
|
|
|
{
|
2024-04-17 03:20:25 +00:00
|
|
|
/* TODO: check if this works when HCL_TRAIT_LANG_ENABLE_EOL is not set */
|
|
|
|
if (!hcl_feedpending(hcl))
|
2024-04-16 17:00:28 +00:00
|
|
|
{
|
2024-04-17 03:20:25 +00:00
|
|
|
if (xtn->feed.ncompexprs > 0 && hcl_getbclen(hcl) > 0)
|
|
|
|
{
|
|
|
|
execute_in_interactive_mode (hcl);
|
|
|
|
xtn->feed.ncompexprs = 0;
|
|
|
|
}
|
|
|
|
show_prompt (hcl, 0);
|
2024-04-16 17:00:28 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-05 07:58:45 +00:00
|
|
|
}
|
2024-05-15 13:59:34 +00:00
|
|
|
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDOUT, "\n");
|
2024-02-21 16:21:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (1)
|
2023-11-07 15:11:43 +00:00
|
|
|
{
|
2023-11-09 15:03:03 +00:00
|
|
|
hcl_bch_t buf[1024];
|
|
|
|
hcl_oow_t xlen;
|
|
|
|
|
|
|
|
xlen = fread(buf, HCL_SIZEOF(buf[0]), HCL_COUNTOF(buf), fp);
|
|
|
|
if (xlen > 0 && hcl_feedbchars(hcl, buf, xlen) <= -1) goto feed_error;
|
|
|
|
if (xlen < HCL_COUNTOF(buf))
|
2023-11-07 15:11:43 +00:00
|
|
|
{
|
2023-11-09 15:03:03 +00:00
|
|
|
if (ferror(fp))
|
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: failed to read - %hs - %hs\n", xtn->cci_path, strerror(errno));
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
break;
|
2023-11-07 15:11:43 +00:00
|
|
|
}
|
|
|
|
}
|
2022-07-18 10:28:36 +00:00
|
|
|
}
|
2023-11-05 07:58:45 +00:00
|
|
|
|
2022-07-29 14:41:00 +00:00
|
|
|
if (hcl_endfeed(hcl) <= -1)
|
2022-07-23 06:57:01 +00:00
|
|
|
{
|
|
|
|
feed_error:
|
2024-02-20 13:57:30 +00:00
|
|
|
print_error (hcl, "failed to feed");
|
2022-07-23 06:57:01 +00:00
|
|
|
goto oops; /* TODO: proceed or just exit? */
|
|
|
|
}
|
2023-11-05 07:58:45 +00:00
|
|
|
fclose (fp);
|
2022-07-23 06:57:01 +00:00
|
|
|
|
2023-11-05 07:58:45 +00:00
|
|
|
if (!is_tty && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose);
|
2022-07-18 10:28:36 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
oops:
|
2023-11-05 07:58:45 +00:00
|
|
|
if (fp) fclose (fp);
|
2022-07-18 10:28:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-01-21 02:40:40 +00:00
|
|
|
/* #define DEFAULT_HEAPSIZE (512000ul) */
|
2024-01-14 00:48:57 +00:00
|
|
|
#define DEFAULT_HEAPSIZE (0ul) /* don't use the pre-allocated heap */
|
2021-03-28 03:44:27 +00:00
|
|
|
|
2018-03-13 10:20:33 +00:00
|
|
|
int main (int argc, char* argv[])
|
2016-09-28 14:40:37 +00:00
|
|
|
{
|
2018-04-25 04:12:13 +00:00
|
|
|
hcl_t* hcl = HCL_NULL;
|
2016-09-28 14:40:37 +00:00
|
|
|
xtn_t* xtn;
|
2018-02-05 10:43:25 +00:00
|
|
|
hcl_cb_t hclcb;
|
|
|
|
|
|
|
|
hcl_bci_t c;
|
|
|
|
static hcl_bopt_lng_t lopt[] =
|
|
|
|
{
|
2018-02-21 09:30:18 +00:00
|
|
|
#if defined(HCL_BUILD_DEBUG)
|
2021-01-01 07:34:21 +00:00
|
|
|
{ ":debug", '\0' },
|
2018-02-05 10:43:25 +00:00
|
|
|
#endif
|
2021-01-01 07:34:21 +00:00
|
|
|
{ ":heapsize", '\0' },
|
2024-01-05 06:01:59 +00:00
|
|
|
{ ":log", 'l' },
|
2024-01-21 02:40:40 +00:00
|
|
|
{ "info", '\0' },
|
2024-01-05 06:01:59 +00:00
|
|
|
{ ":modlibdirs", '\0' },
|
2021-01-01 07:34:21 +00:00
|
|
|
|
2018-02-05 10:43:25 +00:00
|
|
|
{ HCL_NULL, '\0' }
|
|
|
|
};
|
|
|
|
static hcl_bopt_t opt =
|
|
|
|
{
|
2024-01-18 10:16:05 +00:00
|
|
|
"l:bnv",
|
2018-02-05 10:43:25 +00:00
|
|
|
lopt
|
|
|
|
};
|
|
|
|
|
|
|
|
const char* logopt = HCL_NULL;
|
2021-01-01 07:34:21 +00:00
|
|
|
hcl_oow_t heapsize = DEFAULT_HEAPSIZE;
|
2019-04-16 09:35:56 +00:00
|
|
|
int verbose = 0;
|
2023-10-07 15:51:07 +00:00
|
|
|
int show_info = 0;
|
2024-01-18 10:16:05 +00:00
|
|
|
int enable_block = 0;
|
|
|
|
int nl_terminator = 0;
|
2024-01-05 06:01:59 +00:00
|
|
|
const char* modlibdirs = HCL_NULL;
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2018-02-21 09:30:18 +00:00
|
|
|
#if defined(HCL_BUILD_DEBUG)
|
2018-02-05 10:43:25 +00:00
|
|
|
const char* dbgopt = HCL_NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
setlocale (LC_ALL, "");
|
2016-09-28 14:40:37 +00:00
|
|
|
|
|
|
|
#if !defined(macintosh)
|
|
|
|
if (argc < 2)
|
|
|
|
{
|
2018-02-05 10:43:25 +00:00
|
|
|
print_usage:
|
2024-02-15 23:39:33 +00:00
|
|
|
fprintf (stderr, "Usage: %s [options] script-filename [output-filename]\n", argv[0]);
|
|
|
|
fprintf (stderr, "Options are:\n");
|
|
|
|
fprintf (stderr, " -b enable block construct with {}\n");
|
|
|
|
fprintf (stderr, " -n enable line-break as expression terminator\n");
|
2016-09-28 14:40:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2018-02-05 10:43:25 +00:00
|
|
|
|
2024-01-18 10:16:05 +00:00
|
|
|
while ((c = hcl_getbopt(argc, argv, &opt)) != HCL_BCI_EOF)
|
2018-02-05 10:43:25 +00:00
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 'l':
|
|
|
|
logopt = opt.arg;
|
|
|
|
break;
|
|
|
|
|
2024-01-18 10:16:05 +00:00
|
|
|
case 'b':
|
|
|
|
enable_block = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
nl_terminator = 1;
|
2023-11-09 15:03:03 +00:00
|
|
|
break;
|
2022-07-18 10:28:36 +00:00
|
|
|
|
2019-04-16 09:35:56 +00:00
|
|
|
case 'v':
|
|
|
|
verbose = 1;
|
|
|
|
break;
|
|
|
|
|
2018-02-05 10:43:25 +00:00
|
|
|
case '\0':
|
2021-01-01 07:34:21 +00:00
|
|
|
if (hcl_comp_bcstr(opt.lngopt, "heapsize") == 0)
|
|
|
|
{
|
|
|
|
heapsize = strtoul(opt.arg, HCL_NULL, 0);
|
|
|
|
break;
|
|
|
|
}
|
2018-02-21 09:30:18 +00:00
|
|
|
#if defined(HCL_BUILD_DEBUG)
|
2018-04-07 15:54:16 +00:00
|
|
|
else if (hcl_comp_bcstr(opt.lngopt, "debug") == 0)
|
2018-02-05 10:43:25 +00:00
|
|
|
{
|
|
|
|
dbgopt = opt.arg;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
2023-10-07 15:51:07 +00:00
|
|
|
else if (hcl_comp_bcstr(opt.lngopt, "info") == 0)
|
|
|
|
{
|
|
|
|
show_info = 1;
|
|
|
|
break;
|
|
|
|
}
|
2024-01-05 06:01:59 +00:00
|
|
|
else if (hcl_comp_bcstr(opt.lngopt, "modlibdirs") == 0)
|
|
|
|
{
|
|
|
|
modlibdirs = opt.arg;
|
|
|
|
break;
|
|
|
|
}
|
2018-02-05 10:43:25 +00:00
|
|
|
|
|
|
|
goto print_usage;
|
|
|
|
|
|
|
|
case ':':
|
|
|
|
if (opt.lngopt)
|
|
|
|
fprintf (stderr, "bad argument for '%s'\n", opt.lngopt);
|
|
|
|
else
|
|
|
|
fprintf (stderr, "bad argument for '%c'\n", opt.opt);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
default:
|
|
|
|
goto print_usage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-15 23:39:33 +00:00
|
|
|
if ((opt.ind + 1) != argc && (opt.ind + 2) != argc && !show_info) goto print_usage;
|
2016-09-28 14:40:37 +00:00
|
|
|
#endif
|
|
|
|
|
2021-02-09 17:47:22 +00:00
|
|
|
hcl = hcl_openstd(HCL_SIZEOF(xtn_t), HCL_NULL);
|
2021-02-07 17:57:35 +00:00
|
|
|
if (HCL_UNLIKELY(!hcl))
|
2016-09-28 14:40:37 +00:00
|
|
|
{
|
2018-04-25 04:12:13 +00:00
|
|
|
printf ("ERROR: cannot open hcl\n");
|
|
|
|
goto oops;
|
2016-09-28 14:40:37 +00:00
|
|
|
}
|
|
|
|
|
2024-01-18 10:16:05 +00:00
|
|
|
xtn = (xtn_t*)hcl_getxtn(hcl);
|
2021-02-07 17:57:35 +00:00
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
{
|
|
|
|
hcl_oow_t tab_size;
|
|
|
|
tab_size = 5000;
|
|
|
|
hcl_setoption (hcl, HCL_SYMTAB_SIZE, &tab_size);
|
|
|
|
tab_size = 5000;
|
|
|
|
hcl_setoption (hcl, HCL_SYSDIC_SIZE, &tab_size);
|
2023-11-29 08:12:21 +00:00
|
|
|
tab_size = 600; /* TODO: choose a better stack size or make this user specifiable */
|
2016-09-28 14:40:37 +00:00
|
|
|
hcl_setoption (hcl, HCL_PROCSTK_SIZE, &tab_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2018-04-26 04:39:20 +00:00
|
|
|
hcl_bitmask_t trait = 0;
|
2016-09-28 14:40:37 +00:00
|
|
|
|
2020-09-28 15:44:04 +00:00
|
|
|
/*trait |= HCL_TRAIT_NOGC;*/
|
|
|
|
trait |= HCL_TRAIT_AWAIT_PROCS;
|
2024-05-14 11:52:25 +00:00
|
|
|
#if 0
|
2024-01-21 02:40:40 +00:00
|
|
|
if (enable_block) trait |= HCL_TRAIT_LANG_ENABLE_BLOCK;
|
2024-04-14 17:23:55 +00:00
|
|
|
if (nl_terminator) trait |= HCL_TRAIT_LANG_ENABLE_EOL;
|
2024-05-14 11:52:25 +00:00
|
|
|
#else
|
|
|
|
trait |= HCL_TRAIT_LANG_ENABLE_BLOCK;
|
|
|
|
trait |= HCL_TRAIT_LANG_ENABLE_EOL;
|
|
|
|
#endif
|
2016-09-28 14:40:37 +00:00
|
|
|
hcl_setoption (hcl, HCL_TRAIT, &trait);
|
|
|
|
}
|
|
|
|
|
2024-01-05 06:01:59 +00:00
|
|
|
if (modlibdirs)
|
|
|
|
{
|
|
|
|
#if defined(HCL_OOCH_IS_UCH)
|
|
|
|
hcl_ooch_t* tmp;
|
|
|
|
tmp = hcl_dupbtoucstr(hcl, modlibdirs, HCL_NULL);
|
|
|
|
if (HCL_UNLIKELY(!tmp))
|
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR,"ERROR: cannot duplicate modlibdirs - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hcl_setoption(hcl, HCL_MOD_LIBDIRS, tmp) <= -1)
|
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR,"ERROR: cannot set modlibdirs - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
|
|
|
hcl_freemem (hcl, tmp);
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
hcl_freemem (hcl, tmp);
|
|
|
|
#else
|
|
|
|
if (hcl_setoption(hcl, HCL_MOD_LIBDIRS, modlibdirs) <= -1)
|
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR,"ERROR: cannot set modlibdirs - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-02-05 10:43:25 +00:00
|
|
|
memset (&hclcb, 0, HCL_SIZEOF(hclcb));
|
2018-03-08 14:18:30 +00:00
|
|
|
hclcb.gc = gc_hcl;
|
2022-07-29 11:29:47 +00:00
|
|
|
hclcb.vm_startup = vm_startup;
|
2018-03-10 17:53:44 +00:00
|
|
|
hclcb.vm_cleanup = vm_cleanup;
|
2018-03-11 11:16:28 +00:00
|
|
|
/*hclcb.vm_checkbc = vm_checkbc;*/
|
2018-02-05 10:43:25 +00:00
|
|
|
hcl_regcb (hcl, &hclcb);
|
|
|
|
|
|
|
|
if (logopt)
|
|
|
|
{
|
2019-04-16 15:46:00 +00:00
|
|
|
if (handle_logopt(hcl, logopt) <= -1) goto oops;
|
2018-02-05 10:43:25 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 09:30:18 +00:00
|
|
|
#if defined(HCL_BUILD_DEBUG)
|
2018-02-05 10:43:25 +00:00
|
|
|
if (dbgopt)
|
|
|
|
{
|
2021-11-21 16:02:39 +00:00
|
|
|
if (handle_dbgopt(hcl, dbgopt) <= -1) goto oops;
|
2018-02-05 10:43:25 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-10-07 15:51:07 +00:00
|
|
|
if (show_info)
|
|
|
|
{
|
|
|
|
print_info ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-09 17:47:22 +00:00
|
|
|
if (hcl_ignite(hcl, heapsize) <= -1)
|
2016-09-28 14:40:37 +00:00
|
|
|
{
|
2018-02-05 15:59:32 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "cannot ignite hcl - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
2018-04-25 04:12:13 +00:00
|
|
|
goto oops;
|
2016-09-28 14:40:37 +00:00
|
|
|
}
|
|
|
|
|
2016-10-06 17:49:47 +00:00
|
|
|
if (hcl_addbuiltinprims(hcl) <= -1)
|
|
|
|
{
|
2018-02-05 15:59:32 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "cannot add builtin primitives - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
2018-04-25 04:12:13 +00:00
|
|
|
goto oops;
|
2016-10-06 17:49:47 +00:00
|
|
|
}
|
|
|
|
|
2023-11-05 13:31:33 +00:00
|
|
|
xtn->cci_path = argv[opt.ind++]; /* input source code file */
|
2023-11-05 07:58:45 +00:00
|
|
|
if (opt.ind < argc) xtn->udo_path = argv[opt.ind++];
|
|
|
|
|
2023-11-05 13:31:33 +00:00
|
|
|
if (hcl_attachcciostdwithbcstr(hcl, xtn->cci_path) <= -1)
|
2023-11-05 07:58:45 +00:00
|
|
|
{
|
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot attach source input stream - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hcl_attachudiostdwithbcstr(hcl, "", xtn->udo_path) <= -1) /* TODO: add udi path */
|
2016-09-28 14:40:37 +00:00
|
|
|
{
|
2023-11-05 07:58:45 +00:00
|
|
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot attach user data streams - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
2018-04-25 04:12:13 +00:00
|
|
|
goto oops;
|
2016-09-28 14:40:37 +00:00
|
|
|
}
|
|
|
|
|
2021-03-28 03:44:27 +00:00
|
|
|
/* -- from this point onward, any failure leads to jumping to the oops label
|
2018-03-10 17:53:44 +00:00
|
|
|
* -- instead of returning -1 immediately. --*/
|
|
|
|
set_signal (SIGINT, handle_sigint);
|
|
|
|
|
2020-10-15 12:57:05 +00:00
|
|
|
#if 0
|
2020-10-08 09:25:54 +00:00
|
|
|
// TODO: change the option name
|
|
|
|
// in the INTERACTIVE mode, the compiler generates MAKE_FUNCTION for lambda functions.
|
2021-01-26 10:10:18 +00:00
|
|
|
// in the non-INTERACTIVE mode, the compiler generates MAKE_BLOCK for lambda functions.
|
2020-10-05 09:37:26 +00:00
|
|
|
{
|
|
|
|
hcl_bitmask_t trait;
|
|
|
|
hcl_getoption (hcl, HCL_TRAIT, &trait);
|
|
|
|
trait |= HCL_TRAIT_INTERACTIVE;
|
|
|
|
hcl_setoption (hcl, HCL_TRAIT, &trait);
|
|
|
|
}
|
2020-10-07 08:06:49 +00:00
|
|
|
#endif
|
2022-07-18 10:28:36 +00:00
|
|
|
|
2023-11-05 07:58:45 +00:00
|
|
|
if (feed_loop(hcl, xtn, verbose) <= -1) goto oops;
|
2020-10-13 14:44:00 +00:00
|
|
|
|
2018-03-10 17:53:44 +00:00
|
|
|
set_signal_to_default (SIGINT);
|
2018-02-09 17:15:31 +00:00
|
|
|
hcl_close (hcl);
|
2018-04-25 04:12:13 +00:00
|
|
|
|
2016-09-28 14:40:37 +00:00
|
|
|
return 0;
|
2018-02-09 17:15:31 +00:00
|
|
|
|
|
|
|
oops:
|
2018-04-25 04:12:13 +00:00
|
|
|
set_signal_to_default (SIGINT); /* harmless to call multiple times without set_signal() */
|
|
|
|
if (hcl) hcl_close (hcl);
|
2018-02-09 17:15:31 +00:00
|
|
|
return -1;
|
2016-09-28 14:40:37 +00:00
|
|
|
}
|