2015-05-08 14:29:35 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2016-02-12 16:23:26 +00:00
|
|
|
Copyright (c) 2014-2016 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.
|
|
|
|
*/
|
|
|
|
|
2015-05-07 15:58:04 +00:00
|
|
|
#include "stix-prv.h"
|
|
|
|
|
|
|
|
#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>
|
2015-10-14 13:25:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
# include <windows.h>
|
|
|
|
# include <tchar.h>
|
|
|
|
# if defined(STIX_HAVE_CFG_H)
|
|
|
|
# include <ltdl.h>
|
|
|
|
# define USE_LTDL
|
|
|
|
# endif
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
# define INCL_DOSMODULEMGR
|
|
|
|
# define INCL_DOSPROCESS
|
|
|
|
# define INCL_DOSERRORS
|
|
|
|
# include <os2.h>
|
2015-12-03 15:11:47 +00:00
|
|
|
#elif defined(__MSDOS__)
|
2016-05-18 14:53:20 +00:00
|
|
|
# include <dos.h>
|
2015-12-03 05:46:11 +00:00
|
|
|
#elif defined(macintosh)
|
2016-05-19 03:49:23 +00:00
|
|
|
# include <Timer.h>
|
2015-10-14 13:25:36 +00:00
|
|
|
#else
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <ltdl.h>
|
|
|
|
# define USE_LTDL
|
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
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2015-10-14 09:06:44 +00:00
|
|
|
#if !defined(STIX_DEFAULT_MODPREFIX)
|
|
|
|
# if defined(_WIN32)
|
|
|
|
# define STIX_DEFAULT_MODPREFIX "stix-"
|
|
|
|
# elif defined(__OS2__)
|
|
|
|
# define STIX_DEFAULT_MODPREFIX "st-"
|
2015-12-03 15:11:47 +00:00
|
|
|
# elif defined(__MSDOS__)
|
2015-10-14 09:06:44 +00:00
|
|
|
# define STIX_DEFAULT_MODPREFIX "st-"
|
|
|
|
# else
|
|
|
|
# define STIX_DEFAULT_MODPREFIX "libstix-"
|
|
|
|
# endif
|
2015-10-13 14:51:04 +00:00
|
|
|
#endif
|
|
|
|
|
2015-10-14 09:06:44 +00:00
|
|
|
#if !defined(STIX_DEFAULT_MODPOSTFIX)
|
|
|
|
# if defined(_WIN32)
|
|
|
|
# define STIX_DEFAULT_MODPOSTFIX ""
|
|
|
|
# elif defined(__OS2__)
|
|
|
|
# define STIX_DEFAULT_MODPOSTFIX ""
|
2015-12-03 15:11:47 +00:00
|
|
|
# elif defined(__MSDOS__)
|
2015-10-14 09:06:44 +00:00
|
|
|
# define STIX_DEFAULT_MODPOSTFIX ""
|
|
|
|
# else
|
|
|
|
# define STIX_DEFAULT_MODPOSTFIX ""
|
|
|
|
# endif
|
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
typedef struct bb_t bb_t;
|
|
|
|
struct bb_t
|
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
stix_oow_t pos;
|
|
|
|
stix_oow_t len;
|
|
|
|
FILE* fp;
|
|
|
|
};
|
|
|
|
|
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 */
|
2015-05-16 07:31:16 +00:00
|
|
|
};
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2015-12-17 16:11:10 +00:00
|
|
|
static void* sys_alloc (stix_mmgr_t* mmgr, stix_oow_t size)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return malloc (size);
|
|
|
|
}
|
|
|
|
|
2015-12-17 16:11:10 +00:00
|
|
|
static void* sys_realloc (stix_mmgr_t* mmgr, void* ptr, stix_oow_t size)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return realloc (ptr, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sys_free (stix_mmgr_t* mmgr, void* ptr)
|
|
|
|
{
|
|
|
|
free (ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static stix_mmgr_t sys_mmgr =
|
|
|
|
{
|
|
|
|
sys_alloc,
|
|
|
|
sys_realloc,
|
|
|
|
sys_free,
|
|
|
|
STIX_NULL
|
|
|
|
};
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
static const stix_bch_t* get_base_name (const stix_bch_t* path)
|
|
|
|
{
|
|
|
|
const stix_bch_t* p, * last = STIX_NULL;
|
|
|
|
|
|
|
|
for (p = path; *p != '\0'; p++)
|
|
|
|
{
|
|
|
|
if (IS_PATH_SEP(*p)) last = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (last == STIX_NULL)? path: (last + 1);
|
|
|
|
}
|
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
static STIX_INLINE stix_ooi_t open_input (stix_t* stix, stix_ioarg_t* arg)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
2016-08-15 12:19:04 +00:00
|
|
|
xtn_t* xtn = stix_getxtn(stix);
|
|
|
|
bb_t* bb;
|
|
|
|
FILE* fp;
|
|
|
|
|
2015-05-15 14:55:12 +00:00
|
|
|
if (arg->includer)
|
|
|
|
{
|
|
|
|
/* includee */
|
2016-12-28 13:42:12 +00:00
|
|
|
|
2015-05-17 05:02:30 +00:00
|
|
|
stix_bch_t bcs[1024]; /* TODO: right buffer size */
|
2015-12-17 16:11:10 +00:00
|
|
|
stix_oow_t bcslen = STIX_COUNTOF(bcs);
|
2016-12-27 18:15:35 +00:00
|
|
|
stix_oow_t ucslen;
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2016-12-27 18:15:35 +00:00
|
|
|
if (stix_convootobcstr (stix, arg->name, &ucslen, bcs, &bcslen) <= -1)
|
2016-12-28 13:42:12 +00:00
|
|
|
{
|
2015-05-17 05:02:30 +00:00
|
|
|
stix_seterrnum (stix, STIX_EECERR);
|
2015-05-15 14:55:12 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-05-20 14:27:47 +00:00
|
|
|
|
2016-12-28 13:42:12 +00:00
|
|
|
|
2015-07-03 14:38:37 +00:00
|
|
|
/* TODO: make bcs relative to the includer */
|
2015-06-11 13:10:33 +00:00
|
|
|
#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__)
|
2016-08-15 12:19:04 +00:00
|
|
|
fp = fopen (bcs, "rb");
|
2015-06-11 13:10:33 +00:00
|
|
|
#else
|
2016-08-15 12:19:04 +00:00
|
|
|
fp = fopen (bcs, "r");
|
2015-06-11 13:10:33 +00:00
|
|
|
#endif
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* main stream */
|
2015-06-11 13:10:33 +00:00
|
|
|
#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__)
|
2016-08-15 12:19:04 +00:00
|
|
|
fp = fopen (xtn->source_path, "rb");
|
2015-06-11 13:10:33 +00:00
|
|
|
#else
|
2016-08-15 12:19:04 +00:00
|
|
|
fp = fopen (xtn->source_path, "r");
|
2015-06-11 13:10:33 +00:00
|
|
|
#endif
|
2015-05-15 14:55:12 +00:00
|
|
|
}
|
2015-05-17 05:02:30 +00:00
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
if (!fp)
|
2015-05-17 05:02:30 +00:00
|
|
|
{
|
|
|
|
stix_seterrnum (stix, STIX_EIOERR);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
bb = stix_callocmem (stix, STIX_SIZEOF(*bb));
|
|
|
|
if (!bb)
|
|
|
|
{
|
|
|
|
fclose (fp);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bb->fp = fp;
|
|
|
|
arg->handle = bb;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static STIX_INLINE stix_ooi_t close_input (stix_t* stix, stix_ioarg_t* arg)
|
|
|
|
{
|
|
|
|
xtn_t* xtn = stix_getxtn(stix);
|
|
|
|
bb_t* bb;
|
|
|
|
|
|
|
|
bb = (bb_t*)arg->handle;
|
2016-12-26 18:44:47 +00:00
|
|
|
STIX_ASSERT (stix, bb != STIX_NULL && bb->fp != STIX_NULL);
|
2016-08-15 12:19:04 +00:00
|
|
|
|
|
|
|
fclose (bb->fp);
|
|
|
|
stix_freemem (stix, bb);
|
|
|
|
|
2016-09-06 16:06:22 +00:00
|
|
|
arg->handle = STIX_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
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
static STIX_INLINE stix_ooi_t read_input (stix_t* stix, stix_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;
|
2016-09-23 08:56:25 +00:00
|
|
|
stix_oow_t bcslen, ucslen, remlen;
|
2015-05-16 07:31:16 +00:00
|
|
|
int x;
|
|
|
|
|
2016-09-23 08:56:25 +00:00
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
bb = (bb_t*)arg->handle;
|
2016-12-26 18:44:47 +00:00
|
|
|
STIX_ASSERT (stix, bb != STIX_NULL && bb->fp != STIX_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))
|
|
|
|
{
|
|
|
|
stix_seterrnum (stix, STIX_EIOERR);
|
|
|
|
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
|
|
|
}
|
2016-09-23 08:56:25 +00:00
|
|
|
while (bb->len < STIX_COUNTOF(bb->buf) && x != '\r' && x != '\n');
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2016-08-15 12:19:04 +00:00
|
|
|
bcslen = bb->len;
|
2015-05-17 05:02:30 +00:00
|
|
|
ucslen = STIX_COUNTOF(arg->buf);
|
2016-12-27 18:15:35 +00:00
|
|
|
x = stix_convbtooochars (stix, bb->buf, &bcslen, arg->buf, &ucslen);
|
|
|
|
x = stix_convbtooochars (stix, bb->buf, &bcslen, arg->buf, &ucslen);
|
2015-05-17 05:02:30 +00:00
|
|
|
if (x <= -1 && ucslen <= 0)
|
2015-05-16 07:31:16 +00:00
|
|
|
{
|
2015-05-17 05:02:30 +00:00
|
|
|
stix_seterrnum (stix, STIX_EECERR);
|
|
|
|
return -1;
|
2015-05-16 07:31:16 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
static stix_ooi_t input_handler (stix_t* stix, stix_iocmd_t cmd, stix_ioarg_t* arg)
|
2015-05-15 14:55:12 +00:00
|
|
|
{
|
|
|
|
switch (cmd)
|
|
|
|
{
|
|
|
|
case STIX_IO_OPEN:
|
|
|
|
return open_input (stix, arg);
|
|
|
|
|
|
|
|
case STIX_IO_CLOSE:
|
|
|
|
return close_input (stix, arg);
|
|
|
|
|
|
|
|
case STIX_IO_READ:
|
|
|
|
return read_input (stix, arg);
|
|
|
|
|
|
|
|
default:
|
|
|
|
stix->errnum = STIX_EINTERN;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
2015-05-15 14:55:12 +00:00
|
|
|
|
2016-11-27 15:37:14 +00:00
|
|
|
static void* dl_open (stix_t* stix, const stix_ooch_t* name)
|
2015-10-13 14:51:04 +00:00
|
|
|
{
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
2015-10-13 14:51:04 +00:00
|
|
|
/* TODO: support various platforms */
|
|
|
|
stix_bch_t buf[1024]; /* TODO: use a proper path buffer */
|
2015-12-17 16:11:10 +00:00
|
|
|
stix_oow_t ucslen, bcslen;
|
|
|
|
stix_oow_t len;
|
2015-10-14 13:25:36 +00:00
|
|
|
void* handle;
|
|
|
|
|
2016-08-23 00:37:22 +00:00
|
|
|
/* TODO: using MODPREFIX isn't a good idea for all kind of modules.
|
2015-10-14 13:25:36 +00:00
|
|
|
* OK to use it for a primitive module.
|
|
|
|
* NOT OK to use it for a FFI target.
|
|
|
|
* Attempting /home/hyung-hwan/xxx/lib/libstix-libc.so.6 followed by libc.so.6 is bad.
|
|
|
|
* Need to accept the type or flags?
|
|
|
|
*
|
2016-11-27 15:37:14 +00:00
|
|
|
* dl_open (stix, "xxxx", STIX_MOD_EXTERNAL);
|
2015-10-14 13:25:36 +00:00
|
|
|
* if external, don't use DEFAULT_MODPERFIX and MODPOSTFIX???
|
|
|
|
*/
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2015-10-14 09:06:44 +00:00
|
|
|
len = stix_copybcstr (buf, STIX_COUNTOF(buf), STIX_DEFAULT_MODPREFIX);
|
2015-10-13 14:51:04 +00:00
|
|
|
|
|
|
|
/* TODO: proper error checking and overflow checking */
|
|
|
|
bcslen = STIX_COUNTOF(buf) - len;
|
2016-12-27 18:15:35 +00:00
|
|
|
stix_convootobcstr (stix, name, &ucslen, &buf[len], &bcslen);
|
2015-10-13 14:51:04 +00:00
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
stix_copybcstr (&buf[bcslen + len], STIX_COUNTOF(buf) - bcslen - len, STIX_DEFAULT_MODPOSTFIX);
|
|
|
|
|
|
|
|
handle = lt_dlopenext (buf);
|
|
|
|
if (!handle)
|
|
|
|
{
|
|
|
|
buf[bcslen + len] = '\0';
|
|
|
|
handle = lt_dlopenext (&buf[len]);
|
2016-08-23 00:37:22 +00:00
|
|
|
if (handle) STIX_DEBUG2 (stix, "Opened module file %s handle %p\n", &buf[len], handle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
STIX_DEBUG2 (stix, "Opened module file %s handle %p\n", buf, handle);
|
2015-10-14 13:25:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
|
|
|
#else
|
|
|
|
/* TODO: implemenent this */
|
|
|
|
return STIX_NULL;
|
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 15:37:14 +00:00
|
|
|
static void dl_close (stix_t* stix, void* handle)
|
2015-10-13 14:51:04 +00:00
|
|
|
{
|
2016-08-23 00:37:22 +00:00
|
|
|
STIX_DEBUG1 (stix, "Closed module handle %p\n", handle);
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
|
|
|
lt_dlclose (handle);
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
FreeLibrary ((HMODULE)handle);
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
DosFreeModule ((HMODULE)handle);
|
2015-12-03 15:11:47 +00:00
|
|
|
#elif defined(__MSDOS__) && defined(QSE_ENABLE_DOS_DYNAMIC_MODULE)
|
2015-10-14 13:25:36 +00:00
|
|
|
FreeModule (handle);
|
|
|
|
#else
|
2016-12-13 15:18:19 +00:00
|
|
|
/* nothing to do */
|
2015-10-14 13:25:36 +00:00
|
|
|
#endif
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 15:37:14 +00:00
|
|
|
static void* dl_getsym (stix_t* stix, void* handle, const stix_ooch_t* name)
|
2015-10-13 14:51:04 +00:00
|
|
|
{
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
2015-10-13 14:51:04 +00:00
|
|
|
stix_bch_t buf[1024]; /* TODO: use a proper buffer. dynamically allocated if conversion result in too a large value */
|
2015-12-17 16:11:10 +00:00
|
|
|
stix_oow_t ucslen, bcslen;
|
2015-10-13 14:51:04 +00:00
|
|
|
void* sym;
|
2016-08-23 00:37:22 +00:00
|
|
|
const char* symname;
|
2015-10-13 14:51:04 +00:00
|
|
|
|
|
|
|
buf[0] = '_';
|
|
|
|
|
|
|
|
bcslen = STIX_COUNTOF(buf) - 2;
|
2016-12-27 18:15:35 +00:00
|
|
|
stix_convootobcstr (stix, name, &ucslen, &buf[1], &bcslen); /* TODO: error check */
|
2016-08-23 00:37:22 +00:00
|
|
|
symname = &buf[1];
|
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
if (!sym)
|
|
|
|
{
|
2016-08-23 00:37:22 +00:00
|
|
|
symname = &buf[0];
|
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
if (!sym)
|
|
|
|
{
|
|
|
|
buf[bcslen + 1] = '_';
|
|
|
|
buf[bcslen + 2] = '\0';
|
2016-08-23 00:37:22 +00:00
|
|
|
|
|
|
|
symname = &buf[1];
|
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
if (!sym)
|
|
|
|
{
|
2016-08-23 00:37:22 +00:00
|
|
|
symname = &buf[0];
|
|
|
|
sym = lt_dlsym (handle, symname);
|
2015-10-13 14:51:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-23 00:37:22 +00:00
|
|
|
if (sym) STIX_DEBUG2 (stix, "Loaded module symbol %s from handle %p\n", symname, handle);
|
2015-10-13 14:51:04 +00:00
|
|
|
return sym;
|
2015-10-14 13:25:36 +00:00
|
|
|
#else
|
|
|
|
/* TODO: IMPLEMENT THIS */
|
|
|
|
return STIX_NULL;
|
|
|
|
#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
|
|
|
|
2016-10-06 14:17:24 +00:00
|
|
|
static int write_all (int fd, const char* ptr, stix_oow_t len)
|
|
|
|
{
|
|
|
|
while (len > 0)
|
|
|
|
{
|
|
|
|
stix_ooi_t wr;
|
|
|
|
|
|
|
|
wr = write (1, ptr, len);
|
|
|
|
|
|
|
|
if (wr <= -1)
|
|
|
|
{
|
|
|
|
/*if (errno == EAGAIN || errno == EWOULDBLOCK)
|
|
|
|
{
|
|
|
|
push it to internal buffers? before writing data just converted, need to write buffered data first.
|
|
|
|
}*/
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr += wr;
|
|
|
|
len -= wr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-01 16:31:47 +00:00
|
|
|
static void log_write (stix_t* stix, stix_oow_t mask, const stix_ooch_t* msg, stix_oow_t len)
|
2016-05-27 15:01:54 +00:00
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
# error NOT IMPLEMENTED
|
|
|
|
|
|
|
|
#else
|
2016-06-05 18:37:28 +00:00
|
|
|
stix_bch_t buf[256];
|
2016-05-27 15:01:54 +00:00
|
|
|
stix_oow_t ucslen, bcslen, msgidx;
|
|
|
|
int n;
|
2016-10-06 14:17:24 +00:00
|
|
|
char ts[32];
|
2016-10-06 17:50:27 +00:00
|
|
|
size_t tslen;
|
2016-10-06 14:17:24 +00:00
|
|
|
struct tm tm, *tmp;
|
|
|
|
time_t now;
|
2016-05-27 15:01:54 +00:00
|
|
|
|
2016-12-03 18:08:31 +00:00
|
|
|
if (mask & STIX_LOG_GC) return; /* don't show gc logs */
|
2016-06-22 03:23:14 +00:00
|
|
|
|
2016-06-13 15:52:09 +00:00
|
|
|
/* TODO: beautify the log message.
|
|
|
|
* do classification based on mask. */
|
|
|
|
|
2016-07-01 16:31:47 +00:00
|
|
|
now = time(NULL);
|
2016-10-06 14:17:24 +00:00
|
|
|
#if defined(__MSDOS__)
|
|
|
|
tmp = localtime (&now);
|
|
|
|
#else
|
|
|
|
tmp = localtime_r (&now, &tm);
|
|
|
|
#endif
|
2016-10-06 17:50:27 +00:00
|
|
|
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp);
|
|
|
|
if (tslen == 0)
|
|
|
|
{
|
|
|
|
strcpy (ts, "0000-00-00 00:00:00 +0000");
|
|
|
|
tslen = 25;
|
|
|
|
}
|
|
|
|
write_all (1, ts, tslen);
|
2016-10-06 14:17:24 +00:00
|
|
|
|
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;
|
2016-06-01 15:33:03 +00:00
|
|
|
bcslen = STIX_COUNTOF(buf);
|
2016-05-27 15:01:54 +00:00
|
|
|
|
2016-12-27 18:15:35 +00:00
|
|
|
n = stix_convootobchars (stix, &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. */
|
|
|
|
|
2016-12-26 18:44:47 +00:00
|
|
|
STIX_ASSERT (stix, 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 */
|
2016-10-06 14:17:24 +00:00
|
|
|
if (write_all (1, 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================================================================= */
|
|
|
|
|
2016-10-06 14:17:24 +00:00
|
|
|
static stix_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' };
|
|
|
|
static stix_ooch_t str_main[] = { 'm', 'a', 'i', 'n' };
|
|
|
|
static stix_t* g_stix = STIX_NULL;
|
2016-05-17 15:12:27 +00:00
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
|
|
|
|
2016-05-18 14:53:20 +00:00
|
|
|
#if defined(__MSDOS__) && defined(_INTELC32_)
|
|
|
|
static void (*prev_timer_intr_handler) (void);
|
|
|
|
|
|
|
|
#pragma interrupt(timer_intr_handler)
|
|
|
|
static void timer_intr_handler (void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
_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. */
|
|
|
|
if (g_stix) stix_switchprocess (g_stix);
|
|
|
|
_chain_intr(prev_timer_intr_handler);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
if (g_stix) stix_switchprocess (g_stix);
|
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)
|
|
|
|
{
|
|
|
|
if (g_stix) stix_switchprocess (g_stix);
|
|
|
|
}
|
2016-05-18 14:53:20 +00:00
|
|
|
#endif
|
2016-05-17 15:12:27 +00:00
|
|
|
|
|
|
|
static void setup_tick (void)
|
|
|
|
{
|
2016-05-18 14:53:20 +00:00
|
|
|
#if defined(__MSDOS__) && defined(_INTELC32_)
|
|
|
|
|
|
|
|
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);
|
2016-05-19 03:49:23 +00:00
|
|
|
memset (&g_tmtask, 0, STIX_SIZEOF(g_tmtask));
|
|
|
|
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;
|
|
|
|
act.sa_flags = 0;
|
|
|
|
sigaction (SIGVTALRM, &act, STIX_NULL);
|
|
|
|
|
|
|
|
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;
|
|
|
|
setitimer (ITIMER_VIRTUAL, &itv, STIX_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)
|
|
|
|
{
|
2016-05-18 14:53:20 +00:00
|
|
|
#if defined(__MSDOS__) && defined(_INTELC32_)
|
|
|
|
|
|
|
|
_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;
|
|
|
|
setitimer (ITIMER_VIRTUAL, &itv, STIX_NULL);
|
|
|
|
|
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;
|
|
|
|
sigaction (SIGVTALRM, &act, STIX_NULL);
|
2016-05-18 14:53:20 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
# error UNSUPPORTED
|
2016-05-17 15:12:27 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-05-27 15:01:54 +00:00
|
|
|
/* ========================================================================= */
|
|
|
|
|
2015-05-07 15:58:04 +00:00
|
|
|
int main (int argc, char* argv[])
|
|
|
|
{
|
|
|
|
stix_t* stix;
|
2015-05-16 07:31:16 +00:00
|
|
|
xtn_t* xtn;
|
2015-10-28 14:58:58 +00:00
|
|
|
stix_oocs_t objname;
|
|
|
|
stix_oocs_t mthname;
|
2015-10-13 14:51:04 +00:00
|
|
|
stix_vmprim_t vmprim;
|
2016-05-17 15:12:27 +00:00
|
|
|
int i, xret;
|
2015-05-16 07:31:16 +00:00
|
|
|
|
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
|
|
|
{
|
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;
|
|
|
|
}
|
2015-05-28 16:51:37 +00:00
|
|
|
#endif
|
2015-05-16 07:31:16 +00:00
|
|
|
|
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;
|
|
|
|
|
2015-05-07 15:58:04 +00:00
|
|
|
|
2015-10-14 13:25:36 +00:00
|
|
|
#if defined(USE_LTDL)
|
|
|
|
lt_dlinit ();
|
|
|
|
#endif
|
|
|
|
|
2016-02-12 16:23:26 +00:00
|
|
|
stix = stix_open (&sys_mmgr, STIX_SIZEOF(xtn_t), 2048000lu, &vmprim, STIX_NULL);
|
2015-05-07 15:58:04 +00:00
|
|
|
if (!stix)
|
|
|
|
{
|
|
|
|
printf ("cannot open stix\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2015-05-28 16:51:37 +00:00
|
|
|
stix_oow_t tab_size;
|
|
|
|
|
|
|
|
tab_size = 5000;
|
2015-10-13 14:51:04 +00:00
|
|
|
stix_setoption (stix, STIX_SYMTAB_SIZE, &tab_size);
|
2015-05-28 16:51:37 +00:00
|
|
|
tab_size = 5000;
|
2015-10-13 14:51:04 +00:00
|
|
|
stix_setoption (stix, STIX_SYSDIC_SIZE, &tab_size);
|
2016-02-13 17:39:11 +00:00
|
|
|
tab_size = 600;
|
2016-02-11 14:26:26 +00:00
|
|
|
stix_setoption (stix, STIX_PROCSTK_SIZE, &tab_size);
|
2015-05-07 15:58:04 +00:00
|
|
|
}
|
|
|
|
|
2015-06-28 14:20:37 +00:00
|
|
|
{
|
|
|
|
int trait = 0;
|
|
|
|
|
2015-06-29 13:52:40 +00:00
|
|
|
/*trait |= STIX_NOGC;*/
|
2016-02-15 18:07:20 +00:00
|
|
|
trait |= STIX_AWAIT_PROCS;
|
2015-06-28 14:20:37 +00:00
|
|
|
stix_setoption (stix, STIX_TRAIT, &trait);
|
|
|
|
}
|
|
|
|
|
2015-05-26 16:31:47 +00:00
|
|
|
if (stix_ignite(stix) <= -1)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
2015-05-26 16:31:47 +00:00
|
|
|
printf ("cannot ignite stix - %d\n", stix_geterrnum(stix));
|
2015-05-07 15:58:04 +00:00
|
|
|
stix_close (stix);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-05-16 07:31:16 +00:00
|
|
|
xtn = stix_getxtn (stix);
|
2015-06-11 12:09:10 +00:00
|
|
|
|
|
|
|
#if defined(macintosh)
|
|
|
|
i = 20;
|
2015-05-28 16:51:37 +00:00
|
|
|
xtn->source_path = "test.st";
|
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
|
|
|
|
|
|
|
for (i = 1; 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:
|
2015-05-20 15:52:45 +00:00
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
if (stix_compile (stix, input_handler) <= -1)
|
|
|
|
{
|
|
|
|
if (stix->errnum == STIX_ESYNTAX)
|
2015-05-20 15:52:45 +00:00
|
|
|
{
|
2015-06-11 12:09:10 +00:00
|
|
|
stix_synerr_t synerr;
|
|
|
|
stix_bch_t bcs[1024]; /* TODO: right buffer size */
|
2015-12-17 16:11:10 +00:00
|
|
|
stix_oow_t bcslen, ucslen;
|
2015-06-11 12:09:10 +00:00
|
|
|
|
|
|
|
stix_getsynerr (stix, &synerr);
|
|
|
|
|
|
|
|
printf ("ERROR: ");
|
|
|
|
if (synerr.loc.file)
|
2015-05-20 15:52:45 +00:00
|
|
|
{
|
2015-06-11 12:09:10 +00:00
|
|
|
bcslen = STIX_COUNTOF(bcs);
|
2016-12-27 18:15:35 +00:00
|
|
|
if (stix_convootobcstr (stix, synerr.loc.file, &ucslen, bcs, &bcslen) >= 0)
|
2015-06-11 12:09:10 +00:00
|
|
|
{
|
|
|
|
printf ("%.*s ", (int)bcslen, bcs);
|
|
|
|
}
|
2015-05-20 15:52:45 +00:00
|
|
|
}
|
2015-06-12 13:52:30 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf ("%s ", xtn->source_path);
|
|
|
|
}
|
2015-05-20 15:52:45 +00:00
|
|
|
|
|
|
|
|
2016-12-28 19:12:14 +00:00
|
|
|
printf ("syntax error at line %lu column %lu - ",
|
|
|
|
(unsigned long int)synerr.loc.line, (unsigned long int)synerr.loc.colm);
|
|
|
|
|
|
|
|
bcslen = STIX_COUNTOF(bcs);
|
|
|
|
if (stix_convootobcstr (stix, stix_synerrnumtoerrstr(synerr.num), &ucslen, bcs, &bcslen) >= 0)
|
|
|
|
{
|
|
|
|
printf (" [%.*s]", (int)bcslen, bcs);
|
|
|
|
}
|
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
if (synerr.tgt.len > 0)
|
2015-05-19 15:16:18 +00:00
|
|
|
{
|
2015-06-11 12:09:10 +00:00
|
|
|
bcslen = STIX_COUNTOF(bcs);
|
|
|
|
ucslen = synerr.tgt.len;
|
|
|
|
|
2016-12-27 18:15:35 +00:00
|
|
|
if (stix_convootobchars (stix, synerr.tgt.ptr, &ucslen, bcs, &bcslen) >= 0)
|
2015-06-11 12:09:10 +00:00
|
|
|
{
|
|
|
|
printf (" [%.*s]", (int)bcslen, bcs);
|
|
|
|
}
|
2015-05-19 15:16:18 +00:00
|
|
|
|
2015-06-11 12:09:10 +00:00
|
|
|
}
|
|
|
|
printf ("\n");
|
2015-05-19 15:16:18 +00:00
|
|
|
}
|
2015-06-11 12:09:10 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf ("ERROR: cannot compile code - %d\n", stix_geterrnum(stix));
|
|
|
|
}
|
|
|
|
stix_close (stix);
|
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
|
|
|
}
|
|
|
|
|
2016-09-23 08:56:25 +00:00
|
|
|
printf ("COMPILE OK. STARTING EXECUTION ...\n");
|
2016-05-17 15:12:27 +00:00
|
|
|
xret = 0;
|
|
|
|
g_stix = stix;
|
|
|
|
setup_tick ();
|
|
|
|
|
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;
|
|
|
|
if (stix_invoke (stix, &objname, &mthname) <= -1)
|
2015-06-04 18:34:37 +00:00
|
|
|
{
|
|
|
|
printf ("ERROR: cannot execute code - %d\n", stix_geterrnum(stix));
|
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 ();
|
|
|
|
g_stix = STIX_NULL;
|
2015-06-06 07:24:35 +00:00
|
|
|
|
2016-06-13 15:52:09 +00:00
|
|
|
/*stix_dumpsymtab(stix);
|
|
|
|
*stix_dumpdic(stix, stix->sysdic, "System dictionary");*/
|
2016-06-05 18:37:28 +00:00
|
|
|
|
2015-05-07 15:58:04 +00:00
|
|
|
stix_close (stix);
|
|
|
|
|
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
|
|
|
}
|