2015-05-08 14:29:35 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2017-01-10 14:27:31 +00:00
|
|
|
Copyright (c) 2014-2017 Chung, Hyung-Hwan. All rights reserved.
|
2015-05-08 14:29:35 +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.
|
|
|
|
*/
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
#include "moo-prv.h"
|
2017-11-22 04:52:45 +00:00
|
|
|
#include "moo-opt.h"
|
2015-05-07 15:58:04 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2015-05-17 05:02:30 +00:00
|
|
|
#include <string.h>
|
2015-06-04 18:34:37 +00:00
|
|
|
#include <limits.h>
|
2016-07-01 16:31:47 +00:00
|
|
|
#include <errno.h>
|
2017-07-27 08:32:16 +00:00
|
|
|
#include <locale.h>
|
2015-10-14 13:25:36 +00:00
|
|
|
|
2017-06-08 14:39:17 +00:00
|
|
|
#if !defined(__DOS__)
|
|
|
|
# define USE_THREAD
|
|
|
|
#endif
|
2015-10-14 13:25:36 +00:00
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
# include <windows.h>
|
|
|
|
# include <tchar.h>
|
2017-02-09 16:26:44 +00:00
|
|
|
# if defined(MOO_HAVE_CFG_H) && defined(MOO_ENABLE_LIBLTDL)
|
2015-10-14 13:25:36 +00:00
|
|
|
# include <ltdl.h>
|
|
|
|
# define USE_LTDL
|
|
|
|
# endif
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
# define INCL_DOSMODULEMGR
|
|
|
|
# define INCL_DOSPROCESS
|
2017-02-10 09:06:53 +00:00
|
|
|
# define INCL_DOSMISC
|
|
|
|
# define INCL_DOSDATETIME
|
2015-10-14 13:25:36 +00:00
|
|
|
# define INCL_DOSERRORS
|
|
|
|
# include <os2.h>
|
2017-02-10 09:06:53 +00:00
|
|
|
# include <time.h>
|
2017-01-09 14:52:15 +00:00
|
|
|
#elif defined(__DOS__)
|
2016-05-18 14:53:20 +00:00
|
|
|
# include <dos.h>
|
2017-01-09 14:52:15 +00:00
|
|
|
# include <time.h>
|
2017-01-15 17:53:37 +00:00
|
|
|
# include <io.h>
|
2017-06-08 14:39:17 +00:00
|
|
|
# include <signal.h>
|
|
|
|
|
|
|
|
/* fake XPOLLXXX values */
|
|
|
|
# define XPOLLIN (1 << 0)
|
|
|
|
# define XPOLLOUT (1 << 1)
|
|
|
|
# define XPOLLERR (1 << 2)
|
|
|
|
# define XPOLLHUP (1 << 3)
|
|
|
|
|
2015-12-03 05:46:11 +00:00
|
|
|
#elif defined(macintosh)
|
2017-02-10 09:06:53 +00:00
|
|
|
# include <Types.h>
|
|
|
|
# include <OSUtils.h>
|
2016-05-19 03:49:23 +00:00
|
|
|
# include <Timer.h>
|
2017-06-08 14:39:17 +00:00
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
#else
|
2017-02-21 19:20:27 +00:00
|
|
|
|
2017-02-09 16:26:44 +00:00
|
|
|
# if defined(MOO_ENABLE_LIBLTDL)
|
|
|
|
# include <ltdl.h>
|
|
|
|
# define USE_LTDL
|
2017-05-07 08:58:34 +00:00
|
|
|
# elif defined(HAVE_DLFCN_H)
|
2017-02-09 16:26:44 +00:00
|
|
|
# include <dlfcn.h>
|
|
|
|
# error NOT IMPLEMENTED
|
2017-05-07 08:58:34 +00:00
|
|
|
# else
|
|
|
|
# error UNSUPPORTED DYNAMIC LINKER
|
2017-02-09 16:26:44 +00:00
|
|
|
# endif
|
2016-05-17 15:12:27 +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
|
2017-02-12 18:59:03 +00:00
|
|
|
|
2017-02-21 19:20:27 +00:00
|
|
|
# include <unistd.h>
|
2017-02-21 19:51:10 +00:00
|
|
|
# include <fcntl.h>
|
|
|
|
|
|
|
|
# if defined(USE_THREAD)
|
|
|
|
# include <pthread.h>
|
|
|
|
# include <sched.h>
|
|
|
|
# endif
|
2017-05-07 08:58:34 +00:00
|
|
|
|
|
|
|
# if defined(HAVE_SYS_DEVPOLL_H)
|
|
|
|
/* solaris */
|
|
|
|
# include <sys/devpoll.h>
|
|
|
|
# define USE_DEVPOLL
|
|
|
|
# define XPOLLIN POLLIN
|
|
|
|
# define XPOLLOUT POLLOUT
|
|
|
|
# define XPOLLERR POLLERR
|
|
|
|
# define XPOLLHUP POLLHUP
|
|
|
|
# elif defined(HAVE_SYS_EPOLL_H)
|
|
|
|
/* linux */
|
|
|
|
# include <sys/epoll.h>
|
|
|
|
# define USE_EPOLL
|
|
|
|
# define XPOLLIN EPOLLIN
|
|
|
|
# define XPOLLOUT EPOLLOUT
|
|
|
|
# define XPOLLERR EPOLLERR
|
|
|
|
# define XPOLLHUP EPOLLHUP
|
|
|
|
# elif defined(HAVE_POLL_H)
|
|
|
|
# include <poll.h>
|
|
|
|
# define USE_POLL
|
|
|
|
# define XPOLLIN POLLIN
|
|
|
|
# define XPOLLOUT POLLOUT
|
|
|
|
# define XPOLLERR POLLERR
|
|
|
|
# define XPOLLHUP POLLHUP
|
|
|
|
# else
|
2017-09-27 01:03:18 +00:00
|
|
|
# define USE_SELECT
|
|
|
|
/* fake XPOLLXXX values */
|
|
|
|
# define XPOLLIN (1 << 0)
|
|
|
|
# define XPOLLOUT (1 << 1)
|
|
|
|
# define XPOLLERR (1 << 2)
|
|
|
|
# define XPOLLHUP (1 << 3)
|
2017-05-07 08:58:34 +00:00
|
|
|
# endif
|
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
#if !defined(MOO_DEFAULT_PFMODPREFIX)
|
2015-10-14 09:06:44 +00:00
|
|
|
# if defined(_WIN32)
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPREFIX "moo-"
|
2015-10-14 09:06:44 +00:00
|
|
|
# elif defined(__OS2__)
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPREFIX "moo"
|
2017-01-09 14:52:15 +00:00
|
|
|
# elif defined(__DOS__)
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPREFIX "moo"
|
2015-10-14 09:06:44 +00:00
|
|
|
# else
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPREFIX "libmoo-"
|
2015-10-14 09:06:44 +00:00
|
|
|
# endif
|
2015-10-13 14:51:04 +00:00
|
|
|
#endif
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
#if !defined(MOO_DEFAULT_PFMODPOSTFIX)
|
2015-10-14 09:06:44 +00:00
|
|
|
# if defined(_WIN32)
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPOSTFIX ""
|
2015-10-14 09:06:44 +00:00
|
|
|
# elif defined(__OS2__)
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPOSTFIX ""
|
2017-01-09 14:52:15 +00:00
|
|
|
# elif defined(__DOS__)
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPOSTFIX ""
|
2015-10-14 09:06:44 +00:00
|
|
|
# else
|
2017-01-10 10:50:26 +00:00
|
|
|
# define MOO_DEFAULT_PFMODPOSTFIX ""
|
2015-10-14 09:06:44 +00:00
|
|
|
# endif
|
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_THREAD)
|
|
|
|
# define MUTEX_INIT(x) pthread_mutex_init((x), MOO_NULL)
|
|
|
|
# define MUTEX_DESTROY(x) pthread_mutex_destroy(x)
|
|
|
|
# define MUTEX_LOCK(x) pthread_mutex_lock(x)
|
|
|
|
# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x)
|
|
|
|
#else
|
|
|
|
# define MUTEX_INIT(x)
|
|
|
|
# define MUTEX_DESTROY(x)
|
|
|
|
# define MUTEX_LOCK(x)
|
|
|
|
# define MUTEX_UNLOCK(x)
|
|
|
|
#endif
|
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
typedef struct bb_t bb_t;
|
|
|
|
struct bb_t
|
|
|
|
{
|
|
|
|
char buf[1024];
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_oow_t pos;
|
|
|
|
moo_oow_t len;
|
2017-02-02 12:45:15 +00:00
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
FILE* fp;
|
2017-02-02 12:45:15 +00:00
|
|
|
moo_bch_t* fn;
|
2016-08-15 12:19:04 +00:00
|
|
|
};
|
|
|
|
|
2017-09-27 06:48:01 +00:00
|
|
|
#if defined(USE_SELECT)
|
|
|
|
struct select_fd_t
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int events;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2015-05-15 14:55:12 +00:00
|
|
|
typedef struct xtn_t xtn_t;
|
|
|
|
struct xtn_t
|
|
|
|
{
|
2016-08-15 12:19:04 +00:00
|
|
|
const char* source_path; /* main source file */
|
2017-06-23 16:09:07 +00:00
|
|
|
int vm_running;
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
int logfd;
|
2017-11-23 15:45:25 +00:00
|
|
|
int logmask;
|
2017-11-22 04:52:45 +00:00
|
|
|
|
2017-02-11 05:48:30 +00:00
|
|
|
#if defined(_WIN32)
|
|
|
|
HANDLE waitable_timer;
|
2017-02-12 18:59:03 +00:00
|
|
|
#else
|
2017-04-28 14:45:13 +00:00
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
int ep; /* /dev/poll */
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
moo_oow_t capa;
|
|
|
|
moo_ooi_t* ptr;
|
|
|
|
} epd;
|
|
|
|
#elif defined(USE_EPOLL)
|
|
|
|
int ep; /* epoll */
|
|
|
|
#elif defined(USE_POLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
moo_oow_t capa;
|
|
|
|
moo_ooi_t* ptr;
|
|
|
|
} epd;
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
struct
|
|
|
|
{
|
2017-09-27 14:03:05 +00:00
|
|
|
void* data[FD_SETSIZE];
|
2017-09-27 06:48:01 +00:00
|
|
|
} epd;
|
2017-06-23 16:09:07 +00:00
|
|
|
#endif
|
2017-02-21 19:51:10 +00:00
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
#if defined(USE_THREAD)
|
2017-02-21 19:20:27 +00:00
|
|
|
int p[2]; /* pipe for signaling */
|
|
|
|
pthread_t iothr;
|
2017-03-04 05:48:23 +00:00
|
|
|
int iothr_up;
|
2017-02-22 09:48:58 +00:00
|
|
|
int iothr_abort;
|
2017-06-23 16:09:07 +00:00
|
|
|
#endif
|
2017-05-07 12:43:52 +00:00
|
|
|
|
2017-02-21 19:20:27 +00:00
|
|
|
struct
|
|
|
|
{
|
2017-04-28 14:45:13 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
2017-05-07 10:23:21 +00:00
|
|
|
/*TODO: make it dynamically changeable depending on the number of
|
|
|
|
* file descriptors added */
|
2017-09-27 01:03:18 +00:00
|
|
|
struct pollfd buf[64]; /* buffer for reading events */
|
2017-05-07 10:23:21 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
|
|
|
/*TODO: make it dynamically changeable depending on the number of
|
|
|
|
* file descriptors added */
|
2017-09-27 01:03:18 +00:00
|
|
|
struct epoll_event buf[64]; /* buffer for reading events */
|
2017-05-07 10:23:21 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
struct pollfd* ptr;
|
|
|
|
moo_oow_t capa;
|
|
|
|
moo_oow_t len;
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_THREAD)
|
|
|
|
pthread_mutex_t pmtx;
|
|
|
|
#endif
|
2017-05-07 10:23:21 +00:00
|
|
|
} reg; /* registrar */
|
|
|
|
struct pollfd* buf;
|
2017-09-27 14:03:05 +00:00
|
|
|
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
fd_set rfds;
|
|
|
|
fd_set wfds;
|
|
|
|
int maxfd;
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_THREAD)
|
|
|
|
pthread_mutex_t smtx;
|
|
|
|
#endif
|
2017-09-27 01:03:18 +00:00
|
|
|
} reg;
|
2017-09-27 06:48:01 +00:00
|
|
|
|
|
|
|
struct select_fd_t buf[FD_SETSIZE];
|
2017-04-28 14:45:13 +00:00
|
|
|
#endif
|
2017-05-07 12:43:52 +00:00
|
|
|
|
2017-02-21 19:20:27 +00:00
|
|
|
moo_oow_t len;
|
2017-09-27 06:48:01 +00:00
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
#if defined(USE_THREAD)
|
2017-02-21 19:20:27 +00:00
|
|
|
pthread_mutex_t mtx;
|
|
|
|
pthread_cond_t cnd;
|
|
|
|
pthread_cond_t cnd2;
|
2017-06-23 16:09:07 +00:00
|
|
|
#endif
|
2017-05-07 12:43:52 +00:00
|
|
|
} ev;
|
2017-02-11 05:48:30 +00:00
|
|
|
#endif
|
2015-05-16 07:31:16 +00:00
|
|
|
};
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static void* sys_alloc (moo_mmgr_t* mmgr, moo_oow_t size)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return malloc (size);
|
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static void* sys_realloc (moo_mmgr_t* mmgr, void* ptr, moo_oow_t size)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return realloc (ptr, size);
|
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static void sys_free (moo_mmgr_t* mmgr, void* ptr)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
free (ptr);
|
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static moo_mmgr_t sys_mmgr =
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
sys_alloc,
|
|
|
|
sys_realloc,
|
|
|
|
sys_free,
|
2017-01-09 09:54:49 +00:00
|
|
|
MOO_NULL
|
2015-05-07 15:58:04 +00:00
|
|
|
};
|
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2016-12-28 13:42:12 +00:00
|
|
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
|
|
|
# define IS_PATH_SEP(c) ((c) == '/' || (c) == '\\')
|
|
|
|
#else
|
|
|
|
# define IS_PATH_SEP(c) ((c) == '/')
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static const moo_bch_t* get_base_name (const moo_bch_t* path)
|
2016-12-28 13:42:12 +00:00
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
const moo_bch_t* p, * last = MOO_NULL;
|
2016-12-28 13:42:12 +00:00
|
|
|
|
|
|
|
for (p = path; *p != '\0'; p++)
|
|
|
|
{
|
|
|
|
if (IS_PATH_SEP(*p)) last = p;
|
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
return (last == MOO_NULL)? path: (last + 1);
|
2016-12-28 13:42:12 +00:00
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static MOO_INLINE moo_ooi_t open_input (moo_t* moo, moo_ioarg_t* arg)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
xtn_t* xtn = moo_getxtn(moo);
|
2017-02-03 06:28:12 +00:00
|
|
|
bb_t* bb = MOO_NULL;
|
2016-08-15 12:19:04 +00:00
|
|
|
|
2017-02-02 12:45:15 +00:00
|
|
|
/* TOOD: support predefined include directory as well */
|
2015-05-15 14:55:12 +00:00
|
|
|
if (arg->includer)
|
|
|
|
{
|
|
|
|
/* includee */
|
2017-02-02 12:45:15 +00:00
|
|
|
moo_oow_t ucslen, bcslen, parlen;
|
|
|
|
const moo_bch_t* fn, * fb;
|
2016-12-28 13:42:12 +00:00
|
|
|
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
|
|
|
if (moo_convootobcstr (moo, arg->name, &ucslen, MOO_NULL, &bcslen) <= -1) goto oops;
|
|
|
|
#else
|
|
|
|
bcslen = moo_countbcstr (arg->name);
|
|
|
|
#endif
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2017-02-02 12:45:15 +00:00
|
|
|
fn = ((bb_t*)arg->includer->handle)->fn;
|
2015-05-20 14:27:47 +00:00
|
|
|
|
2017-02-02 12:45:15 +00:00
|
|
|
fb = get_base_name (fn);
|
|
|
|
parlen = fb - fn;
|
|
|
|
|
|
|
|
bb = moo_callocmem (moo, MOO_SIZEOF(*bb) + (MOO_SIZEOF(moo_bch_t) * (parlen + bcslen + 1)));
|
2017-02-03 06:28:12 +00:00
|
|
|
if (!bb) goto oops;
|
2017-02-02 12:45:15 +00:00
|
|
|
|
|
|
|
bb->fn = (moo_bch_t*)(bb + 1);
|
|
|
|
moo_copybchars (bb->fn, fn, parlen);
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-02-02 12:45:15 +00:00
|
|
|
moo_convootobcstr (moo, arg->name, &ucslen, &bb->fn[parlen], &bcslen);
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
|
|
|
moo_copybcstr (&bb->fn[parlen], bcslen + 1, arg->name);
|
|
|
|
#endif
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* main stream */
|
2017-02-02 12:45:15 +00:00
|
|
|
moo_oow_t pathlen;
|
|
|
|
|
|
|
|
pathlen = moo_countbcstr (xtn->source_path);
|
|
|
|
|
|
|
|
bb = moo_callocmem (moo, MOO_SIZEOF(*bb) + (MOO_SIZEOF(moo_bch_t) * (pathlen + 1)));
|
2017-02-03 06:28:12 +00:00
|
|
|
if (!bb) goto oops;
|
2017-02-02 12:45:15 +00:00
|
|
|
|
|
|
|
bb->fn = (moo_bch_t*)(bb + 1);
|
|
|
|
moo_copybcstr (bb->fn, pathlen + 1, xtn->source_path);
|
|
|
|
}
|
|
|
|
|
2017-01-09 14:52:15 +00:00
|
|
|
#if defined(__DOS__) || defined(_WIN32) || defined(__OS2__)
|
2017-02-02 12:45:15 +00:00
|
|
|
bb->fp = fopen (bb->fn, "rb");
|
2015-06-11 13:10:33 +00:00
|
|
|
#else
|
2017-02-02 12:45:15 +00:00
|
|
|
bb->fp = fopen (bb->fn, "r");
|
2015-06-11 13:10:33 +00:00
|
|
|
#endif
|
2017-02-02 12:45:15 +00:00
|
|
|
if (!bb->fp)
|
2015-05-17 05:02:30 +00:00
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_seterrnum (moo, MOO_EIOERR);
|
2017-02-03 06:28:12 +00:00
|
|
|
goto oops;
|
2015-05-17 05:02:30 +00:00
|
|
|
}
|
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
arg->handle = bb;
|
|
|
|
return 0;
|
2017-02-03 06:28:12 +00:00
|
|
|
|
|
|
|
oops:
|
2017-02-09 15:56:51 +00:00
|
|
|
if (bb)
|
|
|
|
{
|
|
|
|
if (bb->fp) fclose (bb->fp);
|
|
|
|
moo_freemem (moo, bb);
|
|
|
|
}
|
2017-02-03 06:28:12 +00:00
|
|
|
return -1;
|
2016-08-15 12:19:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static MOO_INLINE moo_ooi_t close_input (moo_t* moo, moo_ioarg_t* arg)
|
2016-08-15 12:19:04 +00:00
|
|
|
{
|
2017-02-02 12:45:15 +00:00
|
|
|
/*xtn_t* xtn = moo_getxtn(moo);*/
|
2016-08-15 12:19:04 +00:00
|
|
|
bb_t* bb;
|
|
|
|
|
|
|
|
bb = (bb_t*)arg->handle;
|
2017-01-09 09:54:49 +00:00
|
|
|
MOO_ASSERT (moo, bb != MOO_NULL && bb->fp != MOO_NULL);
|
2016-08-15 12:19:04 +00:00
|
|
|
|
|
|
|
fclose (bb->fp);
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_freemem (moo, bb);
|
2016-08-15 12:19:04 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
arg->handle = MOO_NULL;
|
2015-05-17 05:02:30 +00:00
|
|
|
return 0;
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static MOO_INLINE moo_ooi_t read_input (moo_t* moo, moo_ioarg_t* arg)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
2016-09-23 08:56:25 +00:00
|
|
|
/*xtn_t* xtn = hcl_getxtn(hcl);*/
|
2016-08-15 12:19:04 +00:00
|
|
|
bb_t* bb;
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_oow_t bcslen, ucslen, remlen;
|
2015-05-16 07:31:16 +00:00
|
|
|
int x;
|
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
bb = (bb_t*)arg->handle;
|
2017-01-09 09:54:49 +00:00
|
|
|
MOO_ASSERT (moo, bb != MOO_NULL && bb->fp != MOO_NULL);
|
2016-09-23 08:56:25 +00:00
|
|
|
do
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
2016-09-23 08:56:25 +00:00
|
|
|
x = fgetc (bb->fp);
|
|
|
|
if (x == EOF)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
2016-09-23 08:56:25 +00:00
|
|
|
if (ferror((FILE*)bb->fp))
|
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_seterrnum (moo, MOO_EIOERR);
|
2016-09-23 08:56:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
2016-09-23 08:56:25 +00:00
|
|
|
|
|
|
|
bb->buf[bb->len++] = x;
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
2017-01-09 09:54:49 +00:00
|
|
|
while (bb->len < MOO_COUNTOF(bb->buf) && x != '\r' && x != '\n');
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2016-08-15 12:19:04 +00:00
|
|
|
bcslen = bb->len;
|
2017-01-09 09:54:49 +00:00
|
|
|
ucslen = MOO_COUNTOF(arg->buf);
|
|
|
|
x = moo_convbtooochars (moo, bb->buf, &bcslen, arg->buf, &ucslen);
|
2017-01-12 10:06:43 +00:00
|
|
|
if (x <= -1 && ucslen <= 0) return -1;
|
|
|
|
/* if ucslen is greater than 0, i see that some characters have been
|
|
|
|
* converted properly */
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
|
|
|
bcslen = (bb->len < MOO_COUNTOF(arg->buf))? bb->len: MOO_COUNTOF(arg->buf);
|
|
|
|
ucslen = bcslen;
|
|
|
|
moo_copybchars (arg->buf, bb->buf, bcslen);
|
|
|
|
#endif
|
2015-05-17 05:02:30 +00:00
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
remlen = bb->len - bcslen;
|
|
|
|
if (remlen > 0) memmove (bb->buf, &bb->buf[bcslen], remlen);
|
|
|
|
bb->len = remlen;
|
2015-05-17 05:02:30 +00:00
|
|
|
return ucslen;
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static moo_ooi_t input_handler (moo_t* moo, moo_iocmd_t cmd, moo_ioarg_t* arg)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
|
|
|
switch (cmd)
|
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
case MOO_IO_OPEN:
|
|
|
|
return open_input (moo, arg);
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
case MOO_IO_CLOSE:
|
|
|
|
return close_input (moo, arg);
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
case MOO_IO_READ:
|
|
|
|
return read_input (moo, arg);
|
2015-05-15 14:55:12 +00:00
|
|
|
|
|
|
|
default:
|
2017-05-11 14:59:20 +00:00
|
|
|
moo_seterrnum (moo, MOO_EINTERN);
|
2015-05-15 14:55:12 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static void* dl_open (moo_t* moo, const moo_ooch_t* name, int flags)
|
2015-10-13 14:51:04 +00:00
|
|
|
{
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
2017-02-09 08:05:14 +00:00
|
|
|
moo_bch_t stabuf[128], * bufptr;
|
2017-02-04 05:30:15 +00:00
|
|
|
moo_oow_t ucslen, bcslen, bufcapa;
|
2015-10-14 13:25:36 +00:00
|
|
|
void* handle;
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-02-04 05:30:15 +00:00
|
|
|
if (moo_convootobcstr (moo, name, &ucslen, MOO_NULL, &bufcapa) <= -1) return MOO_NULL;
|
|
|
|
/* +1 for terminating null. but it's not needed because MOO_COUNTOF(MOO_DEFAULT_PFMODPREFIX)
|
|
|
|
* and MOO_COUNTOF(MOO_DEFAULT_PFMODPOSTIFX) include the terminating nulls. Never mind about
|
|
|
|
* the extra 2 characters. */
|
2017-02-09 08:05:14 +00:00
|
|
|
#else
|
|
|
|
bufcapa = moo_countbcstr (name);
|
|
|
|
#endif
|
2017-02-04 05:30:15 +00:00
|
|
|
bufcapa += MOO_COUNTOF(MOO_DEFAULT_PFMODPREFIX) + MOO_COUNTOF(MOO_DEFAULT_PFMODPOSTFIX) + 1;
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
if (bufcapa <= MOO_COUNTOF(stabuf)) bufptr = stabuf;
|
2017-02-04 05:30:15 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
bufptr = moo_allocmem (moo, bufcapa * MOO_SIZEOF(*bufptr));
|
|
|
|
if (!bufptr) return MOO_NULL;
|
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
if (flags & MOO_VMPRIM_OPENDL_PFMOD)
|
|
|
|
{
|
2017-02-13 13:25:42 +00:00
|
|
|
moo_oow_t len, i, xlen;
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
/* opening a primitive function module - mostly libmoo-xxxx */
|
2017-02-04 05:30:15 +00:00
|
|
|
len = moo_copybcstr (bufptr, bufcapa, MOO_DEFAULT_PFMODPREFIX);
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2017-02-04 05:30:15 +00:00
|
|
|
bcslen = bufcapa - len;
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-02-04 05:30:15 +00:00
|
|
|
moo_convootobcstr (moo, name, &ucslen, &bufptr[len], &bcslen);
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
2017-02-04 05:30:15 +00:00
|
|
|
bcslen = moo_copybcstr (&bufptr[len], bcslen, name);
|
2017-02-03 06:28:12 +00:00
|
|
|
#endif
|
2017-02-13 13:25:42 +00:00
|
|
|
|
|
|
|
/* length including the prefix and the name. but excluding the postfix */
|
|
|
|
xlen = len + bcslen;
|
|
|
|
|
|
|
|
for (i = len; i < xlen; i++)
|
|
|
|
{
|
2017-02-18 15:00:45 +00:00
|
|
|
/* convert a period(.) to a dash(-) */
|
2017-02-13 13:25:42 +00:00
|
|
|
if (bufptr[i] == '.') bufptr[i] = '-';
|
|
|
|
}
|
2017-02-03 06:28:12 +00:00
|
|
|
|
2017-02-13 13:25:42 +00:00
|
|
|
retry:
|
|
|
|
moo_copybcstr (&bufptr[xlen], bufcapa - xlen, MOO_DEFAULT_PFMODPOSTFIX);
|
2015-10-14 13:25:36 +00:00
|
|
|
|
2017-02-13 13:25:42 +00:00
|
|
|
/* both prefix and postfix attached. for instance, libmoo-xxx */
|
2017-02-04 05:30:15 +00:00
|
|
|
handle = lt_dlopenext (bufptr);
|
2017-01-10 10:50:26 +00:00
|
|
|
if (!handle)
|
|
|
|
{
|
2017-02-04 05:30:15 +00:00
|
|
|
MOO_DEBUG3 (moo, "Failed to open(ext) DL %hs[%js] - %hs\n", bufptr, name, lt_dlerror());
|
2017-02-13 13:25:42 +00:00
|
|
|
|
|
|
|
/* try without prefix and postfix */
|
|
|
|
bufptr[xlen] = '\0';
|
2017-02-04 05:30:15 +00:00
|
|
|
handle = lt_dlopenext (&bufptr[len]);
|
2017-02-13 13:25:42 +00:00
|
|
|
if (!handle)
|
|
|
|
{
|
|
|
|
moo_bch_t* dash;
|
|
|
|
MOO_DEBUG3 (moo, "Failed to open(ext) DL %hs[%js] - %s\n", &bufptr[len], name, lt_dlerror());
|
|
|
|
dash = moo_rfindbchar (bufptr, moo_countbcstr(bufptr), '-');
|
|
|
|
if (dash)
|
|
|
|
{
|
|
|
|
/* remove a segment at the back.
|
|
|
|
* [NOTE] a dash contained in the original name before
|
|
|
|
* period-to-dash transformation may cause extraneous/wrong
|
|
|
|
* loading reattempts. */
|
|
|
|
xlen = dash - bufptr;
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
}
|
2017-02-04 05:30:15 +00:00
|
|
|
else MOO_DEBUG3 (moo, "Opened(ext) DL %hs[%js] handle %p\n", &bufptr[len], name, handle);
|
2017-01-10 10:50:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-04 05:30:15 +00:00
|
|
|
MOO_DEBUG3 (moo, "Opened(ext) DL %hs[%js] handle %p\n", bufptr, name, handle);
|
2017-01-10 10:50:26 +00:00
|
|
|
}
|
2016-08-23 00:37:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-04 05:30:15 +00:00
|
|
|
/* opening a raw shared object without a prefix and/or a postfix */
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-02-04 05:30:15 +00:00
|
|
|
bcslen = bufcapa;
|
|
|
|
moo_convootobcstr (moo, name, &ucslen, bufptr, &bcslen);
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
2017-02-04 05:30:15 +00:00
|
|
|
bcslen = moo_copybcstr (bufptr, bufcapa, name);
|
2017-02-03 06:28:12 +00:00
|
|
|
#endif
|
2017-01-10 13:56:19 +00:00
|
|
|
|
2017-02-04 05:30:15 +00:00
|
|
|
if (moo_findbchar (bufptr, bcslen, '.'))
|
2017-01-10 10:50:26 +00:00
|
|
|
{
|
2017-02-04 05:30:15 +00:00
|
|
|
handle = lt_dlopen (bufptr);
|
|
|
|
if (!handle) MOO_DEBUG2 (moo, "Failed to open DL %hs - %s\n", bufptr, lt_dlerror());
|
|
|
|
else MOO_DEBUG2 (moo, "Opened DL %hs handle %p\n", bufptr, handle);
|
2017-01-10 10:50:26 +00:00
|
|
|
}
|
2017-01-10 13:56:19 +00:00
|
|
|
else
|
|
|
|
{
|
2017-02-04 05:30:15 +00:00
|
|
|
handle = lt_dlopenext (bufptr);
|
|
|
|
if (!handle) MOO_DEBUG2 (moo, "Failed to open(ext) DL %hs - %s\n", bufptr, lt_dlerror());
|
|
|
|
else MOO_DEBUG2 (moo, "Opened(ext) DL %hs handle %p\n", bufptr, handle);
|
2017-01-10 13:56:19 +00:00
|
|
|
}
|
2015-10-14 13:25:36 +00:00
|
|
|
}
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
if (bufptr != stabuf) moo_freemem (moo, bufptr);
|
2015-10-14 13:25:36 +00:00
|
|
|
return handle;
|
|
|
|
|
|
|
|
#else
|
2017-03-19 14:18:37 +00:00
|
|
|
|
2017-02-04 05:30:15 +00:00
|
|
|
/* TODO: support various platforms */
|
2015-10-14 13:25:36 +00:00
|
|
|
/* TODO: implemenent this */
|
2017-02-04 05:30:15 +00:00
|
|
|
MOO_DEBUG1 (moo, "Dynamic loading not implemented - cannot open %js\n", name);
|
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
2017-01-09 09:54:49 +00:00
|
|
|
return MOO_NULL;
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static void dl_close (moo_t* moo, void* handle)
|
2015-10-13 14:51:04 +00:00
|
|
|
{
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
2017-02-04 05:30:15 +00:00
|
|
|
MOO_DEBUG1 (moo, "Closed DL handle %p\n", handle);
|
2015-10-14 13:25:36 +00:00
|
|
|
lt_dlclose (handle);
|
2017-02-09 08:05:14 +00:00
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
#else
|
2017-02-04 05:30:15 +00:00
|
|
|
/* TODO: implemenent this */
|
|
|
|
MOO_DEBUG1 (moo, "Dynamic loading not implemented - cannot close handle %p\n", handle);
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static void* dl_getsym (moo_t* moo, void* handle, const moo_ooch_t* name)
|
2015-10-13 14:51:04 +00:00
|
|
|
{
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
2017-02-09 08:05:14 +00:00
|
|
|
moo_bch_t stabuf[64], * bufptr;
|
2017-02-13 13:25:42 +00:00
|
|
|
moo_oow_t bufcapa, ucslen, bcslen, i;
|
2017-02-09 08:05:14 +00:00
|
|
|
const moo_bch_t* symname;
|
2015-10-13 14:51:04 +00:00
|
|
|
void* sym;
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
|
|
|
if (moo_convootobcstr (moo, name, &ucslen, MOO_NULL, &bcslen) <= -1) return MOO_NULL;
|
|
|
|
#else
|
|
|
|
bcslen = moo_countbcstr (name);
|
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
if (bcslen >= MOO_COUNTOF(stabuf) - 2)
|
|
|
|
{
|
|
|
|
bufcapa = bcslen + 3;
|
|
|
|
bufptr = moo_allocmem (moo, bufcapa * MOO_SIZEOF(*bufptr));
|
|
|
|
if (!bufptr) return MOO_NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bufcapa = MOO_COUNTOF(stabuf);
|
|
|
|
bufptr = stabuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
bcslen = bufcapa - 1;
|
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
|
|
|
moo_convootobcstr (moo, name, &ucslen, &bufptr[1], &bcslen);
|
|
|
|
#else
|
|
|
|
bcslen = moo_copybcstr (&bufptr[1], bcslen, name);
|
|
|
|
#endif
|
|
|
|
|
2017-02-13 13:25:42 +00:00
|
|
|
/* convert a period(.) to an underscore(_) */
|
|
|
|
for (i = 1; i <= bcslen; i++) if (bufptr[i] == '.') bufptr[i] = '_';
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
symname = &bufptr[1]; /* try the name as it is */
|
2016-08-23 00:37:22 +00:00
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
if (!sym)
|
|
|
|
{
|
2017-02-09 08:05:14 +00:00
|
|
|
bufptr[0] = '_';
|
|
|
|
symname = &bufptr[0]; /* try _name */
|
2016-08-23 00:37:22 +00:00
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
if (!sym)
|
|
|
|
{
|
2017-02-09 08:05:14 +00:00
|
|
|
bufptr[bcslen + 1] = '_';
|
|
|
|
bufptr[bcslen + 2] = '\0';
|
2016-08-23 00:37:22 +00:00
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
symname = &bufptr[1]; /* try name_ */
|
2016-08-23 00:37:22 +00:00
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
if (!sym)
|
|
|
|
{
|
2017-02-09 08:05:14 +00:00
|
|
|
symname = &bufptr[0]; /* try _name_ */
|
2016-08-23 00:37:22 +00:00
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
if (sym) MOO_DEBUG3 (moo, "Loaded module symbol %js from handle %p - %hs\n", name, handle, symname);
|
|
|
|
if (bufptr != stabuf) moo_freemem (moo, bufptr);
|
2015-10-13 14:51:04 +00:00
|
|
|
return sym;
|
2015-10-14 13:25:36 +00:00
|
|
|
#else
|
|
|
|
/* TODO: IMPLEMENT THIS */
|
2017-02-09 08:05:14 +00:00
|
|
|
MOO_DEBUG2 (moo, "Dynamic loading not implemented - Cannot load module symbol %js from handle %p\n", name, handle);
|
2017-02-03 06:28:12 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
2017-01-09 09:54:49 +00:00
|
|
|
return MOO_NULL;
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
2016-06-03 15:46:01 +00:00
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
#if defined(_WIN32)
|
2017-02-10 09:06:53 +00:00
|
|
|
/* nothing to do */
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
#elif defined(macintosh)
|
2017-02-10 09:06:53 +00:00
|
|
|
/* nothing to do */
|
2017-02-09 08:05:14 +00:00
|
|
|
|
|
|
|
#else
|
2017-01-09 09:54:49 +00:00
|
|
|
static int write_all (int fd, const char* ptr, moo_oow_t len)
|
2016-10-06 14:17:24 +00:00
|
|
|
{
|
|
|
|
while (len > 0)
|
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_ooi_t wr;
|
2016-10-06 14:17:24 +00:00
|
|
|
|
2017-03-09 13:39:59 +00:00
|
|
|
wr = write (fd, ptr, len);
|
2016-10-06 14:17:24 +00:00
|
|
|
|
|
|
|
if (wr <= -1)
|
|
|
|
{
|
2017-01-09 13:48:33 +00:00
|
|
|
#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK)
|
|
|
|
/* TODO: push it to internal buffers? before writing data just converted, need to write buffered data first. */
|
|
|
|
if (errno == EAGAIN) continue;
|
|
|
|
#else
|
|
|
|
|
2017-01-22 18:01:26 +00:00
|
|
|
#if defined(EAGAIN)
|
2017-01-09 13:48:33 +00:00
|
|
|
if (errno == EAGAIN) continue;
|
2017-01-22 18:01:26 +00:00
|
|
|
#endif
|
|
|
|
#if defined(EWOULDBLOCK)
|
2017-01-09 13:48:33 +00:00
|
|
|
if (errno == EWOULDBLOCK) continue;
|
2017-01-22 18:01:26 +00:00
|
|
|
#endif
|
2017-05-12 04:15:09 +00:00
|
|
|
#endif
|
2017-01-09 13:48:33 +00:00
|
|
|
|
2017-05-12 04:15:09 +00:00
|
|
|
#if defined(EINTR)
|
|
|
|
/* TODO: would this interfere with non-blocking nature of this VM? */
|
|
|
|
if (errno == EINTR) continue;
|
2017-01-09 13:48:33 +00:00
|
|
|
#endif
|
2016-10-06 14:17:24 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr += wr;
|
|
|
|
len -= wr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-02-09 08:05:14 +00:00
|
|
|
#endif
|
2016-10-06 14:17:24 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static void log_write (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len)
|
2016-05-27 15:01:54 +00:00
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
# error NOT IMPLEMENTED
|
|
|
|
|
2017-02-09 08:05:14 +00:00
|
|
|
#elif defined(macintosh)
|
|
|
|
# error NOT IMPLEMENTED
|
2016-05-27 15:01:54 +00:00
|
|
|
#else
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_bch_t buf[256];
|
|
|
|
moo_oow_t ucslen, bcslen, msgidx;
|
2016-05-27 15:01:54 +00:00
|
|
|
int n;
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
xtn_t* xtn = moo_getxtn(moo);
|
|
|
|
int logfd;
|
2016-06-13 15:52:09 +00:00
|
|
|
|
2017-11-23 15:45:25 +00:00
|
|
|
if (!(xtn->logmask & mask)) return;
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
if (mask & MOO_LOG_STDOUT) logfd = 1;
|
|
|
|
else if (mask & MOO_LOG_STDERR) logfd = 2;
|
|
|
|
else
|
2017-01-22 18:01:26 +00:00
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
logfd = xtn->logfd;
|
|
|
|
if (logfd <= -1) return;
|
2017-01-22 18:01:26 +00:00
|
|
|
}
|
2017-11-22 04:52:45 +00:00
|
|
|
|
|
|
|
/* TODO: beautify the log message.
|
|
|
|
* do classification based on mask. */
|
|
|
|
if (!(mask & (MOO_LOG_STDOUT | MOO_LOG_STDERR)))
|
|
|
|
{
|
|
|
|
time_t now;
|
|
|
|
char ts[32];
|
|
|
|
size_t tslen;
|
|
|
|
struct tm tm, *tmp;
|
|
|
|
|
|
|
|
now = time(NULL);
|
|
|
|
#if defined(__DOS__)
|
|
|
|
tmp = localtime (&now);
|
|
|
|
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S ", tmp); /* no timezone info */
|
|
|
|
if (tslen == 0)
|
|
|
|
{
|
|
|
|
strcpy (ts, "0000-00-00 00:00:00");
|
|
|
|
tslen = 19;
|
|
|
|
}
|
2017-04-28 23:25:21 +00:00
|
|
|
#else
|
2017-11-22 04:52:45 +00:00
|
|
|
tmp = localtime_r (&now, &tm);
|
|
|
|
#if defined(HAVE_STRFTIME_SMALL_Z)
|
|
|
|
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
|
|
|
|
if (tslen == 0)
|
|
|
|
{
|
|
|
|
strcpy (ts, "0000-00-00 00:00:00 +0000");
|
|
|
|
tslen = 25;
|
|
|
|
}
|
2017-04-28 14:57:00 +00:00
|
|
|
#endif
|
2017-11-22 04:52:45 +00:00
|
|
|
write_all (logfd, ts, tslen);
|
2016-10-06 17:50:27 +00:00
|
|
|
}
|
2016-10-06 14:17:24 +00:00
|
|
|
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2016-07-01 16:31:47 +00:00
|
|
|
msgidx = 0;
|
2016-06-01 15:33:03 +00:00
|
|
|
while (len > 0)
|
2016-05-27 15:01:54 +00:00
|
|
|
{
|
|
|
|
ucslen = len;
|
2017-01-09 09:54:49 +00:00
|
|
|
bcslen = MOO_COUNTOF(buf);
|
2016-05-27 15:01:54 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
n = moo_convootobchars (moo, &msg[msgidx], &ucslen, buf, &bcslen);
|
2016-07-01 16:31:47 +00:00
|
|
|
if (n == 0 || n == -2)
|
2016-05-27 15:01:54 +00:00
|
|
|
{
|
2016-07-01 16:31:47 +00:00
|
|
|
/* n = 0:
|
|
|
|
* converted all successfully
|
|
|
|
* n == -2:
|
|
|
|
* buffer not sufficient. not all got converted yet.
|
|
|
|
* write what have been converted this round. */
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
MOO_ASSERT (moo, ucslen > 0); /* if this fails, the buffer size must be increased */
|
2016-07-01 16:31:47 +00:00
|
|
|
|
|
|
|
/* attempt to write all converted characters */
|
2017-11-22 04:52:45 +00:00
|
|
|
if (write_all (logfd, buf, bcslen) <= -1) break;
|
2016-07-01 16:31:47 +00:00
|
|
|
|
|
|
|
if (n == 0) break;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msgidx += ucslen;
|
|
|
|
len -= ucslen;
|
|
|
|
}
|
2016-05-27 15:01:54 +00:00
|
|
|
}
|
|
|
|
else if (n <= -1)
|
|
|
|
{
|
|
|
|
/* conversion error */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
2017-11-22 04:52:45 +00:00
|
|
|
write_all (logfd, msg, len);
|
2017-02-03 06:28:12 +00:00
|
|
|
#endif
|
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-02-10 09:06:53 +00:00
|
|
|
/* ========================================================================= */
|
2017-05-07 12:43:52 +00:00
|
|
|
#if defined(USE_DEVPOLL) || defined(USE_POLL)
|
2017-09-27 14:03:05 +00:00
|
|
|
static MOO_INLINE int secure_poll_data_space (moo_t* moo, int fd)
|
2017-05-07 12:43:52 +00:00
|
|
|
{
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
if (fd >= xtn->epd.capa)
|
|
|
|
{
|
|
|
|
moo_oow_t newcapa;
|
|
|
|
moo_ooi_t* tmp;
|
|
|
|
|
|
|
|
newcapa = MOO_ALIGN_POW2 (fd + 1, 256);
|
|
|
|
tmp = moo_reallocmem (moo, xtn->epd.ptr, newcapa * MOO_SIZEOF(*tmp));
|
|
|
|
if (!tmp) return -1;
|
|
|
|
|
|
|
|
xtn->epd.capa = newcapa;
|
|
|
|
xtn->epd.ptr = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-09-27 14:03:05 +00:00
|
|
|
static MOO_INLINE void destroy_poll_data_space (moo_t* moo)
|
|
|
|
{
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
if (xtn->epd.ptr)
|
|
|
|
{
|
|
|
|
moo_freemem (moo, xtn->epd.ptr);
|
|
|
|
xtn->epd.ptr = MOO_NULL;
|
|
|
|
xtn->epd.capa = 0;
|
|
|
|
}
|
|
|
|
}
|
2017-05-07 12:43:52 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static int _add_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_data)
|
2017-05-07 10:23:21 +00:00
|
|
|
{
|
|
|
|
#if defined(USE_DEVPOLL)
|
2017-05-07 14:32:38 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-05-07 10:23:21 +00:00
|
|
|
struct pollfd ev;
|
2017-05-07 12:43:52 +00:00
|
|
|
|
|
|
|
if (secure_poll_data_space (moo, fd) <= -1) return -1;
|
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_ASSERT (moo, xtn->ep >= 0);
|
|
|
|
ev.fd = fd;
|
|
|
|
ev.events = event_mask;
|
|
|
|
ev.revents = 0;
|
|
|
|
if (write (xtn->ep, &ev, MOO_SIZEOF(ev)) != MOO_SIZEOF(ev))
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_DEBUG2 (moo, "Cannot add file descriptor %d to devpoll - %hs\n", fd, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
2017-06-27 13:47:58 +00:00
|
|
|
|
|
|
|
xtn->epd.ptr[fd] = event_data;
|
2017-05-07 14:32:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
2017-05-07 14:32:38 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-05-07 10:23:21 +00:00
|
|
|
struct epoll_event ev;
|
2017-05-07 12:43:52 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_ASSERT (moo, xtn->ep >= 0);
|
|
|
|
ev.events = event_mask;
|
2017-06-27 16:03:29 +00:00
|
|
|
#if defined(USE_THREAD) && defined(EPOLLET)
|
|
|
|
/* epoll_wait may return again if the worker thread consumes events.
|
|
|
|
* switch to level-trigger. */
|
|
|
|
/* TODO: verify if EPOLLLET is desired */
|
|
|
|
ev.events |= EPOLLET;
|
|
|
|
#endif
|
2017-05-07 12:43:52 +00:00
|
|
|
ev.data.ptr = (void*)event_data;
|
2017-05-07 10:23:21 +00:00
|
|
|
if (epoll_ctl (xtn->ep, EPOLL_CTL_ADD, fd, &ev) == -1)
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_DEBUG2 (moo, "Cannot add file descriptor %d to epoll - %hs\n", fd, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
2017-05-07 14:32:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
#elif defined(USE_POLL)
|
2017-05-07 14:32:38 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-05-07 12:43:52 +00:00
|
|
|
|
|
|
|
if (secure_poll_data_space (moo, fd) <= -1) return -1;
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_LOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
if (xtn->ev.reg.len >= xtn->ev.reg.capa)
|
|
|
|
{
|
2017-05-07 14:32:38 +00:00
|
|
|
struct pollfd* tmp, * tmp2;
|
2017-05-07 10:23:21 +00:00
|
|
|
moo_oow_t newcapa;
|
|
|
|
|
|
|
|
newcapa = MOO_ALIGN_POW2 (xtn->ev.reg.len + 1, 256);
|
|
|
|
tmp = (struct pollfd*)moo_reallocmem (moo, xtn->ev.reg.ptr, newcapa * MOO_SIZEOF(*tmp));
|
2017-05-07 14:32:38 +00:00
|
|
|
tmp2 = (struct pollfd*)moo_reallocmem (moo, xtn->ev.buf, newcapa * MOO_SIZEOF(*tmp2));
|
|
|
|
if (!tmp || !tmp2)
|
2017-05-07 10:23:21 +00:00
|
|
|
{
|
2017-05-07 12:43:52 +00:00
|
|
|
MOO_DEBUG2 (moo, "Cannot add file descriptor %d to poll - %hs\n", fd, strerror(errno));
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 14:32:38 +00:00
|
|
|
if (tmp) moo_freemem (moo, tmp);
|
2017-05-07 10:23:21 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->ev.reg.ptr = tmp;
|
|
|
|
xtn->ev.reg.capa = newcapa;
|
2017-05-07 14:32:38 +00:00
|
|
|
|
|
|
|
xtn->ev.buf = tmp2;
|
2017-05-07 10:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
xtn->ev.reg.ptr[xtn->ev.reg.len].fd = fd;
|
|
|
|
xtn->ev.reg.ptr[xtn->ev.reg.len].events = event_mask;
|
|
|
|
xtn->ev.reg.ptr[xtn->ev.reg.len].revents = 0;
|
|
|
|
xtn->ev.reg.len++;
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
|
2017-06-27 13:47:58 +00:00
|
|
|
xtn->epd.ptr[fd] = event_data;
|
2017-05-07 14:32:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-09-27 14:03:05 +00:00
|
|
|
|
|
|
|
MUTEX_LOCK (&xtn->ev.reg.smtx);
|
2017-09-27 01:03:18 +00:00
|
|
|
if (event_mask & XPOLLIN)
|
|
|
|
{
|
|
|
|
FD_SET (fd, &xtn->ev.reg.rfds);
|
|
|
|
if (fd > xtn->ev.reg.maxfd) xtn->ev.reg.maxfd = fd;
|
|
|
|
}
|
|
|
|
if (event_mask & XPOLLOUT)
|
|
|
|
{
|
|
|
|
FD_SET (fd, &xtn->ev.reg.wfds);
|
|
|
|
if (fd > xtn->ev.reg.maxfd) xtn->ev.reg.maxfd = fd;
|
|
|
|
}
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.smtx);
|
2017-09-27 06:48:01 +00:00
|
|
|
|
|
|
|
xtn->epd.data[fd] = (void*)event_data;
|
|
|
|
return 0;
|
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
#else
|
2017-06-08 14:39:17 +00:00
|
|
|
|
|
|
|
MOO_DEBUG1 (moo, "Cannot add file descriptor %d to poll - not implemented\n", fd);
|
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
|
|
|
return -1;
|
2017-05-07 10:23:21 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int _del_poll_fd (moo_t* moo, int fd)
|
|
|
|
{
|
|
|
|
|
|
|
|
#if defined(USE_DEVPOLL)
|
2017-05-07 14:32:38 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-05-07 10:23:21 +00:00
|
|
|
struct pollfd ev;
|
2017-05-07 14:32:38 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_ASSERT (moo, xtn->ep >= 0);
|
|
|
|
ev.fd = fd;
|
|
|
|
ev.events = POLLREMOVE;
|
|
|
|
ev.revents = 0;
|
|
|
|
if (write (xtn->ep, &ev, MOO_SIZEOF(ev)) != MOO_SIZEOF(ev))
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_DEBUG2 (moo, "Cannot remove file descriptor %d from devpoll - %hs\n", fd, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-05-07 14:32:38 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
2017-05-07 14:32:38 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-05-07 10:23:21 +00:00
|
|
|
struct epoll_event ev;
|
2017-05-07 14:32:38 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_ASSERT (moo, xtn->ep >= 0);
|
2017-05-07 14:32:38 +00:00
|
|
|
memset (&ev, 0, MOO_SIZEOF(ev));
|
2017-05-07 10:23:21 +00:00
|
|
|
if (epoll_ctl (xtn->ep, EPOLL_CTL_DEL, fd, &ev) == -1)
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-05-07 10:23:21 +00:00
|
|
|
MOO_DEBUG2 (moo, "Cannot remove file descriptor %d from epoll - %hs\n", fd, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
2017-05-07 14:32:38 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
#elif defined(USE_POLL)
|
2017-05-07 14:32:38 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-05-07 10:23:21 +00:00
|
|
|
moo_oow_t i;
|
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
/* TODO: performance boost. no linear search */
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_LOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
for (i = 0; i < xtn->ev.reg.len; i++)
|
|
|
|
{
|
|
|
|
if (xtn->ev.reg.ptr[i].fd == fd)
|
|
|
|
{
|
|
|
|
xtn->ev.reg.len--;
|
2017-05-07 14:32:38 +00:00
|
|
|
memmove (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i) * MOO_SIZEOF(*xtn->ev.reg.ptr));
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-09-27 01:03:18 +00:00
|
|
|
}
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
MOO_DEBUG1 (moo, "Cannot remove file descriptor %d from poll - not found\n", fd);
|
2017-06-08 14:39:17 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOENT);
|
2017-05-07 10:23:21 +00:00
|
|
|
return -1;
|
2017-06-08 14:39:17 +00:00
|
|
|
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_LOCK (&xtn->ev.reg.smtx);
|
2017-09-27 01:03:18 +00:00
|
|
|
FD_CLR (fd, &xtn->ev.reg.rfds);
|
|
|
|
FD_CLR (fd, &xtn->ev.reg.wfds);
|
2017-09-27 14:03:05 +00:00
|
|
|
if (fd >= xtn->ev.reg.maxfd)
|
2017-09-27 01:03:18 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
/* TODO: any way to make this search faster or to do without the search like this */
|
2017-09-27 14:03:05 +00:00
|
|
|
for (i = fd - 1; i >= 0; i--)
|
2017-09-27 01:03:18 +00:00
|
|
|
{
|
|
|
|
if (FD_ISSET(i, &xtn->ev.reg.rfds) || FD_ISSET(i, &xtn->ev.reg.wfds)) break;
|
|
|
|
}
|
|
|
|
xtn->ev.reg.maxfd = i;
|
|
|
|
}
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.smtx);
|
|
|
|
|
|
|
|
/* keep xtn->epd.data[fd] so that the data is still accessible after deletion */
|
2017-09-27 06:48:01 +00:00
|
|
|
return 0;
|
2017-09-27 01:03:18 +00:00
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
#else
|
2017-06-08 14:39:17 +00:00
|
|
|
|
|
|
|
MOO_DEBUG1 (moo, "Cannot remove file descriptor %d from poll - not implemented\n", fd);
|
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
|
|
|
return -1;
|
2017-05-07 10:23:21 +00:00
|
|
|
#endif
|
|
|
|
}
|
2017-02-10 09:06:53 +00:00
|
|
|
|
2017-05-07 12:43:52 +00:00
|
|
|
|
|
|
|
static int _mod_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_data)
|
|
|
|
{
|
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
|
|
|
|
if (_del_poll_fd (moo, fd) <= -1) return -1;
|
|
|
|
|
|
|
|
if (_add_poll_fd (moo, fd, event_mask, event_data) <= -1)
|
|
|
|
{
|
|
|
|
/* TODO: any good way to rollback successful deletion? */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#elif defined(USE_EPOLL)
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
struct epoll_event ev;
|
|
|
|
|
|
|
|
MOO_ASSERT (moo, xtn->ep >= 0);
|
|
|
|
ev.events = event_mask;
|
|
|
|
ev.data.ptr = (void*)event_data;
|
|
|
|
if (epoll_ctl (xtn->ep, EPOLL_CTL_MOD, fd, &ev) == -1)
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-05-07 12:43:52 +00:00
|
|
|
MOO_DEBUG2 (moo, "Cannot modify file descriptor %d in epoll - %hs\n", fd, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
2017-05-07 14:32:38 +00:00
|
|
|
|
|
|
|
return 0;
|
2017-09-27 06:48:01 +00:00
|
|
|
|
2017-05-07 12:43:52 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
moo_oow_t i;
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_LOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 12:43:52 +00:00
|
|
|
for (i = 0; i < xtn->ev.reg.len; i++)
|
|
|
|
{
|
|
|
|
if (xtn->ev.reg.ptr[i].fd == fd)
|
|
|
|
{
|
|
|
|
memmove (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i - 1) * MOO_SIZEOF(*xtn->ev.reg.ptr));
|
|
|
|
xtn->ev.reg.ptr[i].fd = fd;
|
|
|
|
xtn->ev.reg.ptr[i].events = event_mask;
|
|
|
|
xtn->ev.reg.ptr[i].revents = 0;
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
2017-09-27 06:48:01 +00:00
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
MOO_ASSERT (moo, fd < xtn->epd.capa);
|
2017-09-27 06:48:01 +00:00
|
|
|
xtn->epd.ptr[fd] = event_data;
|
2017-05-07 12:43:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
2017-05-07 12:43:52 +00:00
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
MOO_DEBUG1 (moo, "Cannot modify file descriptor %d in poll - not found\n", fd);
|
2017-05-07 12:43:52 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOENT);
|
|
|
|
return -1;
|
|
|
|
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_LOCK (&xtn->ev.reg.smtx);
|
2017-09-27 01:03:18 +00:00
|
|
|
MOO_ASSERT (moo, fd <= xtn->ev.reg.maxfd);
|
|
|
|
|
|
|
|
if (event_mask & XPOLLIN)
|
|
|
|
FD_SET (fd, &xtn->ev.reg.rfds);
|
|
|
|
else
|
|
|
|
FD_CLR (fd, &xtn->ev.reg.rfds);
|
|
|
|
|
|
|
|
if (event_mask & XPOLLOUT)
|
|
|
|
FD_SET (fd, &xtn->ev.reg.wfds);
|
|
|
|
else
|
|
|
|
FD_CLR (fd, &xtn->ev.reg.wfds);
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.smtx);
|
2017-09-27 01:03:18 +00:00
|
|
|
|
2017-09-27 06:48:01 +00:00
|
|
|
xtn->epd.data[fd] = (void*)event_data;
|
|
|
|
return 0;
|
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
#else
|
2017-06-08 14:39:17 +00:00
|
|
|
MOO_DEBUG1 (moo, "Cannot modify file descriptor %d in poll - not implemented\n", fd);
|
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
|
|
|
return -1;
|
2017-05-07 12:43:52 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-12 18:59:03 +00:00
|
|
|
static int vm_startup (moo_t* moo)
|
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
xtn->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL);
|
|
|
|
|
|
|
|
#else
|
2017-05-07 10:23:21 +00:00
|
|
|
|
2017-02-12 18:59:03 +00:00
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
2017-02-21 19:20:27 +00:00
|
|
|
int pcount = 0, flag;
|
2017-02-12 18:59:03 +00:00
|
|
|
|
2017-04-28 14:45:13 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
xtn->ep = open ("/dev/poll", O_RDWR);
|
|
|
|
if (xtn->ep == -1)
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-04-28 14:45:13 +00:00
|
|
|
MOO_DEBUG1 (moo, "Cannot create devpoll - %hs\n", strerror(errno));
|
|
|
|
goto oops;
|
|
|
|
}
|
2017-05-07 10:23:21 +00:00
|
|
|
|
|
|
|
flag = fcntl (xtn->ep, F_GETFD);
|
|
|
|
if (flag >= 0) fcntl (xtn->ep, F_SETFD, flag | FD_CLOEXEC);
|
|
|
|
|
|
|
|
#elif defined(USE_EPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
#if defined(EPOLL_CLOEXEC)
|
|
|
|
xtn->ep = epoll_create1 (EPOLL_CLOEXEC);
|
|
|
|
#else
|
2017-02-21 19:51:10 +00:00
|
|
|
xtn->ep = epoll_create (1024);
|
2017-04-28 14:45:13 +00:00
|
|
|
#endif
|
2017-02-12 18:59:03 +00:00
|
|
|
if (xtn->ep == -1)
|
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-02-21 19:20:27 +00:00
|
|
|
MOO_DEBUG1 (moo, "Cannot create epoll - %hs\n", strerror(errno));
|
|
|
|
goto oops;
|
|
|
|
}
|
2017-04-28 14:45:13 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
#if defined(EPOLL_CLOEXEC)
|
2017-02-21 19:51:10 +00:00
|
|
|
/* do nothing */
|
2017-05-07 10:23:21 +00:00
|
|
|
#else
|
2017-02-21 19:51:10 +00:00
|
|
|
flag = fcntl (xtn->ep, F_GETFD);
|
|
|
|
if (flag >= 0) fcntl (xtn->ep, F_SETFD, flag | FD_CLOEXEC);
|
2017-05-07 10:23:21 +00:00
|
|
|
#endif
|
2017-09-27 14:03:05 +00:00
|
|
|
|
|
|
|
#elif defined(USE_POLL)
|
|
|
|
|
|
|
|
MUTEX_INIT (&xtn->ev.reg.pmtx);
|
|
|
|
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2017-09-27 06:48:01 +00:00
|
|
|
FD_ZERO (&xtn->ev.reg.rfds);
|
|
|
|
FD_ZERO (&xtn->ev.reg.wfds);
|
2017-09-27 01:03:18 +00:00
|
|
|
xtn->ev.reg.maxfd = -1;
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_INIT (&xtn->ev.reg.smtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
#endif /* USE_DEVPOLL */
|
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
#if defined(USE_THREAD)
|
2017-09-27 14:03:05 +00:00
|
|
|
if (pipe(xtn->p) == -1)
|
2017-02-21 19:20:27 +00:00
|
|
|
{
|
2017-10-18 16:15:51 +00:00
|
|
|
moo_syserr_to_errnum (errno);
|
2017-02-21 19:20:27 +00:00
|
|
|
MOO_DEBUG1 (moo, "Cannot create pipes - %hs\n", strerror(errno));
|
2017-02-12 18:59:03 +00:00
|
|
|
goto oops;
|
|
|
|
}
|
2017-02-21 19:20:27 +00:00
|
|
|
pcount = 2;
|
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
#if defined(O_CLOEXEC)
|
2017-02-21 19:20:27 +00:00
|
|
|
flag = fcntl (xtn->p[0], F_GETFD);
|
|
|
|
if (flag >= 0) fcntl (xtn->p[0], F_SETFD, flag | FD_CLOEXEC);
|
|
|
|
flag = fcntl (xtn->p[1], F_GETFD);
|
|
|
|
if (flag >= 0) fcntl (xtn->p[1], F_SETFD, flag | FD_CLOEXEC);
|
2017-06-23 16:09:07 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(O_NONBLOCK)
|
2017-02-21 19:20:27 +00:00
|
|
|
flag = fcntl (xtn->p[0], F_GETFL);
|
|
|
|
if (flag >= 0) fcntl (xtn->p[0], F_SETFL, flag | O_NONBLOCK);
|
|
|
|
flag = fcntl (xtn->p[1], F_GETFL);
|
|
|
|
if (flag >= 0) fcntl (xtn->p[1], F_SETFL, flag | O_NONBLOCK);
|
2017-06-23 16:09:07 +00:00
|
|
|
#endif
|
2017-02-21 19:20:27 +00:00
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
if (_add_poll_fd(moo, xtn->p[0], XPOLLIN, MOO_TYPE_MAX(moo_oow_t)) <= -1) goto oops;
|
2017-02-21 19:20:27 +00:00
|
|
|
|
|
|
|
pthread_mutex_init (&xtn->ev.mtx, MOO_NULL);
|
|
|
|
pthread_cond_init (&xtn->ev.cnd, MOO_NULL);
|
|
|
|
pthread_cond_init (&xtn->ev.cnd2, MOO_NULL);
|
2017-02-22 09:48:58 +00:00
|
|
|
|
|
|
|
xtn->iothr_abort = 0;
|
2017-03-04 05:48:23 +00:00
|
|
|
xtn->iothr_up = 0;
|
|
|
|
/*pthread_create (&xtn->iothr, MOO_NULL, iothr_main, moo);*/
|
2017-02-12 18:59:03 +00:00
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
|
|
|
|
#endif /* USE_THREAD */
|
|
|
|
|
|
|
|
xtn->vm_running = 1;
|
2017-02-12 18:59:03 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
oops:
|
2017-02-21 19:51:10 +00:00
|
|
|
|
|
|
|
#if defined(USE_THREAD)
|
2017-05-07 10:23:21 +00:00
|
|
|
if (pcount > 0)
|
2017-02-21 19:20:27 +00:00
|
|
|
{
|
|
|
|
close (xtn->p[0]);
|
|
|
|
close (xtn->p[1]);
|
|
|
|
}
|
2017-02-21 19:51:10 +00:00
|
|
|
#endif
|
2017-05-07 10:23:21 +00:00
|
|
|
|
|
|
|
#if defined(USE_DEVPOLL) || defined(USE_EPOLL)
|
2017-02-12 18:59:03 +00:00
|
|
|
if (xtn->ep >= 0)
|
|
|
|
{
|
|
|
|
close (xtn->ep);
|
|
|
|
xtn->ep = -1;
|
|
|
|
}
|
2017-05-07 10:23:21 +00:00
|
|
|
#endif
|
2017-02-12 18:59:03 +00:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vm_cleanup (moo_t* moo)
|
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
if (xtn->waitable_timer)
|
|
|
|
{
|
|
|
|
CloseHandle (xtn->waitable_timer);
|
|
|
|
xtn->waitable_timer = MOO_NULL;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
xtn->vm_running = 0;
|
2017-03-09 13:39:59 +00:00
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
#if defined(USE_THREAD)
|
2017-03-04 05:48:23 +00:00
|
|
|
if (xtn->iothr_up)
|
|
|
|
{
|
2017-03-09 13:39:59 +00:00
|
|
|
xtn->iothr_abort = 1;
|
2017-03-04 05:48:23 +00:00
|
|
|
write (xtn->p[1], "Q", 1);
|
|
|
|
pthread_cond_signal (&xtn->ev.cnd);
|
|
|
|
pthread_join (xtn->iothr, MOO_NULL);
|
|
|
|
xtn->iothr_up = 0;
|
|
|
|
}
|
2017-02-21 19:20:27 +00:00
|
|
|
pthread_cond_destroy (&xtn->ev.cnd);
|
|
|
|
pthread_cond_destroy (&xtn->ev.cnd2);
|
|
|
|
pthread_mutex_destroy (&xtn->ev.mtx);
|
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
_del_poll_fd (moo, xtn->p[0]);
|
2017-05-07 10:23:21 +00:00
|
|
|
close (xtn->p[1]);
|
|
|
|
close (xtn->p[0]);
|
|
|
|
#endif /* USE_THREAD */
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
if (xtn->ep >= 0)
|
|
|
|
{
|
|
|
|
close (xtn->ep);
|
|
|
|
xtn->ep = -1;
|
|
|
|
}
|
|
|
|
destroy_poll_data_space (moo);
|
|
|
|
#elif defined(USE_EPOLL)
|
|
|
|
if (xtn->ep >= 0)
|
2017-02-12 18:59:03 +00:00
|
|
|
{
|
|
|
|
close (xtn->ep);
|
|
|
|
xtn->ep = -1;
|
|
|
|
}
|
2017-05-07 14:32:38 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
if (xtn->ev.reg.ptr)
|
|
|
|
{
|
|
|
|
moo_freemem (moo, xtn->ev.reg.ptr);
|
|
|
|
xtn->ev.reg.ptr = MOO_NULL;
|
|
|
|
xtn->ev.reg.len = 0;
|
|
|
|
xtn->ev.reg.capa = 0;
|
|
|
|
}
|
|
|
|
if (xtn->ev.buf)
|
|
|
|
{
|
|
|
|
moo_freemem (moo, xtn->ev.buf);
|
|
|
|
xtn->ev.buf = MOO_NULL;
|
|
|
|
}
|
2017-09-27 14:03:05 +00:00
|
|
|
destroy_poll_data_space (moo);
|
|
|
|
MUTEX_DESTROY (&xtn->ev.reg.pmtx);
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2017-09-27 06:48:01 +00:00
|
|
|
FD_ZERO (&xtn->ev.reg.rfds);
|
|
|
|
FD_ZERO (&xtn->ev.reg.wfds);
|
2017-09-27 01:03:18 +00:00
|
|
|
xtn->ev.reg.maxfd = -1;
|
2017-09-27 14:03:05 +00:00
|
|
|
MUTEX_DESTROY (&xtn->ev.reg.smtx);
|
2017-05-07 10:23:21 +00:00
|
|
|
#endif
|
2017-04-28 14:45:13 +00:00
|
|
|
|
2017-02-12 18:59:03 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-02-10 09:06:53 +00:00
|
|
|
static void vm_gettime (moo_t* moo, moo_ntime_t* now)
|
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
/* TODO: */
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
ULONG out;
|
|
|
|
|
|
|
|
/* TODO: handle overflow?? */
|
|
|
|
/* TODO: use DosTmrQueryTime() and DosTmrQueryFreq()? */
|
|
|
|
DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &out, MOO_SIZEOF(out)); /* milliseconds */
|
|
|
|
/* it must return NO_ERROR */
|
|
|
|
MOO_INITNTIME (now, MOO_MSEC_TO_SEC(out), MOO_MSEC_TO_NSEC(out));
|
|
|
|
#elif defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
|
|
|
|
clock_t c;
|
|
|
|
|
|
|
|
/* TODO: handle overflow?? */
|
|
|
|
c = clock ();
|
|
|
|
now->sec = c / CLOCKS_PER_SEC;
|
|
|
|
#if (CLOCKS_PER_SEC == 100)
|
|
|
|
now->nsec = MOO_MSEC_TO_NSEC((c % CLOCKS_PER_SEC) * 10);
|
|
|
|
#elif (CLOCKS_PER_SEC == 1000)
|
|
|
|
now->nsec = MOO_MSEC_TO_NSEC(c % CLOCKS_PER_SEC);
|
|
|
|
#elif (CLOCKS_PER_SEC == 1000000L)
|
|
|
|
now->nsec = MOO_USEC_TO_NSEC(c % CLOCKS_PER_SEC);
|
|
|
|
#elif (CLOCKS_PER_SEC == 1000000000L)
|
|
|
|
now->nsec = (c % CLOCKS_PER_SEC);
|
|
|
|
#else
|
|
|
|
# error UNSUPPORTED CLOCKS_PER_SEC
|
|
|
|
#endif
|
|
|
|
#elif defined(macintosh)
|
|
|
|
UnsignedWide tick;
|
|
|
|
moo_uint64_t tick64;
|
|
|
|
Microseconds (&tick);
|
|
|
|
tick64 = *(moo_uint64_t*)&tick;
|
|
|
|
MOO_INITNTIME (now, MOO_USEC_TO_SEC(tick64), MOO_USEC_TO_NSEC(tick64));
|
|
|
|
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
|
|
|
struct timespec ts;
|
|
|
|
clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
|
|
MOO_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
|
|
|
|
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
|
|
|
struct timespec ts;
|
|
|
|
clock_gettime (CLOCK_REALTIME, &ts);
|
|
|
|
MOO_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
|
|
|
|
#else
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday (&tv, MOO_NULL);
|
|
|
|
MOO_INITNTIME(now, tv.tv_sec, MOO_USEC_TO_NSEC(tv.tv_usec));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__DOS__)
|
|
|
|
# if defined(_INTELC32_)
|
|
|
|
void _halt_cpu (void);
|
|
|
|
# elif defined(__WATCOMC__)
|
|
|
|
void _halt_cpu (void);
|
|
|
|
# pragma aux _halt_cpu = "hlt"
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2017-04-28 14:45:13 +00:00
|
|
|
|
2017-05-07 12:43:52 +00:00
|
|
|
static int vm_muxadd (moo_t* moo, moo_oop_semaphore_t sem)
|
2017-02-10 09:06:53 +00:00
|
|
|
{
|
2017-02-15 11:57:24 +00:00
|
|
|
moo_ooi_t mask;
|
2017-05-07 10:23:21 +00:00
|
|
|
int event_mask;
|
2017-02-12 18:59:03 +00:00
|
|
|
|
2017-02-15 11:57:24 +00:00
|
|
|
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_index));
|
|
|
|
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_handle));
|
|
|
|
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_mask));
|
2017-02-12 18:59:03 +00:00
|
|
|
|
2017-02-15 11:57:24 +00:00
|
|
|
mask = MOO_OOP_TO_SMOOI(sem->io_mask);
|
2017-05-07 10:23:21 +00:00
|
|
|
event_mask = 0; /*EPOLLET; */ /* TODO: use edge trigger(EPOLLLET)? */
|
|
|
|
if (mask & MOO_SEMAPHORE_IO_MASK_INPUT) event_mask |= XPOLLIN;
|
|
|
|
if (mask & MOO_SEMAPHORE_IO_MASK_OUTPUT) event_mask |= XPOLLOUT;
|
2017-02-15 11:57:24 +00:00
|
|
|
|
2017-05-07 10:23:21 +00:00
|
|
|
if (event_mask == 0)
|
2017-02-12 18:59:03 +00:00
|
|
|
{
|
2017-02-22 09:48:58 +00:00
|
|
|
MOO_DEBUG2 (moo, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, MOO_OOP_TO_SMOOI(sem->io_handle));
|
2017-02-15 11:57:24 +00:00
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-04-28 14:45:13 +00:00
|
|
|
|
2017-05-07 12:43:52 +00:00
|
|
|
return _add_poll_fd (moo, MOO_OOP_TO_SMOOI(sem->io_handle), event_mask, MOO_OOP_TO_SMOOI(sem->io_index));
|
2017-04-08 07:23:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int vm_muxmod (moo_t* moo, moo_oop_semaphore_t sem)
|
|
|
|
{
|
2017-05-07 12:43:52 +00:00
|
|
|
moo_ooi_t mask;
|
|
|
|
int event_mask;
|
2017-02-15 11:57:24 +00:00
|
|
|
|
|
|
|
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_index));
|
|
|
|
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_handle));
|
|
|
|
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_mask));
|
|
|
|
|
2017-05-07 12:43:52 +00:00
|
|
|
mask = MOO_OOP_TO_SMOOI(sem->io_mask);
|
|
|
|
event_mask = 0; /*EPOLLET; */ /* TODO: use edge trigger(EPOLLLET)? */
|
|
|
|
if (mask & MOO_SEMAPHORE_IO_MASK_INPUT) event_mask |= XPOLLIN;
|
|
|
|
if (mask & MOO_SEMAPHORE_IO_MASK_OUTPUT) event_mask |= XPOLLOUT;
|
|
|
|
|
|
|
|
if (event_mask == 0)
|
2017-04-08 07:23:31 +00:00
|
|
|
{
|
2017-05-07 12:43:52 +00:00
|
|
|
MOO_DEBUG2 (moo, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, MOO_OOP_TO_SMOOI(sem->io_handle));
|
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
2017-04-08 07:23:31 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-05-07 12:43:52 +00:00
|
|
|
return _mod_poll_fd (moo, MOO_OOP_TO_SMOOI(sem->io_handle), event_mask, MOO_OOP_TO_SMOOI(sem->io_index));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int vm_muxdel (moo_t* moo, moo_oop_semaphore_t sem)
|
|
|
|
{
|
|
|
|
return _del_poll_fd (moo, MOO_OOP_TO_SMOOI(sem->io_handle));
|
2017-02-12 18:59:03 +00:00
|
|
|
}
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_THREAD)
|
|
|
|
static void* iothr_main (void* arg)
|
|
|
|
{
|
|
|
|
moo_t* moo = (moo_t*)arg;
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
|
|
|
|
/*while (!moo->abort_req)*/
|
|
|
|
while (!xtn->iothr_abort)
|
|
|
|
{
|
|
|
|
if (xtn->ev.len <= 0) /* TODO: no mutex needed for this check? */
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
struct dvpoll dvp;
|
|
|
|
#elif defined(USE_POLL)
|
|
|
|
moo_oow_t nfds;
|
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
struct timeval tv;
|
|
|
|
fd_set rfds;
|
|
|
|
fd_set wfds;
|
|
|
|
int maxfd;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
poll_for_event:
|
|
|
|
|
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
dvp.dp_timeout = 10000; /* milliseconds */
|
|
|
|
dvp.dp_fds = xtn->ev.buf;
|
|
|
|
dvp.dp_nfds = MOO_COUNTOF(xtn->ev.buf);
|
|
|
|
n = ioctl (xtn->ep, DP_POLL, &dvp);
|
|
|
|
#elif defined(USE_EPOLL)
|
|
|
|
n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), 10000);
|
|
|
|
#elif defined(USE_POLL)
|
|
|
|
MUTEX_LOCK (&xtn->ev.reg.pmtx);
|
|
|
|
memcpy (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf));
|
|
|
|
nfds = xtn->ev.reg.len;
|
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
|
|
|
|
n = poll (xtn->ev.buf, nfds, 10000);
|
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
/* compact the return buffer as poll() doesn't */
|
|
|
|
moo_oow_t i, j;
|
|
|
|
for (i = 0, j = 0; i < nfds && j < n; i++)
|
|
|
|
{
|
|
|
|
if (xtn->ev.buf[i].revents)
|
|
|
|
{
|
|
|
|
if (j != i) xtn->ev.buf[j] = xtn->ev.buf[i];
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
n = j;
|
|
|
|
}
|
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
tv.tv_sec = 10;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
MUTEX_LOCK (&xtn->ev.reg.smtx);
|
|
|
|
maxfd = xtn->ev.reg.maxfd;
|
|
|
|
MOO_MEMCPY (&rfds, &xtn->ev.reg.rfds, MOO_SIZEOF(rfds));
|
|
|
|
MOO_MEMCPY (&wfds, &xtn->ev.reg.wfds, MOO_SIZEOF(wfds));
|
|
|
|
MUTEX_UNLOCK (&xtn->ev.reg.smtx);
|
|
|
|
n = select (maxfd + 1, &rfds, &wfds, NULL, &tv);
|
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
int fd, count = 0;
|
|
|
|
for (fd = 0; fd <= maxfd; fd++)
|
|
|
|
{
|
|
|
|
int events = 0;
|
|
|
|
if (FD_ISSET(fd, &rfds)) events |= XPOLLIN;
|
|
|
|
if (FD_ISSET(fd, &wfds)) events |= XPOLLOUT;
|
|
|
|
|
|
|
|
if (events)
|
|
|
|
{
|
|
|
|
MOO_ASSERT (moo, count < MOO_COUNTOF(xtn->ev.buf));
|
|
|
|
xtn->ev.buf[count].fd = fd;
|
|
|
|
xtn->ev.buf[count].events = events;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
n = count;
|
|
|
|
MOO_ASSERT (moo, n > 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pthread_mutex_lock (&xtn->ev.mtx);
|
|
|
|
if (n <= -1)
|
|
|
|
{
|
|
|
|
/* TODO: don't use MOO_DEBUG2. it's not thread safe... */
|
|
|
|
/* the following call has a race-condition issue when called in this separate thread */
|
|
|
|
/*MOO_DEBUG2 (moo, "Warning: multiplexer wait failure - %d, %hs\n", errno, strerror(errno));*/
|
|
|
|
}
|
|
|
|
else if (n > 0)
|
|
|
|
{
|
|
|
|
xtn->ev.len = n;
|
|
|
|
}
|
|
|
|
pthread_cond_signal (&xtn->ev.cnd2);
|
|
|
|
pthread_mutex_unlock (&xtn->ev.mtx);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* the event buffer has not been emptied yet */
|
|
|
|
struct timespec ts;
|
|
|
|
|
|
|
|
pthread_mutex_lock (&xtn->ev.mtx);
|
|
|
|
if (xtn->ev.len <= 0)
|
|
|
|
{
|
|
|
|
/* it got emptied between the if check and pthread_mutex_lock() above */
|
|
|
|
pthread_mutex_unlock (&xtn->ev.mtx);
|
|
|
|
goto poll_for_event;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
|
|
|
clock_gettime (CLOCK_REALTIME, &ts);
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday (&tv, MOO_NULL);
|
|
|
|
ts.tv_sec = tv.tv_sec;
|
|
|
|
ts.tv_nsec = MOO_USEC_TO_NSEC(tv.tv_usec);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
ts.tv_sec += 10;
|
|
|
|
pthread_cond_timedwait (&xtn->ev.cnd, &xtn->ev.mtx, &ts);
|
|
|
|
pthread_mutex_unlock (&xtn->ev.mtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*sched_yield ();*/
|
|
|
|
}
|
|
|
|
|
|
|
|
return MOO_NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-02-22 09:48:58 +00:00
|
|
|
static void vm_muxwait (moo_t* moo, const moo_ntime_t* dur, moo_vmprim_muxwait_cb_t muxwcb)
|
2017-02-12 18:59:03 +00:00
|
|
|
{
|
|
|
|
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
#if defined(USE_THREAD)
|
2017-02-22 09:48:58 +00:00
|
|
|
int n;
|
2017-02-15 11:57:24 +00:00
|
|
|
|
2017-03-04 05:48:23 +00:00
|
|
|
/* create a thread if mux wait is started at least once. */
|
|
|
|
if (!xtn->iothr_up)
|
|
|
|
{
|
|
|
|
xtn->iothr_up = 1;
|
|
|
|
if (pthread_create (&xtn->iothr, MOO_NULL, iothr_main, moo) != 0)
|
|
|
|
{
|
|
|
|
MOO_LOG2 (moo, MOO_LOG_WARN, "Warning: pthread_create failure - %d, %hs\n", errno, strerror(errno));
|
|
|
|
xtn->iothr_up = 0;
|
|
|
|
/* TODO: switch to the non-threaded mode? */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-21 19:20:27 +00:00
|
|
|
if (xtn->ev.len <= 0)
|
2017-02-10 09:06:53 +00:00
|
|
|
{
|
2017-02-22 09:48:58 +00:00
|
|
|
struct timespec ts;
|
|
|
|
moo_ntime_t ns;
|
2017-02-15 11:57:24 +00:00
|
|
|
|
2017-02-22 09:48:58 +00:00
|
|
|
if (!dur) return; /* immediate check is requested. and there is no event */
|
2017-02-21 19:20:27 +00:00
|
|
|
|
2017-09-27 06:48:01 +00:00
|
|
|
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
2017-02-22 09:48:58 +00:00
|
|
|
clock_gettime (CLOCK_REALTIME, &ts);
|
|
|
|
ns.sec = ts.tv_sec;
|
|
|
|
ns.nsec = ts.tv_nsec;
|
2017-09-27 06:48:01 +00:00
|
|
|
#else
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday (&tv, MOO_NULL);
|
|
|
|
ns.sec = tv.tv_sec;
|
|
|
|
ns.nsec = MOO_USEC_TO_NSEC(tv.tv_usec);
|
|
|
|
}
|
|
|
|
#endif
|
2017-02-22 09:48:58 +00:00
|
|
|
MOO_ADDNTIME (&ns, &ns, dur);
|
|
|
|
ts.tv_sec = ns.sec;
|
|
|
|
ts.tv_nsec = ns.nsec;
|
2017-02-21 19:20:27 +00:00
|
|
|
|
|
|
|
pthread_mutex_lock (&xtn->ev.mtx);
|
2017-02-22 09:48:58 +00:00
|
|
|
if (xtn->ev.len <= 0)
|
2017-02-21 19:20:27 +00:00
|
|
|
{
|
2017-02-22 09:48:58 +00:00
|
|
|
/* the event buffer is still empty */
|
2017-03-23 16:14:22 +00:00
|
|
|
pthread_cond_timedwait (&xtn->ev.cnd2, &xtn->ev.mtx, &ts);
|
2017-02-21 19:20:27 +00:00
|
|
|
}
|
|
|
|
pthread_mutex_unlock (&xtn->ev.mtx);
|
|
|
|
}
|
|
|
|
|
2017-02-22 09:48:58 +00:00
|
|
|
n = xtn->ev.len;
|
|
|
|
|
2017-02-21 19:20:27 +00:00
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
--n;
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
if (xtn->ev.buf[n].fd == xtn->p[0])
|
2017-05-07 12:43:52 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
2017-02-21 19:20:27 +00:00
|
|
|
if (xtn->ev.buf[n].data.ptr == (void*)MOO_TYPE_MAX(moo_oow_t))
|
2017-09-27 14:03:05 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
if (xtn->ev.buf[n].fd == xtn->p[0])
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
if (xtn->ev.buf[n].fd == xtn->p[0])
|
2017-05-07 12:43:52 +00:00
|
|
|
#else
|
|
|
|
# error UNSUPPORTED
|
2017-04-28 14:45:13 +00:00
|
|
|
#endif
|
2017-02-21 19:20:27 +00:00
|
|
|
{
|
2017-02-22 09:48:58 +00:00
|
|
|
moo_uint8_t u8;
|
|
|
|
while (read (xtn->p[0], &u8, MOO_SIZEOF(u8)) > 0)
|
|
|
|
{
|
|
|
|
/* consume as much as possible */;
|
|
|
|
if (u8 == 'Q') xtn->iothr_abort = 1;
|
|
|
|
}
|
2017-02-21 19:20:27 +00:00
|
|
|
}
|
2017-02-22 09:48:58 +00:00
|
|
|
else if (muxwcb)
|
2017-02-21 19:20:27 +00:00
|
|
|
{
|
2017-04-28 14:45:13 +00:00
|
|
|
int revents;
|
|
|
|
moo_ooi_t mask;
|
2017-03-04 05:48:23 +00:00
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
revents = xtn->ev.buf[n].revents;
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
revents = xtn->ev.buf[n].events;
|
2017-09-27 14:03:05 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
revents = xtn->ev.buf[n].revents;
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
revents = xtn->ev.buf[n].events;
|
|
|
|
#endif
|
2017-04-28 14:45:13 +00:00
|
|
|
|
|
|
|
mask = 0;
|
|
|
|
if (revents & XPOLLIN) mask |= MOO_SEMAPHORE_IO_MASK_INPUT;
|
|
|
|
if (revents & XPOLLOUT) mask |= MOO_SEMAPHORE_IO_MASK_OUTPUT;
|
|
|
|
if (revents & XPOLLERR) mask |= MOO_SEMAPHORE_IO_MASK_ERROR;
|
|
|
|
if (revents & XPOLLHUP) mask |= MOO_SEMAPHORE_IO_MASK_HANGUP;
|
2017-02-21 19:20:27 +00:00
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
MOO_ASSERT (moo, xtn->epd.capa > xtn->ev.buf[n].fd);
|
|
|
|
muxwcb (moo, mask, (void*)xtn->epd.ptr[xtn->ev.buf[n].fd]);
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
2017-02-21 19:20:27 +00:00
|
|
|
muxwcb (moo, mask, xtn->ev.buf[n].data.ptr);
|
2017-09-27 14:03:05 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
MOO_ASSERT (moo, xtn->epd.capa > xtn->ev.buf[n].fd);
|
|
|
|
muxwcb (moo, mask, (void*)xtn->epd.ptr[xtn->ev.buf[n].fd]);
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
muxwcb (moo, mask, (void*)xtn->epd.data[xtn->ev.buf[n].fd]);
|
2017-09-27 14:03:05 +00:00
|
|
|
#else
|
|
|
|
# error UNSUPPORTED
|
2017-09-27 06:48:01 +00:00
|
|
|
#endif
|
2017-02-21 19:20:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while (n > 0);
|
|
|
|
|
|
|
|
pthread_mutex_lock (&xtn->ev.mtx);
|
|
|
|
xtn->ev.len = 0;
|
|
|
|
pthread_cond_signal (&xtn->ev.cnd);
|
|
|
|
pthread_mutex_unlock (&xtn->ev.mtx);
|
|
|
|
}
|
2017-02-22 09:48:58 +00:00
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
#else
|
2017-02-22 09:48:58 +00:00
|
|
|
int tmout = 0, n;
|
2017-05-07 14:32:38 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
struct dvpoll dvp;
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
|
|
|
struct timeval tv;
|
2017-09-27 14:03:05 +00:00
|
|
|
fd_set rfds, wfds;
|
|
|
|
int maxfd;
|
2017-05-07 14:32:38 +00:00
|
|
|
#endif
|
2017-02-22 09:48:58 +00:00
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
if (dur) tmout = MOO_SECNSEC_TO_MSEC(dur->sec, dur->nsec);
|
|
|
|
|
2017-05-07 14:32:38 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
|
|
|
dvp.dp_timeout = tmout; /* milliseconds */
|
|
|
|
dvp.dp_fds = xtn->ev.buf;
|
|
|
|
dvp.dp_nfds = MOO_COUNTOF(xtn->ev.buf);
|
|
|
|
n = ioctl (xtn->ep, DP_POLL, &dvp);
|
|
|
|
#elif defined(USE_EPOLL)
|
2017-02-21 19:51:10 +00:00
|
|
|
n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), tmout);
|
2017-05-07 14:32:38 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
memcpy (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf));
|
|
|
|
n = poll (xtn->ev.buf, xtn->ev.reg.len, tmout);
|
2017-09-27 14:03:05 +00:00
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
/* compact the return buffer as poll() doesn't */
|
|
|
|
moo_oow_t i, j;
|
|
|
|
for (i = 0, j = 0; i < xtn->ev.reg.len && j < n; i++)
|
|
|
|
{
|
|
|
|
if (xtn->ev.buf[i].revents)
|
|
|
|
{
|
|
|
|
if (j != i) xtn->ev.buf[j] = xtn->ev.buf[i];
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
n = j;
|
|
|
|
}
|
2017-09-27 01:03:18 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2017-09-27 14:03:05 +00:00
|
|
|
if (dur)
|
|
|
|
{
|
|
|
|
tv.tv_sec = dur->sec;
|
|
|
|
tv.tv_usec = MOO_NSEC_TO_USEC(dur->nsec);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
}
|
|
|
|
maxfd = xtn->ev.reg.maxfd;
|
|
|
|
MOO_MEMCPY (&rfds, &xtn->ev.reg.rfds, MOO_SIZEOF(rfds));
|
|
|
|
MOO_MEMCPY (&wfds, &xtn->ev.reg.wfds, MOO_SIZEOF(wfds));
|
|
|
|
n = select (maxfd + 1, &rfds, &wfds, NULL, &tv);
|
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
int fd, count = 0;
|
|
|
|
for (fd = 0; fd <= maxfd; fd++)
|
|
|
|
{
|
|
|
|
int events = 0;
|
|
|
|
if (FD_ISSET(fd, &rfds)) events |= XPOLLIN;
|
|
|
|
if (FD_ISSET(fd, &wfds)) events |= XPOLLOUT;
|
|
|
|
|
|
|
|
if (events)
|
|
|
|
{
|
|
|
|
MOO_ASSERT (moo, count < MOO_COUNTOF(xtn->ev.buf));
|
|
|
|
xtn->ev.buf[count].fd = fd;
|
|
|
|
xtn->ev.buf[count].events = events;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
n = count;
|
|
|
|
MOO_ASSERT (moo, n > 0);
|
|
|
|
}
|
2017-05-07 14:32:38 +00:00
|
|
|
#endif
|
2017-02-21 19:51:10 +00:00
|
|
|
|
|
|
|
if (n <= -1)
|
|
|
|
{
|
2017-09-27 14:03:05 +00:00
|
|
|
MOO_DEBUG2 (moo, "Warning: multiplexer wait failure - %d, %hs\n", errno, strerror(errno));
|
2017-02-21 19:51:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xtn->ev.len = n;
|
|
|
|
}
|
|
|
|
|
2017-03-04 05:48:23 +00:00
|
|
|
/* the muxwcb must be valid all the time in a non-threaded mode */
|
|
|
|
MOO_ASSERT (moo, muxwcb != MOO_NULL);
|
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
while (n > 0)
|
|
|
|
{
|
2017-04-28 14:45:13 +00:00
|
|
|
int revents;
|
|
|
|
moo_ooi_t mask;
|
2017-02-21 19:51:10 +00:00
|
|
|
|
|
|
|
--n;
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
revents = xtn->ev.buf[n].revents;
|
2017-05-07 12:43:52 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
|
|
|
revents = xtn->ev.buf[n].events;
|
2017-09-27 14:03:05 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
revents = xtn->ev.buf[n].revents;
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2017-09-27 14:03:05 +00:00
|
|
|
revents = xtn->ev.buf[n].events;
|
2017-04-28 14:45:13 +00:00
|
|
|
#else
|
2017-10-08 15:40:32 +00:00
|
|
|
revents = 0; /* TODO: fake. unsupported but to compile on such an unsupported system.*/
|
2017-04-28 14:45:13 +00:00
|
|
|
#endif
|
|
|
|
|
2017-02-21 19:51:10 +00:00
|
|
|
mask = 0;
|
2017-05-07 14:32:38 +00:00
|
|
|
if (revents & XPOLLIN) mask |= MOO_SEMAPHORE_IO_MASK_INPUT;
|
2017-04-28 14:45:13 +00:00
|
|
|
if (revents & XPOLLOUT) mask |= MOO_SEMAPHORE_IO_MASK_OUTPUT;
|
|
|
|
if (revents & XPOLLERR) mask |= MOO_SEMAPHORE_IO_MASK_ERROR;
|
|
|
|
if (revents & XPOLLHUP) mask |= MOO_SEMAPHORE_IO_MASK_HANGUP;
|
|
|
|
|
2017-09-27 14:03:05 +00:00
|
|
|
#if defined(USE_DEVPOLL)
|
2017-04-28 14:45:13 +00:00
|
|
|
MOO_ASSERT (moo, xtn->epd.capa > xtn->ev.buf[n].fd);
|
|
|
|
muxwcb (moo, mask, (void*)xtn->epd.ptr[xtn->ev.buf[n].fd]);
|
2017-05-07 12:43:52 +00:00
|
|
|
#elif defined(USE_EPOLL)
|
2017-02-21 19:51:10 +00:00
|
|
|
muxwcb (moo, mask, xtn->ev.buf[n].data.ptr);
|
2017-09-27 14:03:05 +00:00
|
|
|
#elif defined(USE_POLL)
|
|
|
|
MOO_ASSERT (moo, xtn->epd.capa > xtn->ev.buf[n].fd);
|
|
|
|
muxwcb (moo, mask, (void*)xtn->epd.ptr[xtn->ev.buf[n].fd]);
|
2017-09-27 06:48:01 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2017-09-27 14:03:05 +00:00
|
|
|
muxwcb (moo, mask, (void*)xtn->epd.data[xtn->ev.buf[n].fd]);
|
2017-04-28 14:45:13 +00:00
|
|
|
#endif
|
2017-02-21 19:51:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
xtn->ev.len = 0;
|
|
|
|
#endif
|
2017-02-10 09:06:53 +00:00
|
|
|
}
|
2017-02-22 09:48:58 +00:00
|
|
|
|
|
|
|
static void vm_sleep (moo_t* moo, const moo_ntime_t* dur)
|
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
xtn_t* xtn = moo_getxtn(moo);
|
|
|
|
if (xtn->waitable_timer)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER li;
|
|
|
|
li.QuadPart = -MOO_SECNSEC_TO_NSEC(dur->sec, dur->nsec);
|
|
|
|
if(SetWaitableTimer(timer, &li, 0, MOO_NULL, MOO_NULL, FALSE) == FALSE) goto normal_sleep;
|
|
|
|
WaitForSingleObject(timer, INFINITE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
normal_sleep:
|
|
|
|
/* fallback to normal Sleep() */
|
|
|
|
Sleep (MOO_SECNSEC_TO_MSEC(dur->sec,dur->nsec));
|
|
|
|
}
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
|
|
|
|
/* TODO: in gui mode, this is not a desirable method???
|
|
|
|
* this must be made event-driven coupled with the main event loop */
|
|
|
|
DosSleep (MOO_SECNSEC_TO_MSEC(dur->sec,dur->nsec));
|
|
|
|
|
|
|
|
#elif defined(macintosh)
|
|
|
|
|
|
|
|
/* TODO: ... */
|
|
|
|
|
|
|
|
#elif defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
|
|
|
|
|
|
|
|
clock_t c;
|
|
|
|
|
|
|
|
c = clock ();
|
|
|
|
c += dur->sec * CLOCKS_PER_SEC;
|
|
|
|
|
|
|
|
#if (CLOCKS_PER_SEC == 100)
|
|
|
|
c += MOO_NSEC_TO_MSEC(dur->nsec) / 10;
|
|
|
|
#elif (CLOCKS_PER_SEC == 1000)
|
|
|
|
c += MOO_NSEC_TO_MSEC(dur->nsec);
|
|
|
|
#elif (CLOCKS_PER_SEC == 1000000L)
|
|
|
|
c += MOO_NSEC_TO_USEC(dur->nsec);
|
|
|
|
#elif (CLOCKS_PER_SEC == 1000000000L)
|
|
|
|
c += dur->nsec;
|
|
|
|
#else
|
|
|
|
# error UNSUPPORTED CLOCKS_PER_SEC
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* TODO: handle clock overvlow */
|
|
|
|
/* TODO: check if there is abortion request or interrupt */
|
|
|
|
while (c > clock())
|
|
|
|
{
|
|
|
|
_halt_cpu();
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#if defined(USE_THREAD)
|
|
|
|
/* the sleep callback is called only if there is no IO semaphore
|
2017-03-23 16:14:22 +00:00
|
|
|
* waiting. so i can safely call vm_muxwait() without a muxwait callback
|
2017-03-04 05:48:23 +00:00
|
|
|
* when USE_THREAD is true */
|
2017-02-22 09:48:58 +00:00
|
|
|
vm_muxwait (moo, dur, MOO_NULL);
|
|
|
|
#else
|
|
|
|
struct timespec ts;
|
|
|
|
ts.tv_sec = dur->sec;
|
|
|
|
ts.tv_nsec = dur->nsec;
|
|
|
|
nanosleep (&ts, MOO_NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
static moo_t* g_moo = MOO_NULL;
|
2016-05-17 15:12:27 +00:00
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2017-01-15 17:53:37 +00:00
|
|
|
#if defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
|
|
|
|
|
|
|
|
#if defined(_INTELC32_)
|
2016-05-18 14:53:20 +00:00
|
|
|
static void (*prev_timer_intr_handler) (void);
|
2017-01-15 17:53:37 +00:00
|
|
|
#else
|
|
|
|
static void (__interrupt *prev_timer_intr_handler) (void);
|
|
|
|
#endif
|
2016-05-18 14:53:20 +00:00
|
|
|
|
2017-01-15 17:53:37 +00:00
|
|
|
#if defined(_INTELC32_)
|
2016-05-18 14:53:20 +00:00
|
|
|
#pragma interrupt(timer_intr_handler)
|
|
|
|
static void timer_intr_handler (void)
|
2017-01-15 17:53:37 +00:00
|
|
|
#else
|
|
|
|
static void __interrupt timer_intr_handler (void)
|
|
|
|
#endif
|
2016-05-18 14:53:20 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
_XSTACK *stk;
|
|
|
|
int r;
|
|
|
|
stk = (_XSTACK *)_get_stk_frame();
|
|
|
|
r = (unsigned short)stk_ptr->eax;
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* The timer interrupt (normally) occurs 18.2 times per second. */
|
2017-01-09 09:54:49 +00:00
|
|
|
if (g_moo) moo_switchprocess (g_moo);
|
2017-01-19 17:12:16 +00:00
|
|
|
_chain_intr (prev_timer_intr_handler);
|
2016-05-18 14:53:20 +00:00
|
|
|
}
|
|
|
|
|
2016-05-19 03:49:23 +00:00
|
|
|
#elif defined(macintosh)
|
|
|
|
|
|
|
|
static TMTask g_tmtask;
|
2016-05-19 11:22:02 +00:00
|
|
|
static ProcessSerialNumber g_psn;
|
|
|
|
|
|
|
|
#define TMTASK_DELAY 50 /* milliseconds if positive, microseconds(after negation) if negative */
|
2016-05-19 03:49:23 +00:00
|
|
|
|
|
|
|
static pascal void timer_intr_handler (TMTask* task)
|
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
if (g_moo) moo_switchprocess (g_moo);
|
2016-05-19 11:22:02 +00:00
|
|
|
WakeUpProcess (&g_psn);
|
|
|
|
PrimeTime ((QElem*)&g_tmtask, TMTASK_DELAY);
|
2016-05-19 03:49:23 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 14:53:20 +00:00
|
|
|
#else
|
2016-05-17 15:12:27 +00:00
|
|
|
static void arrange_process_switching (int sig)
|
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
if (g_moo) moo_switchprocess (g_moo);
|
2016-05-17 15:12:27 +00:00
|
|
|
}
|
2016-05-18 14:53:20 +00:00
|
|
|
#endif
|
2016-05-17 15:12:27 +00:00
|
|
|
|
|
|
|
static void setup_tick (void)
|
|
|
|
{
|
2017-01-15 17:53:37 +00:00
|
|
|
#if defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
|
2016-05-18 14:53:20 +00:00
|
|
|
|
|
|
|
prev_timer_intr_handler = _dos_getvect (0x1C);
|
|
|
|
_dos_setvect (0x1C, timer_intr_handler);
|
|
|
|
|
2016-05-19 03:49:23 +00:00
|
|
|
#elif defined(macintosh)
|
|
|
|
|
2016-05-19 11:22:02 +00:00
|
|
|
GetCurrentProcess (&g_psn);
|
2017-01-09 09:54:49 +00:00
|
|
|
memset (&g_tmtask, 0, MOO_SIZEOF(g_tmtask));
|
2016-05-19 03:49:23 +00:00
|
|
|
g_tmtask.tmAddr = NewTimerProc (timer_intr_handler);
|
|
|
|
InsXTime ((QElem*)&g_tmtask);
|
|
|
|
|
2016-05-19 11:22:02 +00:00
|
|
|
PrimeTime ((QElem*)&g_tmtask, TMTASK_DELAY);
|
2016-05-19 03:49:23 +00:00
|
|
|
|
2016-05-18 14:53:20 +00:00
|
|
|
#elif defined(HAVE_SETITIMER) && defined(SIGVTALRM) && defined(ITIMER_VIRTUAL)
|
2016-05-17 15:12:27 +00:00
|
|
|
struct itimerval itv;
|
|
|
|
struct sigaction act;
|
|
|
|
|
|
|
|
sigemptyset (&act.sa_mask);
|
|
|
|
act.sa_handler = arrange_process_switching;
|
2017-01-22 18:01:26 +00:00
|
|
|
act.sa_flags = SA_RESTART;
|
2017-01-09 09:54:49 +00:00
|
|
|
sigaction (SIGVTALRM, &act, MOO_NULL);
|
2016-05-17 15:12:27 +00:00
|
|
|
|
|
|
|
itv.it_interval.tv_sec = 0;
|
|
|
|
itv.it_interval.tv_usec = 100; /* 100 microseconds */
|
|
|
|
itv.it_value.tv_sec = 0;
|
|
|
|
itv.it_value.tv_usec = 100;
|
2017-01-09 09:54:49 +00:00
|
|
|
setitimer (ITIMER_VIRTUAL, &itv, MOO_NULL);
|
2016-05-18 14:53:20 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
# error UNSUPPORTED
|
2016-05-17 15:12:27 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cancel_tick (void)
|
|
|
|
{
|
2017-01-15 17:53:37 +00:00
|
|
|
#if defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
|
2016-05-18 14:53:20 +00:00
|
|
|
|
|
|
|
_dos_setvect (0x1C, prev_timer_intr_handler);
|
|
|
|
|
2016-05-19 03:49:23 +00:00
|
|
|
#elif defined(macintosh)
|
|
|
|
RmvTime ((QElem*)&g_tmtask);
|
|
|
|
/*DisposeTimerProc (g_tmtask.tmAddr);*/
|
|
|
|
|
2016-05-18 14:53:20 +00:00
|
|
|
#elif defined(HAVE_SETITIMER) && defined(SIGVTALRM) && defined(ITIMER_VIRTUAL)
|
2016-05-17 15:12:27 +00:00
|
|
|
struct itimerval itv;
|
|
|
|
struct sigaction act;
|
|
|
|
|
|
|
|
itv.it_interval.tv_sec = 0;
|
|
|
|
itv.it_interval.tv_usec = 0;
|
2016-06-05 18:37:28 +00:00
|
|
|
itv.it_value.tv_sec = 0; /* make setitimer() one-shot only */
|
2016-05-17 15:12:27 +00:00
|
|
|
itv.it_value.tv_usec = 0;
|
2017-01-09 09:54:49 +00:00
|
|
|
setitimer (ITIMER_VIRTUAL, &itv, MOO_NULL);
|
2016-05-17 15:12:27 +00:00
|
|
|
|
2016-06-05 18:37:28 +00:00
|
|
|
sigemptyset (&act.sa_mask);
|
|
|
|
act.sa_handler = SIG_IGN; /* ignore the signal potentially fired by the one-shot arrange above */
|
2016-05-17 15:12:27 +00:00
|
|
|
act.sa_flags = 0;
|
2017-01-09 09:54:49 +00:00
|
|
|
sigaction (SIGVTALRM, &act, MOO_NULL);
|
2016-05-18 14:53:20 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
# error UNSUPPORTED
|
2016-05-17 15:12:27 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-02-14 14:00:14 +00:00
|
|
|
static void handle_term (int sig)
|
|
|
|
{
|
2017-02-21 19:20:27 +00:00
|
|
|
if (g_moo)
|
|
|
|
{
|
2017-05-07 12:43:52 +00:00
|
|
|
#if defined(USE_THREAD)
|
2017-02-22 09:48:58 +00:00
|
|
|
xtn_t* xtn = moo_getxtn(g_moo);
|
|
|
|
write (xtn->p[1], "Q", 1);
|
2017-05-07 12:43:52 +00:00
|
|
|
#endif
|
2017-02-21 19:20:27 +00:00
|
|
|
moo_abort (g_moo);
|
|
|
|
}
|
2017-02-14 14:00:14 +00:00
|
|
|
}
|
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
static void setup_sigterm (void)
|
2017-02-14 14:00:14 +00:00
|
|
|
{
|
2017-06-08 14:39:17 +00:00
|
|
|
#if defined(_WIN32)
|
|
|
|
SetConsoleCtrlHandler (handle_term, TRUE);
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
os2_excrr.ExceptionHandler = (ERR)__intr_handler;
|
|
|
|
DosSetExceptionHandler (&os2_excrr); /* TODO: check if NO_ERROR is returned */
|
|
|
|
#elif defined(__DOS__)
|
|
|
|
signal (SIGINT, handle_term);
|
|
|
|
#else
|
2017-02-14 14:00:14 +00:00
|
|
|
struct sigaction sa;
|
2017-02-21 19:20:27 +00:00
|
|
|
memset (&sa, 0, MOO_SIZEOF(sa));
|
2017-02-14 14:00:14 +00:00
|
|
|
sa.sa_handler = handle_term;
|
|
|
|
sigaction (SIGINT, &sa, MOO_NULL);
|
2017-06-08 14:39:17 +00:00
|
|
|
#endif
|
2017-02-14 14:00:14 +00:00
|
|
|
}
|
|
|
|
|
2017-06-23 16:09:07 +00:00
|
|
|
static void clear_sigterm (void)
|
2017-06-08 14:39:17 +00:00
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
SetConsoleCtrlHandler (handle_term, FALSE);
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
DosUnsetExceptionHandler (&os2_excrr);
|
|
|
|
#elif defined(__DOS__)
|
|
|
|
signal (SIGINT, SIG_DFL);
|
|
|
|
#else
|
|
|
|
struct sigaction sa;
|
|
|
|
memset (&sa, 0, MOO_SIZEOF(sa));
|
|
|
|
sa.sa_handler = SIG_DFL;
|
|
|
|
sigaction (SIGINT, &sa, MOO_NULL);
|
|
|
|
#endif
|
|
|
|
}
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
static void close_moo (moo_t* moo)
|
|
|
|
{
|
|
|
|
xtn_t* xtn = moo_getxtn(moo);
|
|
|
|
if (xtn->logfd >= 0)
|
|
|
|
{
|
|
|
|
close (xtn->logfd);
|
|
|
|
xtn->logfd = -1;
|
|
|
|
}
|
|
|
|
moo_close (moo);
|
|
|
|
}
|
|
|
|
|
2017-11-23 15:45:25 +00:00
|
|
|
static int handle_logopt (moo_t* moo, const moo_bch_t* str)
|
|
|
|
{
|
|
|
|
xtn_t* xtn = moo_getxtn (moo);
|
|
|
|
moo_bch_t* xstr = (moo_bch_t*)str;
|
|
|
|
moo_bch_t* cm, * flt;
|
|
|
|
|
|
|
|
cm = moo_findbcharinbcstr (xstr, ',');
|
|
|
|
if (cm)
|
|
|
|
{
|
|
|
|
xstr = moo_dupbchars (moo, str, moo_countbcstr(str));
|
|
|
|
if (!xstr)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "ERROR: out of memory in duplicating %s\n", str);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cm = moo_findbcharinbcstr(xstr, ',');
|
|
|
|
*cm = '\0';
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
flt = cm + 1;
|
|
|
|
|
|
|
|
cm = moo_findbcharinbcstr(flt, ',');
|
|
|
|
if (cm) *cm = '\0';
|
|
|
|
|
|
|
|
if (moo_compbcstr (flt, "app") == 0) xtn->logmask |= MOO_LOG_APP;
|
|
|
|
else if (moo_compbcstr (flt, "mnemonic") == 0) xtn->logmask |= MOO_LOG_MNEMONIC;
|
|
|
|
else if (moo_compbcstr (flt, "gc") == 0) xtn->logmask |= MOO_LOG_GC;
|
|
|
|
else if (moo_compbcstr (flt, "ic") == 0) xtn->logmask |= MOO_LOG_IC;
|
|
|
|
else if (moo_compbcstr (flt, "primitive") == 0) xtn->logmask |= MOO_LOG_PRIMITIVE;
|
|
|
|
|
|
|
|
}
|
|
|
|
while (cm);
|
2017-11-24 17:40:20 +00:00
|
|
|
|
2017-12-03 17:08:04 +00:00
|
|
|
xtn->logmask |= MOO_LOG_ALL_LEVELS; /* TODO: parse levels also */
|
2017-11-23 15:45:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-24 17:40:20 +00:00
|
|
|
xtn->logmask = MOO_LOG_ALL_LEVELS | MOO_LOG_ALL_TYPES;
|
2017-11-23 15:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
xtn->logfd = open (xstr, O_CREAT | O_WRONLY | O_APPEND , 0644);
|
|
|
|
if (xtn->logfd == -1)
|
|
|
|
{
|
2017-12-16 05:21:38 +00:00
|
|
|
fprintf (stderr, "ERROR: cannot open a log file %s\n", xstr);
|
2017-11-23 15:45:25 +00:00
|
|
|
if (str != xstr) moo_freemem (moo, xstr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str != xstr) moo_freemem (moo, xstr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-16 16:14:23 +00:00
|
|
|
#if !defined(NDEBUG)
|
|
|
|
static int handle_dbgopt (moo_t* moo, const moo_bch_t* str)
|
|
|
|
{
|
|
|
|
xtn_t* xtn = moo_getxtn (moo);
|
|
|
|
const moo_bch_t* cm, * flt;
|
|
|
|
moo_oow_t len;
|
|
|
|
unsigned int trait, dbgopt = 0;
|
|
|
|
|
|
|
|
cm = str - 1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
flt = cm + 1;
|
|
|
|
|
|
|
|
cm = moo_findbcharinbcstr(flt, ',');
|
|
|
|
len = cm? (cm - flt): moo_countbcstr(flt);
|
|
|
|
if (moo_compbcharsbcstr (flt, len, "gc") == 0) dbgopt |= MOO_DEBUG_GC;
|
|
|
|
else if (moo_compbcharsbcstr (flt, len, "bigint") == 0) dbgopt |= MOO_DEBUG_BIGINT;
|
|
|
|
/* TODO: error handling for unknown options */
|
|
|
|
}
|
|
|
|
while (cm);
|
|
|
|
|
|
|
|
moo_getoption (moo, MOO_TRAIT, &trait);
|
|
|
|
trait |= dbgopt;
|
|
|
|
moo_setoption (moo, MOO_TRAIT, &trait);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define MIN_MEMSIZE 2048000ul
|
|
|
|
|
2015-05-07 15:58:04 +00:00
|
|
|
int main (int argc, char* argv[])
|
|
|
|
{
|
2017-02-10 09:06:53 +00:00
|
|
|
static moo_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' }; /*TODO: make this an argument */
|
|
|
|
static moo_ooch_t str_main[] = { 'm', 'a', 'i', 'n' };
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_t* moo;
|
2015-05-16 07:31:16 +00:00
|
|
|
xtn_t* xtn;
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_oocs_t objname;
|
|
|
|
moo_oocs_t mthname;
|
|
|
|
moo_vmprim_t vmprim;
|
2016-05-17 15:12:27 +00:00
|
|
|
int i, xret;
|
2015-05-16 07:31:16 +00:00
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_bci_t c;
|
2017-12-03 17:08:04 +00:00
|
|
|
static moo_bopt_lng_t lopt[] =
|
|
|
|
{
|
2017-12-16 16:14:23 +00:00
|
|
|
{ ":log", 'l' },
|
|
|
|
{ ":memsize", 'm' },
|
|
|
|
#if !defined(NDEBUG)
|
|
|
|
{ ":debug", '\0' }, /* NOTE: there is no short option for --debug */
|
|
|
|
#endif
|
|
|
|
{ MOO_NULL, '\0' }
|
2017-12-03 17:08:04 +00:00
|
|
|
};
|
2017-11-22 04:52:45 +00:00
|
|
|
static moo_bopt_t opt =
|
|
|
|
{
|
2017-12-16 16:14:23 +00:00
|
|
|
"l:m:",
|
2017-12-03 17:08:04 +00:00
|
|
|
lopt
|
2017-11-22 04:52:45 +00:00
|
|
|
};
|
|
|
|
|
2017-11-23 15:45:25 +00:00
|
|
|
const char* logopt = MOO_NULL;
|
2017-12-16 16:14:23 +00:00
|
|
|
moo_oow_t memsize = MIN_MEMSIZE;
|
|
|
|
|
|
|
|
#if !defined(NDEBUG)
|
|
|
|
const char* dbgopt = MOO_NULL;
|
|
|
|
#endif
|
2017-11-22 04:52:45 +00:00
|
|
|
|
|
|
|
setlocale (LC_ALL, "");
|
|
|
|
|
2015-05-28 16:51:37 +00:00
|
|
|
#if !defined(macintosh)
|
2015-06-11 12:09:10 +00:00
|
|
|
if (argc < 2)
|
2015-05-16 07:31:16 +00:00
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
print_usage:
|
2015-06-11 12:09:10 +00:00
|
|
|
fprintf (stderr, "Usage: %s filename ...\n", argv[0]);
|
2015-05-16 07:31:16 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
while ((c = moo_getbopt (argc, argv, &opt)) != MOO_BCI_EOF)
|
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 'l':
|
2017-11-23 15:45:25 +00:00
|
|
|
logopt = opt.arg;
|
2017-11-22 04:52:45 +00:00
|
|
|
break;
|
|
|
|
|
2017-12-16 16:14:23 +00:00
|
|
|
case 'm':
|
|
|
|
memsize = strtoul(opt.arg, MOO_NULL, 0);
|
|
|
|
if (memsize <= MIN_MEMSIZE) memsize = MIN_MEMSIZE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\0':
|
2017-12-16 16:27:27 +00:00
|
|
|
#if !defined(NDEBUG)
|
2017-12-16 16:14:23 +00:00
|
|
|
if (moo_compbcstr(opt.lngopt, "debug") == 0)
|
|
|
|
{
|
|
|
|
dbgopt = opt.arg;
|
|
|
|
break;
|
|
|
|
}
|
2017-12-16 16:27:27 +00:00
|
|
|
#endif
|
2017-12-16 16:14:23 +00:00
|
|
|
goto print_usage;
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-12-16 05:21:38 +00:00
|
|
|
|
|
|
|
if (opt.ind >= argc) goto print_usage;
|
2017-11-22 04:52:45 +00:00
|
|
|
#endif
|
2017-07-27 08:32:16 +00:00
|
|
|
|
2017-03-19 14:18:37 +00:00
|
|
|
memset (&vmprim, 0, MOO_SIZEOF(vmprim));
|
2016-11-27 15:37:14 +00:00
|
|
|
vmprim.dl_open = dl_open;
|
|
|
|
vmprim.dl_close = dl_close;
|
|
|
|
vmprim.dl_getsym = dl_getsym;
|
2016-05-27 15:01:54 +00:00
|
|
|
vmprim.log_write = log_write;
|
2017-02-10 09:06:53 +00:00
|
|
|
vmprim.vm_startup = vm_startup;
|
|
|
|
vmprim.vm_cleanup = vm_cleanup;
|
2017-02-12 18:59:03 +00:00
|
|
|
vmprim.vm_gettime = vm_gettime;
|
2017-02-22 09:48:58 +00:00
|
|
|
vmprim.vm_muxadd = vm_muxadd;
|
|
|
|
vmprim.vm_muxdel = vm_muxdel;
|
2017-04-08 07:23:31 +00:00
|
|
|
vmprim.vm_muxmod = vm_muxmod;
|
2017-02-22 09:48:58 +00:00
|
|
|
vmprim.vm_muxwait = vm_muxwait;
|
2017-02-12 18:59:03 +00:00
|
|
|
vmprim.vm_sleep = vm_sleep;
|
2015-05-07 15:58:04 +00:00
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
|
|
|
lt_dlinit ();
|
|
|
|
#endif
|
|
|
|
|
2017-12-16 16:14:23 +00:00
|
|
|
moo = moo_open (&sys_mmgr, MOO_SIZEOF(xtn_t), memsize, &vmprim, MOO_NULL);
|
2017-01-09 09:54:49 +00:00
|
|
|
if (!moo)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
2017-11-23 15:45:25 +00:00
|
|
|
fprintf (stderr, "ERROR: cannot open moo\n");
|
2015-05-07 15:58:04 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_oow_t tab_size;
|
2015-05-28 16:51:37 +00:00
|
|
|
|
|
|
|
tab_size = 5000;
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_setoption (moo, MOO_SYMTAB_SIZE, &tab_size);
|
2015-05-28 16:51:37 +00:00
|
|
|
tab_size = 5000;
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_setoption (moo, MOO_SYSDIC_SIZE, &tab_size);
|
2016-02-13 17:39:11 +00:00
|
|
|
tab_size = 600;
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_setoption (moo, MOO_PROCSTK_SIZE, &tab_size);
|
2015-05-07 15:58:04 +00:00
|
|
|
}
|
|
|
|
|
2015-06-28 14:20:37 +00:00
|
|
|
{
|
2017-05-21 16:57:21 +00:00
|
|
|
unsigned int trait = 0;
|
2015-06-28 14:20:37 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
/*trait |= MOO_NOGC;*/
|
|
|
|
trait |= MOO_AWAIT_PROCS;
|
|
|
|
moo_setoption (moo, MOO_TRAIT, &trait);
|
2017-05-21 16:57:21 +00:00
|
|
|
|
|
|
|
/* disable GC logs */
|
|
|
|
trait = ~MOO_LOG_GC;
|
|
|
|
moo_setoption (moo, MOO_LOG_MASK, &trait);
|
2015-06-28 14:20:37 +00:00
|
|
|
}
|
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
xtn = moo_getxtn (moo);
|
|
|
|
xtn->logfd = -1;
|
|
|
|
|
2017-11-23 15:45:25 +00:00
|
|
|
if (logopt)
|
2017-11-22 04:52:45 +00:00
|
|
|
{
|
2017-11-23 15:45:25 +00:00
|
|
|
if (handle_logopt (moo, logopt) <= -1)
|
2017-11-22 04:52:45 +00:00
|
|
|
{
|
|
|
|
close_moo (moo);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2017-12-03 17:08:04 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* default logging mask when no logging option is set */
|
|
|
|
xtn->logmask = MOO_LOG_ALL_TYPES | MOO_LOG_ERROR | MOO_LOG_FATAL;
|
|
|
|
}
|
2017-11-22 04:52:45 +00:00
|
|
|
|
2017-12-16 16:14:23 +00:00
|
|
|
#if !defined(NDEBUG)
|
|
|
|
if (dbgopt)
|
|
|
|
{
|
|
|
|
if (handle_dbgopt (moo, dbgopt) <= -1)
|
|
|
|
{
|
|
|
|
close_moo (moo);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
if (moo_ignite(moo) <= -1)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
2017-12-03 17:08:04 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "ERROR: cannot ignite moo - [%d] %js\n", moo_geterrnum(moo), moo_geterrstr(moo));
|
2017-11-22 04:52:45 +00:00
|
|
|
close_moo (moo);
|
2015-05-07 15:58:04 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
#if defined(macintosh)
|
|
|
|
i = 20;
|
2017-12-16 05:21:38 +00:00
|
|
|
xtn->source_path = "test.moo";
|
2015-06-11 12:09:10 +00:00
|
|
|
goto compile;
|
2015-05-28 16:51:37 +00:00
|
|
|
#endif
|
2015-06-11 12:09:10 +00:00
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
for (i = opt.ind; i < argc; i++)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
2015-06-11 12:09:10 +00:00
|
|
|
xtn->source_path = argv[i];
|
2015-05-20 15:52:45 +00:00
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
compile:
|
2017-01-09 09:54:49 +00:00
|
|
|
if (moo_compile (moo, input_handler) <= -1)
|
2015-06-11 12:09:10 +00:00
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
if (moo->errnum == MOO_ESYNTAX)
|
2015-05-20 15:52:45 +00:00
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_synerr_t synerr;
|
|
|
|
moo_bch_t bcs[1024]; /* TODO: right buffer size */
|
|
|
|
moo_oow_t bcslen, ucslen;
|
2015-06-11 12:09:10 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
moo_getsynerr (moo, &synerr);
|
2015-06-11 12:09:10 +00:00
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "ERROR: ");
|
2015-06-11 12:09:10 +00:00
|
|
|
if (synerr.loc.file)
|
2015-05-20 15:52:45 +00:00
|
|
|
{
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-01-09 09:54:49 +00:00
|
|
|
bcslen = MOO_COUNTOF(bcs);
|
|
|
|
if (moo_convootobcstr (moo, synerr.loc.file, &ucslen, bcs, &bcslen) >= 0)
|
2015-06-11 12:09:10 +00:00
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "%.*s ", (int)bcslen, bcs);
|
2015-06-11 12:09:10 +00:00
|
|
|
}
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "%s ", synerr.loc.file);
|
2017-02-03 06:28:12 +00:00
|
|
|
#endif
|
2015-05-20 15:52:45 +00:00
|
|
|
}
|
2015-06-12 13:52:30 +00:00
|
|
|
else
|
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "%s ", xtn->source_path);
|
2015-06-12 13:52:30 +00:00
|
|
|
}
|
2015-05-20 15:52:45 +00:00
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "syntax error at line %lu column %lu - ",
|
2016-12-28 19:12:14 +00:00
|
|
|
(unsigned long int)synerr.loc.line, (unsigned long int)synerr.loc.colm);
|
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
bcslen = MOO_COUNTOF(bcs);
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-10-18 16:15:51 +00:00
|
|
|
if (moo_convootobcstr (moo, moo_synerrnum_to_errstr(synerr.num), &ucslen, bcs, &bcslen) >= 0)
|
2016-12-28 19:12:14 +00:00
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, " [%.*s]", (int)bcslen, bcs);
|
2016-12-28 19:12:14 +00:00
|
|
|
}
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, " [%s]", moo_synerrnum_to_errstr(synerr.num));
|
2017-02-03 06:28:12 +00:00
|
|
|
#endif
|
2016-12-28 19:12:14 +00:00
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
if (synerr.tgt.len > 0)
|
2015-05-19 15:16:18 +00:00
|
|
|
{
|
2017-01-09 09:54:49 +00:00
|
|
|
bcslen = MOO_COUNTOF(bcs);
|
2015-06-11 12:09:10 +00:00
|
|
|
ucslen = synerr.tgt.len;
|
|
|
|
|
2017-02-03 06:28:12 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-01-09 09:54:49 +00:00
|
|
|
if (moo_convootobchars (moo, synerr.tgt.ptr, &ucslen, bcs, &bcslen) >= 0)
|
2015-06-11 12:09:10 +00:00
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, " [%.*s]", (int)bcslen, bcs);
|
2015-06-11 12:09:10 +00:00
|
|
|
}
|
2017-02-03 06:28:12 +00:00
|
|
|
#else
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, " [%.*s]", (int)synerr.tgt.len, synerr.tgt.ptr);
|
2017-02-03 06:28:12 +00:00
|
|
|
#endif
|
2015-05-19 15:16:18 +00:00
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
}
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "\n");
|
2015-05-19 15:16:18 +00:00
|
|
|
}
|
2015-06-11 12:09:10 +00:00
|
|
|
else
|
|
|
|
{
|
2017-11-22 04:52:45 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR | MOO_LOG_STDERR, "ERROR: cannot compile code - [%d] %js\n", moo_geterrnum(moo), moo_geterrstr(moo));
|
2015-06-11 12:09:10 +00:00
|
|
|
}
|
2017-11-22 04:52:45 +00:00
|
|
|
|
|
|
|
close_moo (moo);
|
2016-02-18 17:49:56 +00:00
|
|
|
#if defined(USE_LTDL)
|
|
|
|
lt_dlexit ();
|
|
|
|
#endif
|
2015-06-11 12:09:10 +00:00
|
|
|
return -1;
|
2015-05-19 15:16:18 +00:00
|
|
|
}
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
MOO_DEBUG0 (moo, "COMPILE OK. STARTING EXECUTION...\n");
|
2016-05-17 15:12:27 +00:00
|
|
|
xret = 0;
|
2017-01-09 09:54:49 +00:00
|
|
|
g_moo = moo;
|
2016-05-17 15:12:27 +00:00
|
|
|
setup_tick ();
|
2017-06-23 16:09:07 +00:00
|
|
|
setup_sigterm ();
|
2016-05-17 15:12:27 +00:00
|
|
|
|
2015-06-11 09:11:18 +00:00
|
|
|
objname.ptr = str_my_object;
|
|
|
|
objname.len = 8;
|
2015-06-06 07:24:35 +00:00
|
|
|
mthname.ptr = str_main;
|
|
|
|
mthname.len = 4;
|
2017-01-09 09:54:49 +00:00
|
|
|
if (moo_invoke (moo, &objname, &mthname) <= -1)
|
2015-06-04 18:34:37 +00:00
|
|
|
{
|
2017-01-12 10:06:43 +00:00
|
|
|
moo_logbfmt (moo, MOO_LOG_ERROR, "ERROR: cannot execute code - [%d] %js\n", moo_geterrnum(moo), moo_geterrstr(moo));
|
2016-05-17 15:12:27 +00:00
|
|
|
xret = -1;
|
2015-06-04 18:34:37 +00:00
|
|
|
}
|
2015-06-06 07:24:35 +00:00
|
|
|
|
2016-05-17 15:12:27 +00:00
|
|
|
cancel_tick ();
|
2017-06-23 16:09:07 +00:00
|
|
|
clear_sigterm ();
|
2017-01-09 09:54:49 +00:00
|
|
|
g_moo = MOO_NULL;
|
2015-06-06 07:24:35 +00:00
|
|
|
|
2017-01-09 09:54:49 +00:00
|
|
|
/*moo_dumpsymtab(moo);
|
|
|
|
*moo_dumpdic(moo, moo->sysdic, "System dictionary");*/
|
2016-06-05 18:37:28 +00:00
|
|
|
|
2017-11-22 04:52:45 +00:00
|
|
|
close_moo (moo);
|
2015-05-07 15:58:04 +00:00
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
|
|
|
lt_dlexit ();
|
2015-11-22 13:32:06 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(_WIN32) && defined(_DEBUG)
|
|
|
|
getchar();
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2016-05-17 15:12:27 +00:00
|
|
|
return xret;
|
2015-05-07 15:58:04 +00:00
|
|
|
}
|