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 .
*/
# include "hcl-prv.h"
2018-02-05 10:43:25 +00:00
# include "hcl-opt.h"
2018-11-03 15:57:14 +00:00
# include "cb-impl.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>
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>
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
2016-09-28 14:40:37 +00:00
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
} ;
2019-04-16 15:46:00 +00:00
enum logfd_flag_t
{
LOGFD_TTY = ( 1 < < 0 ) ,
LOGFD_OPENED_HERE = ( 1 < < 1 )
} ;
2016-09-28 14:40:37 +00:00
typedef struct xtn_t xtn_t ;
struct xtn_t
{
2018-03-31 07:10:43 +00:00
# if defined(_WIN32)
HANDLE waitable_timer ;
# endif
2016-09-28 14:40:37 +00:00
const char * read_path ; /* main source file */
const char * print_path ;
2018-02-05 10:43:25 +00:00
2018-02-08 14:40:56 +00:00
int vm_running ;
2019-04-16 15:46:00 +00:00
struct
2018-03-16 16:20:40 +00:00
{
2019-04-16 15:46:00 +00:00
int fd ;
int fd_flag ; /* bitwise OR'ed fo logfd_flag_t bits */
struct
{
hcl_bch_t buf [ 4096 ] ;
hcl_oow_t len ;
} out ;
} log ;
2018-02-08 15:04:07 +00:00
int reader_istty ;
2018-03-08 14:18:30 +00:00
hcl_oop_t sym_errstr ;
2016-09-28 14:40:37 +00:00
} ;
/* ========================================================================= */
static void * sys_alloc ( hcl_mmgr_t * mmgr , hcl_oow_t size )
{
2018-03-01 14:47:12 +00:00
return malloc ( size ) ;
2016-09-28 14:40:37 +00:00
}
static void * sys_realloc ( hcl_mmgr_t * mmgr , void * ptr , hcl_oow_t size )
{
2018-03-01 14:47:12 +00:00
return realloc ( ptr , size ) ;
2016-09-28 14:40:37 +00:00
}
static void sys_free ( hcl_mmgr_t * mmgr , void * ptr )
{
free ( ptr ) ;
}
static hcl_mmgr_t sys_mmgr =
{
sys_alloc ,
sys_realloc ,
sys_free ,
HCL_NULL
} ;
/* ========================================================================= */
2018-02-05 10:43:25 +00:00
static const hcl_bch_t * get_base_name ( const hcl_bch_t * path )
{
const hcl_bch_t * p , * last = HCL_NULL ;
for ( p = path ; * p ! = ' \0 ' ; p + + )
{
2018-11-03 15:57:14 +00:00
if ( HCL_IS_PATH_SEP ( * p ) ) last = p ;
2018-02-05 10:43:25 +00:00
}
return ( last = = HCL_NULL ) ? path : ( last + 1 ) ;
}
2018-03-09 05:12:55 +00:00
static HCL_INLINE int open_input ( hcl_t * hcl , hcl_ioinarg_t * arg )
2016-09-28 14:40:37 +00:00
{
2018-02-26 15:24:45 +00:00
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
2018-02-05 10:43:25 +00:00
bb_t * bb = HCL_NULL ;
2016-09-28 14:40:37 +00:00
2018-02-05 10:43:25 +00:00
/* TOOD: support predefined include directory as well */
2016-09-28 14:40:37 +00:00
if ( arg - > includer )
{
/* includee */
2018-02-05 10:43:25 +00:00
hcl_oow_t ucslen , bcslen , parlen ;
const hcl_bch_t * fn , * fb ;
# if defined(HCL_OOCH_IS_UCH)
if ( hcl_convootobcstr ( hcl , arg - > name , & ucslen , HCL_NULL , & bcslen ) < = - 1 ) goto oops ;
# else
2018-04-07 15:54:16 +00:00
bcslen = hcl_count_bcstr ( arg - > name ) ;
2018-02-05 10:43:25 +00:00
# endif
fn = ( ( bb_t * ) arg - > includer - > handle ) - > fn ;
fb = get_base_name ( fn ) ;
parlen = fb - fn ;
2018-02-26 15:24:45 +00:00
bb = ( bb_t * ) hcl_callocmem ( hcl , HCL_SIZEOF ( * bb ) + ( HCL_SIZEOF ( hcl_bch_t ) * ( parlen + bcslen + 1 ) ) ) ;
2018-02-05 10:43:25 +00:00
if ( ! bb ) goto oops ;
bb - > fn = ( hcl_bch_t * ) ( bb + 1 ) ;
2018-04-07 15:54:16 +00:00
hcl_copy_bchars ( bb - > fn , fn , parlen ) ;
2018-02-05 10:43:25 +00:00
# if defined(HCL_OOCH_IS_UCH)
hcl_convootobcstr ( hcl , arg - > name , & ucslen , & bb - > fn [ parlen ] , & bcslen ) ;
# else
2018-04-07 15:54:16 +00:00
hcl_copy_bcstr ( & bb - > fn [ parlen ] , bcslen + 1 , arg - > name ) ;
2018-02-05 10:43:25 +00:00
# endif
2016-09-28 14:40:37 +00:00
}
else
{
/* main stream */
2018-02-05 10:43:25 +00:00
hcl_oow_t pathlen ;
2018-04-07 15:54:16 +00:00
pathlen = hcl_count_bcstr ( xtn - > read_path ) ;
2018-02-05 10:43:25 +00:00
2018-02-26 15:24:45 +00:00
bb = ( bb_t * ) hcl_callocmem ( hcl , HCL_SIZEOF ( * bb ) + ( HCL_SIZEOF ( hcl_bch_t ) * ( pathlen + 1 ) ) ) ;
2018-02-05 10:43:25 +00:00
if ( ! bb ) goto oops ;
bb - > fn = ( hcl_bch_t * ) ( bb + 1 ) ;
2018-04-07 15:54:16 +00:00
hcl_copy_bcstr ( bb - > fn , pathlen + 1 , xtn - > read_path ) ;
2016-09-28 14:40:37 +00:00
}
2018-02-05 10:43:25 +00:00
# if defined(__DOS__) || defined(_WIN32) || defined(__OS2__)
bb - > fp = fopen ( bb - > fn , " rb " ) ;
# else
bb - > fp = fopen ( bb - > fn , " r " ) ;
# endif
if ( ! bb - > fp )
2016-09-28 14:40:37 +00:00
{
2018-02-05 10:43:25 +00:00
hcl_seterrnum ( hcl , HCL_EIOERR ) ;
goto oops ;
2016-09-28 14:40:37 +00:00
}
2018-02-08 15:04:07 +00:00
if ( ! arg - > includer )
{
2018-03-31 07:10:43 +00:00
# if defined(HAVE_ISATTY)
2018-02-08 15:04:07 +00:00
xtn - > reader_istty = isatty ( fileno ( bb - > fp ) ) ;
2018-03-31 07:10:43 +00:00
# endif
2018-02-08 15:04:07 +00:00
}
2016-09-28 14:40:37 +00:00
arg - > handle = bb ;
return 0 ;
2018-02-05 10:43:25 +00:00
oops :
if ( bb )
{
if ( bb - > fp ) fclose ( bb - > fp ) ;
hcl_freemem ( hcl , bb ) ;
}
return - 1 ;
2016-09-28 14:40:37 +00:00
}
2018-02-05 10:43:25 +00:00
2018-03-09 05:12:55 +00:00
static HCL_INLINE int close_input ( hcl_t * hcl , hcl_ioinarg_t * arg )
2016-09-28 14:40:37 +00:00
{
2018-02-26 15:24:45 +00:00
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
2016-09-28 14:40:37 +00:00
bb_t * bb ;
bb = ( bb_t * ) arg - > handle ;
2018-02-05 10:43:25 +00:00
HCL_ASSERT ( hcl , bb ! = HCL_NULL & & bb - > fp ! = HCL_NULL ) ;
2016-09-28 14:40:37 +00:00
2018-02-05 10:43:25 +00:00
fclose ( bb - > fp ) ;
2016-09-28 14:40:37 +00:00
hcl_freemem ( hcl , bb ) ;
2018-02-05 10:43:25 +00:00
arg - > handle = HCL_NULL ;
2016-09-28 14:40:37 +00:00
return 0 ;
}
2018-03-09 05:12:55 +00:00
static HCL_INLINE int read_input ( hcl_t * hcl , hcl_ioinarg_t * arg )
2016-09-28 14:40:37 +00:00
{
2018-02-26 15:24:45 +00:00
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
2016-09-28 14:40:37 +00:00
bb_t * bb ;
hcl_oow_t bcslen , ucslen , remlen ;
int x ;
bb = ( bb_t * ) arg - > handle ;
2018-02-05 10:43:25 +00:00
HCL_ASSERT ( hcl , bb ! = HCL_NULL & & bb - > fp ! = HCL_NULL ) ;
2016-09-28 14:40:37 +00:00
do
{
x = fgetc ( bb - > fp ) ;
if ( x = = EOF )
{
if ( ferror ( ( FILE * ) bb - > fp ) )
{
hcl_seterrnum ( hcl , HCL_EIOERR ) ;
return - 1 ;
}
break ;
}
bb - > buf [ bb - > len + + ] = x ;
}
while ( bb - > len < HCL_COUNTOF ( bb - > buf ) & & x ! = ' \r ' & & x ! = ' \n ' ) ;
2018-02-05 10:43:25 +00:00
# if defined(HCL_OOCH_IS_UCH)
2016-09-28 14:40:37 +00:00
bcslen = bb - > len ;
ucslen = HCL_COUNTOF ( arg - > buf ) ;
2018-02-05 10:43:25 +00:00
x = hcl_convbtooochars ( hcl , bb - > buf , & bcslen , arg - > buf , & ucslen ) ;
if ( x < = - 1 & & ucslen < = 0 ) return - 1 ;
/* if ucslen is greater than 0, i see that some characters have been
* converted properly */
# else
bcslen = ( bb - > len < HCL_COUNTOF ( arg - > buf ) ) ? bb - > len : HCL_COUNTOF ( arg - > buf ) ;
ucslen = bcslen ;
2018-04-07 15:54:16 +00:00
hcl_copy_bchars ( arg - > buf , bb - > buf , bcslen ) ;
2018-02-05 10:43:25 +00:00
# endif
2016-09-28 14:40:37 +00:00
remlen = bb - > len - bcslen ;
if ( remlen > 0 ) memmove ( bb - > buf , & bb - > buf [ bcslen ] , remlen ) ;
bb - > len = remlen ;
2018-03-09 05:05:09 +00:00
arg - > xlen = ucslen ;
return 0 ;
2016-09-28 14:40:37 +00:00
}
2018-03-09 05:12:55 +00:00
static int read_handler ( hcl_t * hcl , hcl_iocmd_t cmd , void * arg )
2016-09-28 14:40:37 +00:00
{
switch ( cmd )
{
case HCL_IO_OPEN :
return open_input ( hcl , ( hcl_ioinarg_t * ) arg ) ;
case HCL_IO_CLOSE :
return close_input ( hcl , ( hcl_ioinarg_t * ) arg ) ;
case HCL_IO_READ :
return read_input ( hcl , ( hcl_ioinarg_t * ) arg ) ;
2019-04-17 05:37:56 +00:00
case HCL_IO_FLUSH :
/* no effect on an input stream */
return 0 ;
2016-09-28 14:40:37 +00:00
default :
2018-02-05 10:43:25 +00:00
hcl_seterrnum ( hcl , HCL_EINTERN ) ;
2016-09-28 14:40:37 +00:00
return - 1 ;
}
}
2018-03-09 05:12:55 +00:00
static HCL_INLINE int open_output ( hcl_t * hcl , hcl_iooutarg_t * arg )
2016-09-28 14:40:37 +00:00
{
2018-02-26 15:24:45 +00:00
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
2016-09-28 14:40:37 +00:00
FILE * fp ;
# if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__)
if ( xtn - > print_path ) fp = fopen ( xtn - > print_path , " wb " ) ;
else fp = stdout ;
# else
if ( xtn - > print_path ) fp = fopen ( xtn - > print_path , " w " ) ;
else fp = stdout ;
# endif
if ( ! fp )
{
hcl_seterrnum ( hcl , HCL_EIOERR ) ;
return - 1 ;
}
arg - > handle = fp ;
return 0 ;
}
2018-03-09 05:12:55 +00:00
static HCL_INLINE int close_output ( hcl_t * hcl , hcl_iooutarg_t * arg )
2016-09-28 14:40:37 +00:00
{
2018-02-26 15:24:45 +00:00
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
2016-09-28 14:40:37 +00:00
FILE * fp ;
fp = ( FILE * ) arg - > handle ;
2018-02-05 10:43:25 +00:00
HCL_ASSERT ( hcl , fp ! = HCL_NULL ) ;
2016-09-28 14:40:37 +00:00
2018-03-01 14:47:12 +00:00
if ( fp ! = stdout ) fclose ( fp ) ;
2016-09-28 14:40:37 +00:00
arg - > handle = HCL_NULL ;
return 0 ;
}
2018-03-09 05:12:55 +00:00
static HCL_INLINE int write_output ( hcl_t * hcl , hcl_iooutarg_t * arg )
2016-09-28 14:40:37 +00:00
{
2018-02-26 15:24:45 +00:00
/*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/
2016-09-28 14:40:37 +00:00
hcl_bch_t bcsbuf [ 1024 ] ;
hcl_oow_t bcslen , ucslen , donelen ;
int x ;
donelen = 0 ;
do
{
2018-03-01 14:47:12 +00:00
# if defined(HCL_OOCH_IS_UCH)
2016-09-28 14:40:37 +00:00
bcslen = HCL_COUNTOF ( bcsbuf ) ;
ucslen = arg - > len - donelen ;
2018-03-09 05:05:09 +00:00
x = hcl_convootobchars ( hcl , & arg - > ptr [ donelen ] , & ucslen , bcsbuf , & bcslen ) ;
2018-02-05 10:43:25 +00:00
if ( x < = - 1 & & ucslen < = 0 ) return - 1 ;
2018-03-01 14:47:12 +00:00
# else
2018-02-05 10:43:25 +00:00
bcslen = HCL_COUNTOF ( bcsbuf ) ;
ucslen = arg - > len - donelen ;
if ( ucslen > bcslen ) ucslen = bcslen ;
else if ( ucslen < bcslen ) bcslen = ucslen ;
2018-04-07 15:54:16 +00:00
hcl_copy_bchars ( bcsbuf , & arg - > ptr [ donelen ] , bcslen ) ;
2018-03-01 14:47:12 +00:00
# endif
2016-09-28 14:40:37 +00:00
2018-03-09 05:05:09 +00:00
if ( fwrite ( bcsbuf , HCL_SIZEOF ( bcsbuf [ 0 ] ) , bcslen , ( FILE * ) arg - > handle ) < bcslen )
2016-09-28 14:40:37 +00:00
{
hcl_seterrnum ( hcl , HCL_EIOERR ) ;
return - 1 ;
}
donelen + = ucslen ;
}
while ( donelen < arg - > len ) ;
2018-03-09 05:05:09 +00:00
arg - > xlen = arg - > len ;
return 0 ;
2016-09-28 14:40:37 +00:00
}
2019-04-17 05:37:56 +00:00
static HCL_INLINE int flush_output ( hcl_t * hcl , hcl_iooutarg_t * arg )
{
FILE * fp ;
fp = ( FILE * ) arg - > handle ;
HCL_ASSERT ( hcl , fp ! = HCL_NULL ) ;
fflush ( fp ) ;
return 0 ;
}
2018-03-09 05:12:55 +00:00
static int print_handler ( hcl_t * hcl , hcl_iocmd_t cmd , void * arg )
2016-09-28 14:40:37 +00:00
{
switch ( cmd )
{
case HCL_IO_OPEN :
2019-04-17 05:37:56 +00:00
return open_output ( hcl , ( hcl_iooutarg_t * ) arg ) ;
2016-09-28 14:40:37 +00:00
case HCL_IO_CLOSE :
2019-04-17 05:37:56 +00:00
return close_output ( hcl , ( hcl_iooutarg_t * ) arg ) ;
2016-09-28 14:40:37 +00:00
case HCL_IO_WRITE :
2019-04-17 05:37:56 +00:00
return write_output ( hcl , ( hcl_iooutarg_t * ) arg ) ;
case HCL_IO_FLUSH :
return flush_output ( hcl , ( hcl_iooutarg_t * ) arg ) ;
2016-09-28 14:40:37 +00:00
default :
2018-02-05 10:43:25 +00:00
hcl_seterrnum ( hcl , HCL_EINTERN ) ;
2016-09-28 14:40:37 +00:00
return - 1 ;
}
}
/* ========================================================================= */
2018-03-16 16:20:40 +00:00
static int write_all ( int fd , const hcl_bch_t * ptr , hcl_oow_t len )
2018-03-01 14:47:12 +00:00
{
while ( len > 0 )
{
hcl_ooi_t wr ;
2018-03-12 10:39:13 +00:00
wr = write ( fd , ptr , len ) ;
2018-03-01 14:47:12 +00:00
if ( wr < = - 1 )
{
# if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK)
if ( errno = = EAGAIN ) continue ;
# else
2018-03-12 10:39:13 +00:00
# if defined(EAGAIN)
2018-03-01 14:47:12 +00:00
if ( errno = = EAGAIN ) continue ;
# elif defined(EWOULDBLOCK)
if ( errno = = EWOULDBLOCK ) continue ;
# endif
# endif
# if defined(EINTR)
/* TODO: would this interfere with non-blocking nature of this VM? */
if ( errno = = EINTR ) continue ;
# endif
return - 1 ;
}
ptr + = wr ;
len - = wr ;
}
return 0 ;
}
2018-03-19 09:50:56 +00:00
static int write_log ( hcl_t * hcl , int fd , const hcl_bch_t * ptr , hcl_oow_t len )
2018-03-16 16:20:40 +00:00
{
2019-04-16 15:46:00 +00:00
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
2018-03-16 16:20:40 +00:00
while ( len > 0 )
{
2019-04-16 15:46:00 +00:00
if ( xtn - > log . out . len > 0 )
2018-03-16 16:20:40 +00:00
{
hcl_oow_t rcapa , cplen ;
2019-04-16 15:46:00 +00:00
rcapa = HCL_COUNTOF ( xtn - > log . out . buf ) - xtn - > log . out . len ;
2018-03-16 16:20:40 +00:00
cplen = ( len > = rcapa ) ? rcapa : len ;
2019-04-16 15:46:00 +00:00
HCL_MEMCPY ( & xtn - > log . out . buf [ xtn - > log . out . len ] , ptr , cplen ) ;
xtn - > log . out . len + = cplen ;
2018-03-16 16:20:40 +00:00
ptr + = cplen ;
len - = cplen ;
2019-04-16 15:46:00 +00:00
if ( xtn - > log . out . len > = HCL_COUNTOF ( xtn - > log . out . buf ) )
2018-03-16 16:20:40 +00:00
{
int n ;
2019-04-16 15:46:00 +00:00
n = write_all ( fd , xtn - > log . out . buf , xtn - > log . out . len ) ;
xtn - > log . out . len = 0 ;
2018-03-16 16:20:40 +00:00
if ( n < = - 1 ) return - 1 ;
}
}
else
{
hcl_oow_t rcapa ;
2019-04-16 15:46:00 +00:00
rcapa = HCL_COUNTOF ( xtn - > log . out . buf ) ;
2018-03-16 16:20:40 +00:00
if ( len > = rcapa )
{
2018-03-19 09:50:56 +00:00
if ( write_all ( fd , ptr , rcapa ) < = - 1 ) return - 1 ;
2018-03-16 16:20:40 +00:00
ptr + = rcapa ;
len - = rcapa ;
}
else
{
2019-04-16 15:46:00 +00:00
HCL_MEMCPY ( xtn - > log . out . buf , ptr , len ) ;
xtn - > log . out . len + = len ;
2018-03-16 16:20:40 +00:00
ptr + = len ;
len - = len ;
}
}
}
return 0 ;
}
2018-03-19 09:50:56 +00:00
static void flush_log ( hcl_t * hcl , int fd )
2018-03-16 16:20:40 +00:00
{
2019-04-16 15:46:00 +00:00
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
if ( xtn - > log . out . len > 0 )
2018-03-16 16:20:40 +00:00
{
2019-04-16 15:46:00 +00:00
write_all ( fd , xtn - > log . out . buf , xtn - > log . out . len ) ;
xtn - > log . out . len = 0 ;
2018-03-16 16:20:40 +00:00
}
}
2019-04-16 15:46:00 +00:00
2018-04-26 04:39:20 +00:00
static void log_write ( hcl_t * hcl , hcl_bitmask_t mask , const hcl_ooch_t * msg , hcl_oow_t len )
2018-03-01 14:47:12 +00:00
{
hcl_bch_t buf [ 256 ] ;
hcl_oow_t ucslen , bcslen , msgidx ;
int n ;
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
int logfd ;
2019-04-16 15:46:00 +00:00
if ( mask & HCL_LOG_STDERR ) logfd = 2 ;
else if ( mask & HCL_LOG_STDOUT ) logfd = 1 ;
2018-03-01 14:47:12 +00:00
else
{
2019-04-16 15:46:00 +00:00
logfd = xtn - > log . fd ;
if ( logfd < = - 1 ) return ;
2018-03-01 14:47:12 +00:00
}
/* TODO: beautify the log message.
* do classification based on mask . */
if ( ! ( mask & ( HCL_LOG_STDOUT | HCL_LOG_STDERR ) ) )
{
time_t now ;
char ts [ 32 ] ;
size_t tslen ;
struct tm tm , * tmp ;
2019-04-16 15:46:00 +00:00
now = time ( HCL_NULL ) ;
2018-03-31 07:10:43 +00:00
# if defined(_WIN32)
tmp = localtime ( & now ) ;
tslen = strftime ( ts , sizeof ( ts ) , " %Y-%m-%d %H:%M:%S %z " , tmp ) ;
if ( tslen = = 0 )
{
2019-04-16 15:46:00 +00:00
tslen = sprintf ( ts , " %04d-%02d-%02d %02d:%02d:%02d " , tmp - > tm_year + 1900 , tmp - > tm_mon + 1 , tmp - > tm_mday , tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
2018-03-31 07:10:43 +00:00
}
2019-04-16 15:46:00 +00:00
# elif defined(__OS2__)
# if defined(__WATCOMC__)
tmp = _localtime ( & now , & tm ) ;
# else
2018-03-31 07:10:43 +00:00
tmp = localtime ( & now ) ;
2019-04-16 15:46:00 +00:00
# endif
# if defined(__BORLANDC__)
/* the borland compiler doesn't handle %z properly - it showed 00 all the time */
tslen = strftime ( ts , sizeof ( ts ) , " %Y-%m-%d %H:%M:%S %Z " , tmp ) ;
# else
tslen = strftime ( ts , sizeof ( ts ) , " %Y-%m-%d %H:%M:%S %z " , tmp ) ;
# endif
2018-03-01 14:47:12 +00:00
if ( tslen = = 0 )
{
2019-04-16 15:46:00 +00:00
tslen = sprintf ( ts , " %04d-%02d-%02d %02d:%02d:%02d " , tmp - > tm_year + 1900 , tmp - > tm_mon + 1 , tmp - > tm_mday , tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
2018-03-01 14:47:12 +00:00
}
2019-04-16 15:46:00 +00:00
# elif defined(__DOS__)
tmp = localtime ( & now ) ;
/* since i know that %z/%Z is not available in strftime, i switch to sprintf immediately */
tslen = sprintf ( ts , " %04d-%02d-%02d %02d:%02d:%02d " , tmp - > tm_year + 1900 , tmp - > tm_mon + 1 , tmp - > tm_mday , tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
2018-03-01 14:47:12 +00:00
# else
2019-04-16 15:46:00 +00:00
# if defined(HAVE_LOCALTIME_R)
2018-10-14 10:28:28 +00:00
tmp = localtime_r ( & now , & tm ) ;
# else
tmp = localtime ( & now ) ;
# endif
2019-04-16 15:46:00 +00:00
2018-03-01 14:47:12 +00:00
# if defined(HAVE_STRFTIME_SMALL_Z)
2018-03-31 07:10:43 +00:00
tslen = strftime ( ts , sizeof ( ts ) , " %Y-%m-%d %H:%M:%S %z " , tmp ) ;
2018-03-01 14:47:12 +00:00
# else
2018-03-31 07:10:43 +00:00
tslen = strftime ( ts , sizeof ( ts ) , " %Y-%m-%d %H:%M:%S %Z " , tmp ) ;
2018-03-01 14:47:12 +00:00
# endif
if ( tslen = = 0 )
{
2019-04-16 15:46:00 +00:00
tslen = sprintf ( ts , " %04d-%02d-%02d %02d:%02d:%02d " , tmp - > tm_year + 1900 , tmp - > tm_mon + 1 , tmp - > tm_mday , tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
2018-03-01 14:47:12 +00:00
}
# endif
2018-03-19 09:50:56 +00:00
write_log ( hcl , logfd , ts , tslen ) ;
2018-03-01 14:47:12 +00:00
}
2019-04-16 15:46:00 +00:00
if ( logfd = = xtn - > log . fd & & ( xtn - > log . fd_flag & LOGFD_TTY ) )
2018-03-01 14:47:12 +00:00
{
2018-03-19 09:50:56 +00:00
if ( mask & HCL_LOG_FATAL ) write_log ( hcl , logfd , " \x1B [1;31m " , 7 ) ;
else if ( mask & HCL_LOG_ERROR ) write_log ( hcl , logfd , " \x1B [1 ; 32 m " , 7);
else if ( mask & HCL_LOG_WARN ) write_log ( hcl , logfd , " \x1B [1 ; 33 m " , 7);
2018-03-01 14:47:12 +00:00
}
# if defined(HCL_OOCH_IS_UCH)
msgidx = 0 ;
while ( len > 0 )
{
ucslen = len ;
bcslen = HCL_COUNTOF ( buf ) ;
2018-03-19 09:50:56 +00:00
n = hcl_convootobchars ( hcl , & msg [ msgidx ] , & ucslen , buf , & bcslen ) ;
2018-03-01 14:47:12 +00:00
if ( n = = 0 | | n = = - 2 )
{
/* n = 0:
* converted all successfully
* n = = - 2 :
* buffer not sufficient . not all got converted yet .
* write what have been converted this round . */
HCL_ASSERT ( hcl , ucslen > 0 ) ; /* if this fails, the buffer size must be increased */
/* attempt to write all converted characters */
2018-03-19 09:50:56 +00:00
if ( write_log ( hcl , logfd , buf , bcslen ) < = - 1 ) break ;
2018-03-01 14:47:12 +00:00
if ( n = = 0 ) break ;
else
{
msgidx + = ucslen ;
len - = ucslen ;
}
}
else if ( n < = - 1 )
{
/* conversion error */
break ;
}
}
# else
2018-03-19 09:50:56 +00:00
write_log ( hcl , logfd , msg , len ) ;
2018-03-01 14:47:12 +00:00
# endif
2019-04-16 15:46:00 +00:00
if ( logfd = = xtn - > log . fd & & ( xtn - > log . fd_flag & LOGFD_TTY ) )
2018-03-01 14:47:12 +00:00
{
2018-03-19 09:50:56 +00:00
if ( mask & ( HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN ) ) write_log ( hcl , logfd , " \x1B [0m " , 4 ) ;
2018-03-01 14:47:12 +00:00
}
2018-03-16 16:20:40 +00:00
2018-03-19 09:50:56 +00:00
flush_log ( hcl , logfd ) ;
2018-03-01 14:47:12 +00:00
}
/* ========================================================================= */
2018-02-08 14:40:56 +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
# if defined(_WIN32)
xtn - > waitable_timer = CreateWaitableTimer ( HCL_NULL , TRUE , HCL_NULL ) ;
2018-11-02 14:15:28 +00:00
# endif
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 ;
# if defined(_WIN32)
2018-02-08 14:40:56 +00:00
if ( xtn - > waitable_timer )
{
CloseHandle ( xtn - > waitable_timer ) ;
xtn - > waitable_timer = HCL_NULL ;
}
# endif
}
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 )
{
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
if ( xtn - > sym_errstr ) xtn - > sym_errstr = hcl_moveoop ( hcl , xtn - > sym_errstr ) ;
}
2019-04-16 15:46:00 +00:00
static HCL_INLINE void reset_log_to_default ( xtn_t * xtn )
{
# if defined(ENABLE_LOG_INITIALLY)
xtn - > log . fd = 2 ;
xtn - > log . fd_flag = 0 ;
# if defined(HAVE_ISATTY)
if ( isatty ( xtn - > log . fd ) ) xtn - > log . fd_flag | = LOGFD_TTY ;
# endif
# else
xtn - > log . fd = - 1 ;
xtn - > log . fd_flag = 0 ;
# endif
}
2018-02-05 10:43:25 +00:00
static void fini_hcl ( hcl_t * hcl )
{
2018-02-26 15:24:45 +00:00
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
2019-04-16 15:46:00 +00:00
if ( ( xtn - > log . fd_flag & LOGFD_OPENED_HERE ) & & xtn - > log . fd > = 0 ) close ( xtn - > log . fd ) ;
reset_log_to_default ( xtn ) ;
2018-02-05 10:43:25 +00:00
}
2018-03-10 17:53:44 +00:00
/* ========================================================================= */
2018-02-05 10:43:25 +00:00
static int handle_logopt ( hcl_t * hcl , const hcl_bch_t * str )
{
2019-04-16 15:46:00 +00:00
xtn_t * xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
2018-02-05 10:43:25 +00:00
hcl_bch_t * xstr = ( hcl_bch_t * ) str ;
hcl_bch_t * cm , * flt ;
2018-04-26 04:39:20 +00:00
hcl_bitmask_t logmask ;
2018-02-05 10:43:25 +00:00
2018-04-07 15:54:16 +00:00
cm = hcl_find_bchar_in_bcstr ( xstr , ' , ' ) ;
2018-02-05 10:43:25 +00:00
if ( cm )
{
/* i duplicate this string for open() below as open() doesn't
* accept a length - bounded string */
2018-04-07 15:54:16 +00:00
xstr = hcl_dupbchars ( hcl , str , hcl_count_bcstr ( str ) ) ;
2018-02-05 10:43:25 +00:00
if ( ! xstr )
{
fprintf ( stderr , " ERROR: out of memory in duplicating %s \n " , str ) ;
return - 1 ;
}
2018-04-07 15:54:16 +00:00
cm = hcl_find_bchar_in_bcstr ( xstr , ' , ' ) ;
2018-02-05 10:43:25 +00:00
* cm = ' \0 ' ;
2019-04-16 15:46:00 +00:00
logmask = 0 ;
2018-02-05 10:43:25 +00:00
do
{
flt = cm + 1 ;
2018-04-07 15:54:16 +00:00
cm = hcl_find_bchar_in_bcstr ( flt , ' , ' ) ;
2018-02-05 10:43:25 +00:00
if ( cm ) * cm = ' \0 ' ;
2018-04-07 15:54:16 +00:00
if ( hcl_comp_bcstr ( flt , " app " ) = = 0 ) logmask | = HCL_LOG_APP ;
else if ( hcl_comp_bcstr ( flt , " compiler " ) = = 0 ) logmask | = HCL_LOG_COMPILER ;
else if ( hcl_comp_bcstr ( flt , " vm " ) = = 0 ) logmask | = HCL_LOG_VM ;
else if ( hcl_comp_bcstr ( flt , " mnemonic " ) = = 0 ) logmask | = HCL_LOG_MNEMONIC ;
else if ( hcl_comp_bcstr ( flt , " gc " ) = = 0 ) logmask | = HCL_LOG_GC ;
else if ( hcl_comp_bcstr ( flt , " ic " ) = = 0 ) logmask | = HCL_LOG_IC ;
else if ( hcl_comp_bcstr ( flt , " primitive " ) = = 0 ) logmask | = HCL_LOG_PRIMITIVE ;
else if ( hcl_comp_bcstr ( flt , " fatal " ) = = 0 ) logmask | = HCL_LOG_FATAL ;
else if ( hcl_comp_bcstr ( flt , " error " ) = = 0 ) logmask | = HCL_LOG_ERROR ;
else if ( hcl_comp_bcstr ( flt , " warn " ) = = 0 ) logmask | = HCL_LOG_WARN ;
else if ( hcl_comp_bcstr ( flt , " info " ) = = 0 ) logmask | = HCL_LOG_INFO ;
else if ( hcl_comp_bcstr ( flt , " debug " ) = = 0 ) logmask | = HCL_LOG_DEBUG ;
else if ( hcl_comp_bcstr ( flt , " fatal+ " ) = = 0 ) logmask | = HCL_LOG_FATAL ;
else if ( hcl_comp_bcstr ( flt , " error+ " ) = = 0 ) logmask | = HCL_LOG_FATAL | HCL_LOG_ERROR ;
else if ( hcl_comp_bcstr ( flt , " warn+ " ) = = 0 ) logmask | = HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN ;
else if ( hcl_comp_bcstr ( flt , " info+ " ) = = 0 ) logmask | = HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO ;
else if ( hcl_comp_bcstr ( flt , " debug+ " ) = = 0 ) logmask | = HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN | HCL_LOG_INFO | HCL_LOG_DEBUG ;
2018-02-05 10:43:25 +00:00
else
{
fprintf ( stderr , " ERROR: unknown log option value - %s \n " , flt ) ;
if ( str ! = xstr ) hcl_freemem ( hcl , xstr ) ;
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 ;
2018-02-05 10:43:25 +00:00
}
2018-03-31 07:10:43 +00:00
# if defined(_WIN32)
2019-04-16 15:46:00 +00:00
xtn - > log . fd = _open ( xstr , _O_CREAT | _O_WRONLY | _O_APPEND | _O_BINARY , 0644 ) ;
2018-03-31 07:10:43 +00:00
# else
2019-04-16 15:46:00 +00:00
xtn - > log . fd = open ( xstr , O_CREAT | O_WRONLY | O_APPEND , 0644 ) ;
2018-03-31 07:10:43 +00:00
# endif
2019-04-16 15:46:00 +00:00
if ( xtn - > log . fd = = - 1 )
2018-02-05 10:43:25 +00:00
{
fprintf ( stderr , " ERROR: cannot open a log file %s \n " , xstr ) ;
if ( str ! = xstr ) hcl_freemem ( hcl , xstr ) ;
return - 1 ;
}
2019-04-16 15:46:00 +00:00
xtn - > log . fd_flag | = LOGFD_OPENED_HERE ;
2018-02-05 10:43:25 +00:00
# if defined(HAVE_ISATTY)
2019-04-16 15:46:00 +00:00
if ( isatty ( xtn - > log . fd ) ) xtn - > log . fd_flag | = LOGFD_TTY ;
2018-02-05 10:43:25 +00:00
# endif
if ( str ! = xstr ) hcl_freemem ( hcl , xstr ) ;
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 )
{
2018-03-12 10:39:13 +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 ) ;
if ( hcl_comp_bchars_bcstr ( flt , len , " gc " ) = = 0 ) dbgopt | = HCL_DEBUG_GC ;
else if ( hcl_comp_bchars_bcstr ( flt , len , " bigint " ) = = 0 ) dbgopt | = HCL_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
/* ========================================================================= */
static hcl_t * g_hcl = HCL_NULL ;
/* ========================================================================= */
/* ========================================================================= */
2018-03-31 07:10:43 +00:00
# if defined(_WIN32) || defined(__MSDOS__) || 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
2018-03-31 07:10:43 +00:00
# if defined(_WIN32) || defined(__MSDOS__) || defined(__OS2__)
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 )
{
2018-03-31 07:10:43 +00:00
# if defined(_WIN32) || defined(__MSDOS__) || defined(__OS2__)
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 )
{
2018-03-31 07:10:43 +00:00
# if defined(_WIN32) || defined(__MSDOS__) || defined(__OS2__)
signal ( sig , SIG_DFL ) ;
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 = SIG_DFL ;
sa . sa_flags = 0 ;
sigemptyset ( & sa . sa_mask ) ;
sigaction ( sig , & sa , NULL ) ;
# endif
}
2016-09-28 14:40:37 +00:00
/* ========================================================================= */
static void print_synerr ( hcl_t * hcl )
{
hcl_synerr_t synerr ;
xtn_t * xtn ;
2018-02-26 15:24:45 +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
{
2018-02-05 10:43:25 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " %s " , xtn - > read_path ) ;
2016-09-28 14:40:37 +00:00
}
2018-02-07 13:55:22 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " [%zu,%zu] %js " ,
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 )
{
2018-02-05 10:43:25 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " - %.*js " , synerr . tgt . len , synerr . tgt . ptr ) ;
2016-09-28 14:40:37 +00:00
}
2018-02-05 10:43:25 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " \n " ) ;
2016-09-28 14:40:37 +00:00
}
2018-02-06 10:16:01 +00:00
# define MIN_MEMSIZE 512000ul
2018-02-05 10:43:25 +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 ;
hcl_vmprim_t vmprim ;
2018-02-05 10:43:25 +00:00
hcl_cb_t hclcb ;
hcl_bci_t c ;
static hcl_bopt_lng_t lopt [ ] =
{
{ " :log " , ' l ' } ,
{ " :memsize " , ' m ' } ,
2018-03-01 14:47:12 +00:00
{ " large-pages " , ' \0 ' } ,
2018-02-21 09:30:18 +00:00
# if defined(HCL_BUILD_DEBUG)
2018-02-05 10:43:25 +00:00
{ " :debug " , ' \0 ' } , /* NOTE: there is no short option for --debug */
# endif
{ HCL_NULL , ' \0 ' }
} ;
static hcl_bopt_t opt =
{
2019-04-16 09:35:56 +00:00
" l:m:v " ,
2018-02-05 10:43:25 +00:00
lopt
} ;
const char * logopt = HCL_NULL ;
hcl_oow_t memsize = MIN_MEMSIZE ;
2019-04-16 09:35:56 +00:00
int verbose = 0 ;
2018-03-01 14:47:12 +00:00
int large_pages = 0 ;
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 :
2016-09-28 14:40:37 +00:00
fprintf ( stderr , " Usage: %s filename ... \n " , argv [ 0 ] ) ;
return - 1 ;
}
2018-02-05 10:43:25 +00:00
while ( ( c = hcl_getbopt ( argc , argv , & opt ) ) ! = HCL_BCI_EOF )
{
switch ( c )
{
case ' l ' :
logopt = opt . arg ;
break ;
case ' m ' :
memsize = strtoul ( opt . arg , HCL_NULL , 0 ) ;
if ( memsize < = MIN_MEMSIZE ) memsize = MIN_MEMSIZE ;
break ;
2019-04-16 09:35:56 +00:00
case ' v ' :
verbose = 1 ;
break ;
2018-02-05 10:43:25 +00:00
case ' \0 ' :
2018-04-07 15:54:16 +00:00
if ( hcl_comp_bcstr ( opt . lngopt , " large-pages " ) = = 0 )
2018-03-01 14:47:12 +00:00
{
large_pages = 1 ;
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
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 ;
}
}
if ( opt . ind > = argc ) goto print_usage ;
2016-09-28 14:40:37 +00:00
# endif
memset ( & vmprim , 0 , HCL_SIZEOF ( vmprim ) ) ;
2018-03-01 14:47:12 +00:00
if ( large_pages )
{
2018-11-03 15:57:14 +00:00
vmprim . alloc_heap = hcl_vmprim_alloc_heap ;
vmprim . free_heap = hcl_vmprim_free_heap ;
2018-03-01 14:47:12 +00:00
}
vmprim . log_write = log_write ;
2018-11-03 15:57:14 +00:00
vmprim . syserrstrb = hcl_vmprim_syserrstrb ;
vmprim . assertfail = hcl_vmprim_assertfail ;
vmprim . dl_startup = hcl_vmprim_dl_startup ;
vmprim . dl_cleanup = hcl_vmprim_dl_cleanup ;
vmprim . dl_open = hcl_vmprim_dl_open ;
vmprim . dl_close = hcl_vmprim_dl_close ;
vmprim . dl_getsym = hcl_vmprim_dl_getsym ;
vmprim . gettime = hcl_vmprim_gettime ;
vmprim . sleep = hcl_vmprim_sleep ;
hcl = hcl_open ( & sys_mmgr , HCL_SIZEOF ( xtn_t ) , memsize , & vmprim , HCL_NULL ) ;
2016-09-28 14:40:37 +00:00
if ( ! hcl )
{
2018-04-25 04:12:13 +00:00
printf ( " ERROR: cannot open hcl \n " ) ;
goto oops ;
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 ) ;
tab_size = 600 ;
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
/*trait |= HCL_NOGC;*/
trait | = HCL_AWAIT_PROCS ;
hcl_setoption ( hcl , HCL_TRAIT , & trait ) ;
2018-02-05 10:43:25 +00:00
/* disable GC logs */
2018-02-09 16:10:29 +00:00
/*trait = ~HCL_LOG_GC;
hcl_setoption ( hcl , HCL_LOG_MASK , & trait ) ; */
2016-09-28 14:40:37 +00:00
}
2019-04-16 15:46:00 +00:00
xtn = ( xtn_t * ) hcl_getxtn ( hcl ) ;
reset_log_to_default ( xtn ) ;
2018-02-05 10:43:25 +00:00
memset ( & hclcb , 0 , HCL_SIZEOF ( hclcb ) ) ;
hclcb . fini = fini_hcl ;
2018-03-08 14:18:30 +00:00
hclcb . gc = gc_hcl ;
2018-03-10 17:53:44 +00:00
hclcb . vm_startup = vm_startup ;
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 )
{
2018-04-25 04:12:13 +00:00
if ( handle_dbgopt ( hcl , dbgopt ) < = - 1 ) goto oops ;
2018-02-05 10:43:25 +00:00
}
# endif
2016-09-28 14:40:37 +00:00
if ( hcl_ignite ( hcl ) < = - 1 )
{
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
}
2018-02-05 10:43:25 +00:00
xtn - > read_path = argv [ opt . ind + + ] ;
if ( opt . ind < argc ) xtn - > print_path = argv [ opt . ind + + ] ;
2016-09-28 14:40:37 +00:00
2018-02-20 14:10:09 +00:00
if ( hcl_attachio ( hcl , read_handler , print_handler ) < = - 1 )
2016-09-28 14:40:37 +00:00
{
2018-03-08 14:18:30 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot attach input stream - [%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
}
2018-03-08 14:18:30 +00:00
{
hcl_ooch_t errstr [ ] = { ' E ' , ' R ' , ' R ' , ' S ' , ' T ' , ' R ' } ;
xtn - > sym_errstr = hcl_makesymbol ( hcl , errstr , 6 ) ;
if ( ! xtn - > sym_errstr )
{
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot create the ERRSTR symbol - [%d] %js \n " , hcl_geterrnum ( hcl ) , hcl_geterrmsg ( hcl ) ) ;
2018-04-25 04:12:13 +00:00
goto oops ;
2018-03-08 14:18:30 +00:00
}
HCL_OBJ_SET_FLAGS_KERNEL ( xtn - > sym_errstr , 1 ) ;
}
2018-03-10 17:53:44 +00:00
/* -- from this point onward, any failure leads to jumping to the oops label
* - - instead of returning - 1 immediately . - - */
set_signal ( SIGINT , handle_sigint ) ;
2019-06-02 06:42:47 +00:00
#if 0
2019-06-02 05:06:08 +00:00
hcl_prbfmt ( hcl , " this is good %s %10hs %hs \n " , " whole new world. 1234567890 from this point onward, any failure leasd to jumping to oops label " , " as이거 좋은거잖아dkfjsdakfjsadklfjasd " , " 1111 " ) ;
2019-06-02 06:42:47 +00:00
{
hcl_uch_t fmt [ ] = { ' G ' , ' G ' , ' % ' , ' l ' , ' s ' , ' a ' , ' b ' , ' c ' , ' - ' , ' - ' , ' % ' , ' 0 ' , ' 2 ' , ' 0 ' , ' x ' , ' \0 ' } ;
hcl_uch_t ustr [ ] = { ' A ' , ' B ' , ' C ' , ' X ' , ' Y ' , ' Z ' , ' Q ' , ' Q ' , ' \0 ' } ;
hcl_prufmt ( hcl , fmt , ustr , 0x6789 ) ;
hcl_logufmt ( hcl , HCL_LOG_WARN , fmt , ustr , 0x6789 ) ;
}
# endif
2016-09-28 14:40:37 +00:00
while ( 1 )
{
hcl_oop_t obj ;
2018-03-08 14:18:30 +00:00
/*
static int count = 0 ;
if ( count % 5 = = 0 ) hcl_reset ( hcl ) ;
count + + ;
*/
2018-02-05 10:43:25 +00:00
obj = hcl_read ( hcl ) ;
2016-09-28 14:40:37 +00:00
if ( ! obj )
{
if ( hcl - > errnum = = HCL_EFINIS )
{
/* end of input */
break ;
}
else if ( hcl - > errnum = = HCL_ESYNERR )
{
print_synerr ( hcl ) ;
2018-08-05 18:46:54 +00:00
if ( xtn - > reader_istty & & hcl_getsynerrnum ( hcl ) ! = HCL_SYNERR_EOF )
{
/* TODO: drain remaining data in the reader including the actual inputstream and buffered data in hcl */
continue ;
}
2016-09-28 14:40:37 +00:00
}
else
{
2018-02-05 15:59:32 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot read object - [%d] %js \n " , hcl_geterrnum ( hcl ) , hcl_geterrmsg ( hcl ) ) ;
2016-09-28 14:40:37 +00:00
}
2018-02-20 14:10:09 +00:00
goto oops ;
2016-09-28 14:40:37 +00:00
}
2019-04-16 09:35:56 +00:00
if ( verbose & & hcl_print ( hcl , obj ) < = - 1 )
2016-09-28 14:40:37 +00:00
{
2018-02-05 15:59:32 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot print object - [%d] %js \n " , hcl_geterrnum ( hcl ) , hcl_geterrmsg ( hcl ) ) ;
2016-09-28 14:40:37 +00:00
}
else
{
2018-02-08 10:33:59 +00:00
hcl_oow_t code_offset ;
2018-03-11 11:16:28 +00:00
code_offset = hcl_getbclen ( hcl ) ;
2018-02-08 10:33:59 +00:00
2019-05-31 10:54:13 +00:00
if ( verbose ) hcl_prbfmt ( hcl , " \n " ) ; /* flush the output buffer by hcl_print above */
2018-02-05 10:43:25 +00:00
if ( hcl_compile ( hcl , obj ) < = - 1 )
2016-10-01 04:36:48 +00:00
{
if ( hcl - > errnum = = HCL_ESYNERR )
{
print_synerr ( hcl ) ;
}
else
{
2018-02-05 15:59:32 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot compile object - [%d] %js \n " , hcl_geterrnum ( hcl ) , hcl_geterrmsg ( hcl ) ) ;
2016-10-01 04:36:48 +00:00
}
/* carry on? */
2018-02-09 17:15:31 +00:00
if ( ! xtn - > reader_istty ) goto oops ;
2016-10-01 04:36:48 +00:00
}
2018-02-08 15:04:07 +00:00
else if ( xtn - > reader_istty )
2018-02-08 07:40:27 +00:00
{
2019-04-17 05:37:56 +00:00
/* interactive mode */
2018-02-22 12:57:31 +00:00
hcl_oop_t retv ;
2018-03-11 11:16:28 +00:00
hcl_decode ( hcl , code_offset , hcl_getbclen ( hcl ) ) ;
2018-02-08 07:40:27 +00:00
HCL_LOG0 ( hcl , HCL_LOG_MNEMONIC , " ------------------------------------------ \n " ) ;
g_hcl = hcl ;
//setup_tick ();
2018-02-22 12:57:31 +00:00
retv = hcl_executefromip ( hcl , code_offset ) ;
2019-04-17 05:37:56 +00:00
/* flush pending output data in the interactive mode(e.g. printf without a newline) */
hcl_flushio ( hcl ) ;
2018-02-22 12:57:31 +00:00
if ( ! retv )
2018-02-08 07:40:27 +00:00
{
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot execute - [%d] %js \n " , hcl_geterrnum ( hcl ) , hcl_geterrmsg ( hcl ) ) ;
}
2018-02-22 07:41:03 +00:00
else
{
2019-04-16 15:46:00 +00:00
/* print the result in the interactive mode regardless 'verbose' */
hcl_logbfmt ( hcl , HCL_LOG_STDOUT , " %O \n " , retv ) ;
2018-03-08 14:18:30 +00:00
/*
* 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 ) ) ;
}
*/
2018-02-22 07:41:03 +00:00
}
2018-02-08 07:40:27 +00:00
//cancel_tick();
g_hcl = HCL_NULL ;
}
2016-09-28 14:40:37 +00:00
}
2018-02-08 07:40:27 +00:00
}
2018-02-08 15:04:07 +00:00
if ( ! xtn - > reader_istty )
{
2018-02-22 12:57:31 +00:00
hcl_oop_t retv ;
2018-03-11 11:16:28 +00:00
hcl_decode ( hcl , 0 , hcl_getbclen ( hcl ) ) ;
HCL_LOG2 ( hcl , HCL_LOG_MNEMONIC , " BYTECODES bclen = > %zu lflen => %zu \n " , hcl_getbclen ( hcl ) , hcl_getlflen ( hcl ) ) ;
2018-02-08 15:04:07 +00:00
g_hcl = hcl ;
2018-03-11 11:16:28 +00:00
/*setup_tick ();*/
2018-02-22 12:57:31 +00:00
retv = hcl_execute ( hcl ) ;
if ( ! retv )
2018-02-08 15:04:07 +00:00
{
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " ERROR: cannot execute - [%d] %js \n " , hcl_geterrnum ( hcl ) , hcl_geterrmsg ( hcl ) ) ;
}
2019-04-16 15:46:00 +00:00
else if ( verbose )
2018-02-22 07:41:03 +00:00
{
2019-04-16 15:46:00 +00:00
hcl_logbfmt ( hcl , HCL_LOG_STDERR , " EXECUTION OK - EXITED WITH %O \n " , retv ) ;
2018-02-22 07:41:03 +00:00
}
2018-02-22 12:57:31 +00:00
2018-03-11 11:16:28 +00:00
/*cancel_tick();*/
2018-02-08 15:04:07 +00:00
g_hcl = HCL_NULL ;
/*hcl_dumpsymtab (hcl);*/
}
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
}