qse/qse/lib/awk/std.c

1356 lines
27 KiB
C
Raw Normal View History

2008-08-04 08:14:52 +00:00
/*
* $Id: std.c 85 2009-02-26 10:56:12Z hyunghwan.chung $
2008-12-27 04:35:14 +00:00
*
2009-02-04 08:39:21 +00:00
Copyright 2006-2009 Chung, Hyung-Hwan.
2008-12-27 04:35:14 +00:00
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
2008-08-04 08:14:52 +00:00
*/
2008-08-21 03:17:25 +00:00
#include "awk.h"
#include <qse/awk/std.h>
2008-12-21 21:35:07 +00:00
#include <qse/cmn/sio.h>
#include <qse/cmn/pio.h>
2008-12-21 21:35:07 +00:00
#include <qse/cmn/str.h>
#include <qse/cmn/time.h>
#include <qse/utl/stdio.h> /* TODO: remove dependency on qse_vsprintf */
2008-12-11 04:19:59 +00:00
2008-08-04 08:14:52 +00:00
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
2008-08-04 08:13:03 +00:00
2008-12-16 03:56:48 +00:00
typedef struct xtn_t
{
struct
{
2009-02-16 08:31:34 +00:00
struct
{
qse_awk_parsestd_type_t type;
2009-02-16 08:31:34 +00:00
union
{
2009-02-22 06:28:02 +00:00
const qse_char_t* file;
const qse_char_t* cp;
2009-02-22 06:28:02 +00:00
struct
{
const qse_char_t* ptr;
const qse_char_t* end;
} cpl;
2009-02-18 07:55:48 +00:00
} u;
2009-02-22 06:28:02 +00:00
qse_sio_t* handle; /* the handle to an open file */
2009-02-16 08:31:34 +00:00
} in;
struct
{
qse_awk_parsestd_type_t type;
2009-02-21 23:06:45 +00:00
union
{
const qse_char_t* file;
qse_char_t* cp;
2009-02-22 06:28:02 +00:00
struct
{
qse_xstr_t* osp;
qse_char_t* ptr;
qse_char_t* end;
} cpl;
2009-02-21 23:06:45 +00:00
} u;
2009-02-16 08:31:34 +00:00
qse_sio_t* handle;
} out;
} s;
} xtn_t;
typedef struct rxtn_t
{
unsigned int seed;
2009-02-16 08:31:34 +00:00
struct
{
struct {
2009-02-18 07:55:48 +00:00
const qse_char_t*const* files;
qse_size_t index;
2009-02-16 08:31:34 +00:00
} in;
struct
{
2009-02-18 07:55:48 +00:00
const qse_char_t*const* files;
qse_size_t index;
} out;
2009-02-16 08:31:34 +00:00
} c; /* console */
} rxtn_t;
2009-02-26 04:35:22 +00:00
const qse_char_t*const qse_awk_rtx_openstd_stdio[] =
{
QSE_T(""),
QSE_NULL
};
2009-02-16 08:31:34 +00:00
static qse_real_t custom_awk_pow (qse_awk_t* awk, qse_real_t x, qse_real_t y)
2008-08-04 08:13:03 +00:00
{
#if defined(HAVE_POWL)
return powl (x, y);
#elif defined(HAVE_POW)
2008-08-04 08:13:03 +00:00
return pow (x, y);
#elif defined(HAVE_POWF)
return powf (x, y);
#else
#error ### no pow function available ###
#endif
2008-08-04 08:13:03 +00:00
}
static int custom_awk_sprintf (
2009-02-16 08:31:34 +00:00
qse_awk_t* awk, qse_char_t* buf, qse_size_t size,
2008-12-21 21:35:07 +00:00
const qse_char_t* fmt, ...)
2008-08-04 08:13:03 +00:00
{
int n;
va_list ap;
va_start (ap, fmt);
2008-12-21 21:35:07 +00:00
n = qse_vsprintf (buf, size, fmt, ap);
2008-08-04 08:13:03 +00:00
va_end (ap);
return n;
}
2009-02-17 02:11:31 +00:00
static qse_bool_t custom_awk_isccls (
qse_awk_t* awk, qse_cint_t c, qse_ccls_id_t id)
{
qse_ccls_t* ccls = QSE_CCLS_GETDFL();
return ccls->is (ccls->data, c, id);
}
static qse_cint_t custom_awk_toccls (
qse_awk_t* awk, qse_cint_t c, qse_ccls_id_t id)
{
qse_ccls_t* ccls = QSE_CCLS_GETDFL();
return ccls->to (ccls->data, c, id);
}
2008-12-21 21:35:07 +00:00
static int add_functions (qse_awk_t* awk);
qse_awk_t* qse_awk_openstd (qse_size_t xtnsize)
2008-08-04 08:13:03 +00:00
{
2008-12-21 21:35:07 +00:00
qse_awk_t* awk;
2009-02-16 08:31:34 +00:00
qse_awk_prm_t prm;
xtn_t* xtn;
2008-08-04 08:13:03 +00:00
2009-02-17 02:11:31 +00:00
prm.pow = custom_awk_pow;
prm.sprintf = custom_awk_sprintf;
prm.isccls = custom_awk_isccls;
prm.toccls = custom_awk_toccls;
2009-02-16 08:31:34 +00:00
/* create an object */
awk = qse_awk_open (
QSE_MMGR_GETDFL(), QSE_SIZEOF(xtn_t) + xtnsize, &prm);
2009-02-16 08:31:34 +00:00
if (awk == QSE_NULL) return QSE_NULL;
2008-08-04 08:13:03 +00:00
2009-02-16 08:31:34 +00:00
/* initialize extension */
2009-02-17 02:11:31 +00:00
xtn = (xtn_t*) QSE_XTN (awk);
2009-02-16 08:31:34 +00:00
QSE_MEMSET (xtn, 0, QSE_SIZEOF(xtn_t));
2008-12-16 03:56:48 +00:00
2009-02-16 08:31:34 +00:00
/* add intrinsic functions */
if (add_functions (awk) == -1)
{
2008-12-21 21:35:07 +00:00
qse_awk_close (awk);
return QSE_NULL;
}
2008-08-04 08:13:03 +00:00
return awk;
}
2008-10-01 05:14:20 +00:00
void* qse_awk_getxtnstd (qse_awk_t* awk)
{
return (void*)((xtn_t*)QSE_XTN(awk) + 1);
}
/*** PARSESTD ***/
2008-12-11 04:19:59 +00:00
2009-02-17 02:11:31 +00:00
static qse_ssize_t sf_in (
qse_awk_t* awk, qse_awk_sio_cmd_t cmd,
qse_char_t* data, qse_size_t size)
2008-10-01 05:14:20 +00:00
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = QSE_XTN (awk);
2008-10-01 05:14:20 +00:00
2009-02-17 02:11:31 +00:00
if (cmd == QSE_AWK_SIO_OPEN)
2008-10-01 05:14:20 +00:00
{
2009-02-22 06:28:02 +00:00
switch (xtn->s.in.type)
2008-10-14 05:32:58 +00:00
{
case QSE_AWK_PARSESTD_FILE:
2009-02-22 06:28:02 +00:00
if (xtn->s.in.u.file == QSE_NULL) return -1;
2008-10-01 05:14:20 +00:00
2009-02-16 08:31:34 +00:00
xtn->s.in.handle = qse_sio_open (
awk->mmgr,
2008-12-13 03:42:32 +00:00
0,
2009-02-22 06:28:02 +00:00
xtn->s.in.u.file,
2008-12-21 21:35:07 +00:00
QSE_SIO_READ
2008-12-13 03:42:32 +00:00
);
2009-02-16 08:31:34 +00:00
if (xtn->s.in.handle == QSE_NULL) return -1;
2009-02-22 06:28:02 +00:00
return 1;
2008-12-13 03:42:32 +00:00
case QSE_AWK_PARSESTD_STDIO:
2009-02-22 06:28:02 +00:00
xtn->s.in.handle = qse_sio_in;
return 1;
2008-10-01 05:14:20 +00:00
case QSE_AWK_PARSESTD_CP:
case QSE_AWK_PARSESTD_CPL:
2009-02-22 06:28:02 +00:00
xtn->s.in.handle = QSE_NULL;
return 1;
}
2008-10-01 05:14:20 +00:00
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_SIO_CLOSE)
2008-10-01 05:14:20 +00:00
{
2009-02-16 08:31:34 +00:00
if (xtn->s.in.handle != QSE_NULL &&
xtn->s.in.handle != qse_sio_in &&
xtn->s.in.handle != qse_sio_out &&
xtn->s.in.handle != qse_sio_err)
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
qse_sio_close (xtn->s.in.handle);
2008-12-12 04:05:28 +00:00
}
2008-10-01 05:14:20 +00:00
return 0;
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_SIO_READ)
2008-10-01 05:14:20 +00:00
{
2009-02-22 06:28:02 +00:00
switch (xtn->s.in.type)
2008-12-11 04:19:59 +00:00
{
case QSE_AWK_PARSESTD_FILE:
case QSE_AWK_PARSESTD_STDIO:
2009-02-22 06:28:02 +00:00
QSE_ASSERT (xtn->s.in.handle != QSE_NULL);
return qse_sio_getsn (xtn->s.in.handle, data, size);
2008-12-13 03:42:32 +00:00
case QSE_AWK_PARSESTD_CP:
2008-12-11 04:19:59 +00:00
{
2009-02-22 06:28:02 +00:00
qse_size_t n = 0;
while (n < size && *xtn->s.in.u.cp != QSE_T('\0'))
2008-12-13 03:42:32 +00:00
{
data[n++] = *xtn->s.in.u.cp++;
2008-12-13 03:42:32 +00:00
}
2009-02-22 06:28:02 +00:00
return n;
2008-12-11 04:19:59 +00:00
}
2009-02-22 06:28:02 +00:00
case QSE_AWK_PARSESTD_CPL:
2008-12-11 04:19:59 +00:00
{
2009-02-22 06:28:02 +00:00
qse_size_t n = 0;
while (n < size && xtn->s.in.u.cpl.ptr < xtn->s.in.u.cpl.end)
2009-02-22 06:28:02 +00:00
{
data[n++] = *xtn->s.in.u.cpl.ptr++;
2009-02-22 06:28:02 +00:00
}
return n;
2008-12-11 04:19:59 +00:00
}
2009-02-22 06:28:02 +00:00
2008-10-01 05:14:20 +00:00
}
}
return -1;
}
2009-02-17 02:11:31 +00:00
static qse_ssize_t sf_out (
qse_awk_t* awk, qse_awk_sio_cmd_t cmd,
qse_char_t* data, qse_size_t size)
2008-10-01 05:14:20 +00:00
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = QSE_XTN (awk);
2008-10-14 05:32:58 +00:00
2009-02-17 02:11:31 +00:00
if (cmd == QSE_AWK_SIO_OPEN)
2008-10-14 05:32:58 +00:00
{
2009-02-22 06:28:02 +00:00
switch (xtn->s.out.type)
2008-10-14 05:32:58 +00:00
{
case QSE_AWK_PARSESTD_FILE:
2009-02-22 06:28:02 +00:00
if (xtn->s.out.u.file == QSE_NULL) return -1;
2008-10-01 05:14:20 +00:00
2009-02-22 06:28:02 +00:00
xtn->s.out.handle = qse_sio_open (
awk->mmgr,
0,
xtn->s.out.u.file,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE
);
if (xtn->s.out.handle == QSE_NULL) return -1;
return 1;
case QSE_AWK_PARSESTD_STDIO:
2009-02-22 06:28:02 +00:00
xtn->s.out.handle = qse_sio_out;
return 1;
case QSE_AWK_PARSESTD_CP:
case QSE_AWK_PARSESTD_CPL:
2009-02-22 06:28:02 +00:00
xtn->s.out.handle = QSE_NULL;
return 1;
}
2008-10-14 05:32:58 +00:00
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_SIO_CLOSE)
2008-10-01 05:14:20 +00:00
{
2009-02-22 06:28:02 +00:00
switch (xtn->s.out.type)
2008-12-12 04:05:28 +00:00
{
case QSE_AWK_PARSESTD_FILE:
case QSE_AWK_PARSESTD_STDIO:
2008-12-12 04:05:28 +00:00
2009-02-22 06:28:02 +00:00
qse_sio_flush (xtn->s.out.handle);
if (xtn->s.out.handle != qse_sio_in &&
xtn->s.out.handle != qse_sio_out &&
xtn->s.out.handle != qse_sio_err)
{
qse_sio_close (xtn->s.out.handle);
}
return 0;
case QSE_AWK_PARSESTD_CP:
*xtn->s.out.u.cp = QSE_T('\0');
2009-02-22 06:28:02 +00:00
return 0;
case QSE_AWK_PARSESTD_CPL:
xtn->s.out.u.cpl.osp->len =
xtn->s.out.u.cpl.ptr -
xtn->s.out.u.cpl.osp->ptr;
2009-02-22 06:28:02 +00:00
return 0;
}
2008-10-01 05:14:20 +00:00
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_SIO_WRITE)
2008-10-01 05:14:20 +00:00
{
2009-02-22 06:28:02 +00:00
switch (xtn->s.out.type)
{
case QSE_AWK_PARSESTD_FILE:
case QSE_AWK_PARSESTD_STDIO:
2009-02-22 06:28:02 +00:00
QSE_ASSERT (xtn->s.out.handle != QSE_NULL);
return qse_sio_putsn (xtn->s.out.handle, data, size);
case QSE_AWK_PARSESTD_CP:
2009-02-22 06:28:02 +00:00
{
qse_size_t n = 0;
while (n < size && *xtn->s.out.u.cp != QSE_T('\0'))
2009-02-22 06:28:02 +00:00
{
*xtn->s.out.u.cp++ = data[n++];
2009-02-22 06:28:02 +00:00
}
return n;
}
case QSE_AWK_PARSESTD_CPL:
2009-02-22 06:28:02 +00:00
{
qse_size_t n = 0;
while (n < size && xtn->s.out.u.cpl.ptr < xtn->s.out.u.cpl.end)
2009-02-22 06:28:02 +00:00
{
*xtn->s.out.u.cpl.ptr++ = data[n++];
2009-02-22 06:28:02 +00:00
}
return n;
}
}
2008-10-01 05:14:20 +00:00
}
return -1;
}
int qse_awk_parsestd (
2009-02-21 23:06:45 +00:00
qse_awk_t* awk,
const qse_awk_parsestd_in_t* in,
qse_awk_parsestd_out_t* out)
2008-10-01 05:14:20 +00:00
{
qse_awk_sio_t sio;
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
2008-10-01 05:14:20 +00:00
2009-02-22 08:16:35 +00:00
if (in == QSE_NULL)
2008-10-14 05:32:58 +00:00
{
2009-02-22 08:16:35 +00:00
/* the input is a must */
qse_awk_seterrnum (awk, QSE_AWK_EINVAL);
return -1;
2009-02-21 23:06:45 +00:00
}
2009-02-22 06:28:02 +00:00
2009-02-22 08:16:35 +00:00
switch (in->type)
2008-12-11 04:19:59 +00:00
{
case QSE_AWK_PARSESTD_FILE:
2009-02-22 08:16:35 +00:00
xtn->s.in.u.file = in->u.file;
2009-02-22 06:28:02 +00:00
break;
case QSE_AWK_PARSESTD_CP:
xtn->s.in.u.cp = in->u.cp;
2009-02-22 06:28:02 +00:00
break;
case QSE_AWK_PARSESTD_CPL:
xtn->s.in.u.cpl.ptr = in->u.cpl.ptr;
xtn->s.in.u.cpl.end = in->u.cpl.ptr + in->u.cpl.len;
2009-02-22 06:28:02 +00:00
break;
case QSE_AWK_PARSESTD_STDIO:
2009-02-22 06:28:02 +00:00
/* nothing to do */
break;
default:
qse_awk_seterrnum (awk, QSE_AWK_EINVAL);
return -1;
2008-12-11 04:19:59 +00:00
}
2009-02-22 08:16:35 +00:00
xtn->s.in.type = in->type;
2009-02-16 08:31:34 +00:00
xtn->s.in.handle = QSE_NULL;
2009-02-22 08:16:35 +00:00
sio.in = sf_in;
2008-12-13 03:42:32 +00:00
2009-02-22 08:16:35 +00:00
if (out == QSE_NULL) sio.out = QSE_NULL;
else
{
switch (out->type)
{
case QSE_AWK_PARSESTD_FILE:
2009-02-22 08:16:35 +00:00
xtn->s.out.u.file = out->u.file;
break;
case QSE_AWK_PARSESTD_CP:
xtn->s.out.u.cp = out->u.cp;
2009-02-22 08:16:35 +00:00
break;
case QSE_AWK_PARSESTD_CPL:
xtn->s.out.u.cpl.osp = &out->u.cpl;
xtn->s.out.u.cpl.ptr = out->u.cpl.ptr;
xtn->s.out.u.cpl.end = out->u.cpl.ptr + out->u.cpl.len;
2009-02-22 08:16:35 +00:00
break;
case QSE_AWK_PARSESTD_STDIO:
2009-02-22 08:16:35 +00:00
/* nothing to do */
break;
default:
qse_awk_seterrnum (awk, QSE_AWK_EINVAL);
return -1;
}
xtn->s.out.type = out->type;
xtn->s.out.handle = QSE_NULL;
sio.out = sf_out;
}
2008-10-01 05:14:20 +00:00
2008-12-21 21:35:07 +00:00
return qse_awk_parse (awk, &sio);
2008-10-01 05:14:20 +00:00
}
/*** RTX_OPENSTD ***/
2009-02-16 08:31:34 +00:00
static qse_ssize_t awk_rio_pipe (
2009-02-17 02:11:31 +00:00
qse_awk_rtx_t* rtx, qse_awk_rio_cmd_t cmd, qse_awk_riod_t* riod,
2009-02-16 08:31:34 +00:00
qse_char_t* data, qse_size_t size)
2008-12-12 04:05:28 +00:00
{
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_OPEN:
2008-12-12 04:05:28 +00:00
{
qse_pio_t* handle;
int flags;
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
if (riod->mode == QSE_AWK_RIO_PIPE_READ)
2008-12-12 04:05:28 +00:00
{
/* TODO: should we specify ERRTOOUT? */
flags = QSE_PIO_READOUT |
QSE_PIO_ERRTOOUT;
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
else if (riod->mode == QSE_AWK_RIO_PIPE_WRITE)
2008-12-12 04:05:28 +00:00
{
flags = QSE_PIO_WRITEIN;
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
else if (riod->mode == QSE_AWK_RIO_PIPE_RW)
{
flags = QSE_PIO_READOUT |
QSE_PIO_ERRTOOUT |
QSE_PIO_WRITEIN;
}
2008-12-12 04:05:28 +00:00
else return -1; /* TODO: any way to set the error number? */
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("opening %s of type %d (pipe)\n"), riod->name, riod->type);*/
2008-12-12 04:05:28 +00:00
handle = qse_pio_open (
2009-02-16 08:31:34 +00:00
rtx->awk->mmgr,
0,
2009-02-16 08:31:34 +00:00
riod->name,
flags|QSE_PIO_SHELL|QSE_PIO_TEXT
);
2008-12-21 21:35:07 +00:00
if (handle == QSE_NULL) return -1;
2009-02-16 08:31:34 +00:00
riod->handle = (void*)handle;
2008-12-12 04:05:28 +00:00
return 1;
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_CLOSE:
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("closing %s of type (pipe) %d\n"), riod->name, riod->type);*/
qse_pio_close ((qse_pio_t*)riod->handle);
riod->handle = QSE_NULL;
2008-12-12 04:05:28 +00:00
return 0;
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_READ:
2008-12-12 04:05:28 +00:00
{
return qse_pio_read (
2009-02-16 08:31:34 +00:00
(qse_pio_t*)riod->handle,
2008-12-12 04:05:28 +00:00
data,
size,
QSE_PIO_OUT
2008-12-12 04:05:28 +00:00
);
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_WRITE:
2008-12-12 04:05:28 +00:00
{
return qse_pio_write (
2009-02-16 08:31:34 +00:00
(qse_pio_t*)riod->handle,
2008-12-12 04:05:28 +00:00
data,
size,
QSE_PIO_IN
2008-12-12 04:05:28 +00:00
);
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_FLUSH:
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
/*if (riod->mode == QSE_AWK_RIO_PIPE_READ) return -1;*/
return qse_pio_flush ((qse_pio_t*)riod->handle, QSE_PIO_IN);
2008-12-12 04:05:28 +00:00
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_NEXT:
2008-12-12 04:05:28 +00:00
{
return -1;
}
}
return -1;
}
2009-02-16 08:31:34 +00:00
static qse_ssize_t awk_rio_file (
2009-02-17 02:11:31 +00:00
qse_awk_rtx_t* rtx, qse_awk_rio_cmd_t cmd, qse_awk_riod_t* riod,
2009-02-16 08:31:34 +00:00
qse_char_t* data, qse_size_t size)
2008-12-12 04:05:28 +00:00
{
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_OPEN:
2008-12-12 04:05:28 +00:00
{
qse_fio_t* handle;
int flags;
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
if (riod->mode == QSE_AWK_RIO_FILE_READ)
2008-12-12 04:05:28 +00:00
{
flags = QSE_FIO_READ;
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
else if (riod->mode == QSE_AWK_RIO_FILE_WRITE)
2008-12-12 04:05:28 +00:00
{
flags = QSE_FIO_WRITE |
2009-02-22 06:28:02 +00:00
QSE_FIO_CREATE |
QSE_FIO_TRUNCATE;
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
else if (riod->mode == QSE_AWK_RIO_FILE_APPEND)
2008-12-12 04:05:28 +00:00
{
flags = QSE_FIO_APPEND |
2009-02-22 06:28:02 +00:00
QSE_FIO_CREATE;
2008-12-12 04:05:28 +00:00
}
else return -1; /* TODO: any way to set the error number? */
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("opening %s of type %d (file)\n"), riod->name, riod->type);*/
handle = qse_fio_open (
2009-02-16 08:31:34 +00:00
rtx->awk->mmgr,
2008-12-12 04:05:28 +00:00
0,
2009-02-16 08:31:34 +00:00
riod->name,
flags | QSE_FIO_TEXT,
QSE_FIO_RUSR | QSE_FIO_WUSR |
QSE_FIO_RGRP | QSE_FIO_ROTH
2008-12-12 04:05:28 +00:00
);
2008-12-21 21:35:07 +00:00
if (handle == QSE_NULL)
2008-12-12 04:05:28 +00:00
{
2008-12-21 21:35:07 +00:00
qse_cstr_t errarg;
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
errarg.ptr = riod->name;
errarg.len = qse_strlen(riod->name);
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
qse_awk_rtx_seterror (rtx, QSE_AWK_EOPEN, 0, &errarg);
2008-12-12 04:05:28 +00:00
return -1;
}
2009-02-16 08:31:34 +00:00
riod->handle = (void*)handle;
2008-12-12 04:05:28 +00:00
return 1;
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_CLOSE:
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("closing %s of type %d (file)\n"), riod->name, riod->type);*/
qse_fio_close ((qse_fio_t*)riod->handle);
riod->handle = QSE_NULL;
2008-12-12 04:05:28 +00:00
return 0;
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_READ:
2008-12-12 04:05:28 +00:00
{
return qse_fio_read (
2009-02-16 08:31:34 +00:00
(qse_fio_t*)riod->handle,
2008-12-12 04:05:28 +00:00
data,
size
);
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_WRITE:
2008-12-12 04:05:28 +00:00
{
return qse_fio_write (
2009-02-16 08:31:34 +00:00
(qse_fio_t*)riod->handle,
2008-12-12 04:05:28 +00:00
data,
size
);
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_FLUSH:
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
return qse_fio_flush ((qse_fio_t*)riod->handle);
2008-12-12 04:05:28 +00:00
}
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_NEXT:
2008-12-12 04:05:28 +00:00
{
return -1;
}
}
return -1;
}
2009-02-16 08:31:34 +00:00
static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_riod_t* riod)
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("opening console[%s] of type %x\n"), riod->name, riod->type);*/
2009-02-16 08:31:34 +00:00
if (riod->mode == QSE_AWK_RIO_CONSOLE_READ)
{
if (rxtn->c.in.files == QSE_NULL)
{
/* no input console file given */
return -1;
}
2009-02-16 08:31:34 +00:00
if (rxtn->c.in.files[rxtn->c.in.index] == QSE_NULL)
{
/* no more input file */
2008-12-31 00:08:03 +00:00
/*dprint (QSE_T("console - no more file\n"));*/
return 0;
}
2009-02-16 08:31:34 +00:00
if (rxtn->c.in.files[rxtn->c.in.index][0] == QSE_T('\0'))
{
2008-12-31 00:08:03 +00:00
/*dprint (QSE_T(" console(r) - <standard input>\n"));*/
2009-02-16 08:31:34 +00:00
riod->handle = qse_sio_in;
}
else
{
/* a temporary variable sio is used here not to change
2009-02-16 08:31:34 +00:00
* any fields of riod when the open operation fails */
qse_sio_t* sio;
sio = qse_sio_open (
2009-02-16 08:31:34 +00:00
rtx->awk->mmgr,
0,
2009-02-16 08:31:34 +00:00
rxtn->c.in.files[rxtn->c.in.index],
2008-12-21 21:35:07 +00:00
QSE_SIO_READ
);
if (sio == QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_cstr_t errarg;
2009-02-16 08:31:34 +00:00
errarg.ptr = rxtn->c.in.files[rxtn->c.in.index];
errarg.len = qse_strlen(rxtn->c.in.files[rxtn->c.in.index]);
2009-02-16 08:31:34 +00:00
qse_awk_rtx_seterror (rtx, QSE_AWK_EOPEN, 0, &errarg);
return -1;
}
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T(" console(r) - %s\n"), rxtn->c.in.files[rxtn->c.in.index]);*/
if (qse_awk_rtx_setfilename (
2009-02-16 08:31:34 +00:00
rtx, rxtn->c.in.files[rxtn->c.in.index],
qse_strlen(rxtn->c.in.files[rxtn->c.in.index])) == -1)
{
qse_sio_close (sio);
return -1;
}
riod->handle = sio;
}
2009-02-16 08:31:34 +00:00
rxtn->c.in.index++;
return 1;
}
2009-02-16 08:31:34 +00:00
else if (riod->mode == QSE_AWK_RIO_CONSOLE_WRITE)
{
if (rxtn->c.out.files == QSE_NULL)
{
/* no output console file given */
return -1;
}
if (rxtn->c.out.files[rxtn->c.out.index] == QSE_NULL)
{
/* no more input file */
/*dprint (QSE_T("console - no more file\n"));*/
return 0;
}
2009-02-17 08:22:42 +00:00
if (rxtn->c.out.files[rxtn->c.out.index][0] == QSE_T('\0'))
{
/*dprint (QSE_T(" console(w) - <standard output>\n"));*/
riod->handle = qse_sio_out;
}
else
{
/* a temporary variable sio is used here not to change
* any fields of riod when the open operation fails */
qse_sio_t* sio;
sio = qse_sio_open (
rtx->awk->mmgr,
0,
rxtn->c.out.files[rxtn->c.out.index],
QSE_SIO_READ
);
if (sio == QSE_NULL)
{
qse_cstr_t errarg;
errarg.ptr = rxtn->c.out.files[rxtn->c.out.index];
errarg.len = qse_strlen(rxtn->c.out.files[rxtn->c.out.index]);
qse_awk_rtx_seterror (rtx, QSE_AWK_EOPEN, 0, &errarg);
return -1;
}
/*dprint (QSE_T(" console(w) - %s\n"), rxtn->c.out.files[rxtn->c.out.index]);*/
if (qse_awk_rtx_setofilename (
rtx, rxtn->c.out.files[rxtn->c.out.index],
qse_strlen(rxtn->c.out.files[rxtn->c.out.index])) == -1)
{
qse_sio_close (sio);
return -1;
}
riod->handle = sio;
}
rxtn->c.out.index++;
return 1;
}
return -1;
}
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
static qse_ssize_t awk_rio_console (
2009-02-17 02:11:31 +00:00
qse_awk_rtx_t* rtx, qse_awk_rio_cmd_t cmd, qse_awk_riod_t* riod,
2009-02-16 08:31:34 +00:00
qse_char_t* data, qse_size_t size)
2008-12-12 04:05:28 +00:00
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2008-12-12 04:05:28 +00:00
2009-02-17 02:11:31 +00:00
if (cmd == QSE_AWK_RIO_OPEN)
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
return open_rio_console (rtx, riod);
2008-12-12 04:05:28 +00:00
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_RIO_CLOSE)
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("closing console of type %x\n"), riod->type);*/
2009-02-16 08:31:34 +00:00
if (riod->handle != QSE_NULL &&
riod->handle != qse_sio_in &&
riod->handle != qse_sio_out &&
riod->handle != qse_sio_err)
{
2009-02-16 08:31:34 +00:00
qse_sio_close ((qse_sio_t*)riod->handle);
}
return 0;
2008-12-12 04:05:28 +00:00
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_RIO_READ)
2008-12-12 04:05:28 +00:00
{
2008-12-21 21:35:07 +00:00
qse_ssize_t n;
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
while ((n = qse_sio_getsn((qse_sio_t*)riod->handle,data,size)) == 0)
2008-12-12 04:05:28 +00:00
{
/* it has reached the end of the current file.
* open the next file if available */
2009-02-16 08:31:34 +00:00
if (rxtn->c.in.files[rxtn->c.in.index] == QSE_NULL)
2008-12-12 04:05:28 +00:00
{
/* no more input console */
return 0;
}
2009-02-16 08:31:34 +00:00
if (rxtn->c.in.files[rxtn->c.in.index][0] == QSE_T('\0'))
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
if (riod->handle != QSE_NULL &&
riod->handle != qse_sio_in &&
riod->handle != qse_sio_out &&
riod->handle != qse_sio_err)
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
qse_sio_close ((qse_sio_t*)riod->handle);
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
riod->handle = qse_sio_in;
2008-12-12 04:05:28 +00:00
}
else
{
qse_sio_t* sio;
2008-12-12 04:05:28 +00:00
sio = qse_sio_open (
2009-02-16 08:31:34 +00:00
rtx->awk->mmgr,
2008-12-12 04:05:28 +00:00
0,
2009-02-16 08:31:34 +00:00
rxtn->c.in.files[rxtn->c.in.index],
2008-12-21 21:35:07 +00:00
QSE_SIO_READ
2008-12-12 04:05:28 +00:00
);
if (sio == QSE_NULL)
2008-12-12 04:05:28 +00:00
{
2008-12-21 21:35:07 +00:00
qse_cstr_t errarg;
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
errarg.ptr = rxtn->c.in.files[rxtn->c.in.index];
errarg.len = qse_strlen(rxtn->c.in.files[rxtn->c.in.index]);
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
qse_awk_rtx_seterror (rtx, QSE_AWK_EOPEN, 0, &errarg);
2008-12-12 04:05:28 +00:00
return -1;
}
if (qse_awk_rtx_setfilename (
2009-02-16 08:31:34 +00:00
rtx, rxtn->c.in.files[rxtn->c.in.index],
qse_strlen(rxtn->c.in.files[rxtn->c.in.index])) == -1)
2008-12-12 04:05:28 +00:00
{
qse_sio_close (sio);
2008-12-12 04:05:28 +00:00
return -1;
}
if (qse_awk_rtx_setgbl (
2009-02-16 08:31:34 +00:00
rtx, QSE_AWK_GBL_FNR, qse_awk_val_zero) == -1)
2008-12-12 04:05:28 +00:00
{
/* need to reset FNR */
qse_sio_close (sio);
2008-12-12 04:05:28 +00:00
return -1;
}
2009-02-16 08:31:34 +00:00
if (riod->handle != QSE_NULL &&
riod->handle != qse_sio_in &&
riod->handle != qse_sio_out &&
riod->handle != qse_sio_err)
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
qse_sio_close ((qse_sio_t*)riod->handle);
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("open the next console [%s]\n"), rxtn->c.in.files[rxtn->c.in.index]);*/
riod->handle = sio;
2008-12-12 04:05:28 +00:00
}
2009-02-16 08:31:34 +00:00
rxtn->c.in.index++;
2008-12-12 04:05:28 +00:00
}
return n;
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_RIO_WRITE)
2008-12-12 04:05:28 +00:00
{
return qse_sio_putsn (
2009-02-16 08:31:34 +00:00
(qse_sio_t*)riod->handle,
2008-12-12 04:05:28 +00:00
data,
size
);
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_RIO_FLUSH)
2008-12-12 04:05:28 +00:00
{
2009-02-16 08:31:34 +00:00
return qse_sio_flush ((qse_sio_t*)riod->handle);
2008-12-12 04:05:28 +00:00
}
2009-02-17 02:11:31 +00:00
else if (cmd == QSE_AWK_RIO_NEXT)
2008-12-12 04:05:28 +00:00
{
int n;
qse_sio_t* sio = (qse_sio_t*)riod->handle;
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
/*dprint (QSE_T("switching console[%s] of type %x\n"), riod->name, riod->type);*/
2008-12-12 04:05:28 +00:00
2009-02-16 08:31:34 +00:00
n = open_rio_console (rtx, riod);
if (n == -1) return -1;
2008-12-12 04:05:28 +00:00
if (n == 0)
2008-12-12 04:05:28 +00:00
{
/* if there is no more file, keep the previous handle */
2008-12-12 04:05:28 +00:00
return 0;
}
if (sio != QSE_NULL &&
sio != qse_sio_in &&
sio != qse_sio_out &&
sio != qse_sio_err)
2008-12-12 04:05:28 +00:00
{
qse_sio_close (sio);
2008-12-12 04:05:28 +00:00
}
return n;
2008-12-12 04:05:28 +00:00
}
return -1;
}
qse_awk_rtx_t* qse_awk_rtx_openstd (
2009-02-22 06:28:02 +00:00
qse_awk_t* awk,
2009-02-26 04:35:22 +00:00
const qse_char_t*const icf[],
const qse_char_t*const ocf[])
2009-02-13 04:55:25 +00:00
{
qse_awk_rtx_t* rtx;
2009-02-13 04:55:25 +00:00
qse_awk_rio_t rio;
rxtn_t* rxtn;
qse_ntime_t now;
2009-02-16 08:31:34 +00:00
rio.pipe = awk_rio_pipe;
rio.file = awk_rio_file;
rio.console = awk_rio_console;
2009-02-13 04:55:25 +00:00
rtx = qse_awk_rtx_open (
awk,
QSE_SIZEOF(rxtn_t),
2009-02-13 04:55:25 +00:00
&rio,
QSE_NULL/*runarg*/
);
if (rtx == QSE_NULL) return QSE_NULL;
2009-02-17 02:11:31 +00:00
rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
QSE_MEMSET (rxtn, 0, QSE_SIZEOF(rxtn_t));
2009-02-13 04:55:25 +00:00
if (qse_gettime (&now) == -1) rxtn->seed = 0;
else rxtn->seed = (unsigned int) now;
2009-02-13 04:55:25 +00:00
srand (rxtn->seed);
2009-02-16 08:31:34 +00:00
rxtn->c.in.files = icf;
rxtn->c.in.index = 0;
rxtn->c.out.files = ocf;
rxtn->c.out.index = 0;
2009-02-13 04:55:25 +00:00
return rtx;
}
2008-12-16 03:56:48 +00:00
/*** EXTRA BUILTIN FUNCTIONS ***/
enum
{
FNC_MATH_LD,
FNC_MATH_D,
FNC_MATH_F
};
static int fnc_math_1 (
qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl, int type, void* f)
{
2008-12-21 21:35:07 +00:00
qse_size_t nargs;
qse_awk_val_t* a0;
qse_long_t lv;
qse_real_t rv;
qse_awk_val_t* r;
int n;
nargs = qse_awk_rtx_getnargs (run);
2008-12-21 21:35:07 +00:00
QSE_ASSERT (nargs == 1);
a0 = qse_awk_rtx_getarg (run, 0);
n = qse_awk_rtx_valtonum (run, a0, &lv, &rv);
if (n == -1) return -1;
2008-12-21 21:35:07 +00:00
if (n == 0) rv = (qse_real_t)lv;
if (type == FNC_MATH_LD)
{
long double (*rf) (long double) =
(long double(*)(long double))f;
r = qse_awk_rtx_makerealval (run, rf(rv));
}
else if (type == FNC_MATH_D)
{
double (*rf) (double) = (double(*)(double))f;
r = qse_awk_rtx_makerealval (run, rf(rv));
}
else
{
QSE_ASSERT (type == FNC_MATH_F);
float (*rf) (float) = (float(*)(float))f;
r = qse_awk_rtx_makerealval (run, rf(rv));
}
2008-12-21 21:35:07 +00:00
if (r == QSE_NULL)
{
qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM);
return -1;
}
qse_awk_rtx_setretval (run, r);
return 0;
}
static int fnc_math_2 (
qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl, int type, void* f)
{
2008-12-21 21:35:07 +00:00
qse_size_t nargs;
qse_awk_val_t* a0, * a1;
qse_long_t lv0, lv1;
qse_real_t rv0, rv1;
qse_awk_val_t* r;
int n;
nargs = qse_awk_rtx_getnargs (run);
2008-12-21 21:35:07 +00:00
QSE_ASSERT (nargs == 2);
a0 = qse_awk_rtx_getarg (run, 0);
a1 = qse_awk_rtx_getarg (run, 1);
n = qse_awk_rtx_valtonum (run, a0, &lv0, &rv0);
if (n == -1) return -1;
2008-12-21 21:35:07 +00:00
if (n == 0) rv0 = (qse_real_t)lv0;
n = qse_awk_rtx_valtonum (run, a1, &lv1, &rv1);
if (n == -1) return -1;
2008-12-21 21:35:07 +00:00
if (n == 0) rv1 = (qse_real_t)lv1;
if (type == FNC_MATH_LD)
{
long double (*rf) (long double,long double) =
(long double(*)(long double,long double))f;
r = qse_awk_rtx_makerealval (run, rf(rv0,rv1));
}
else if (type == FNC_MATH_D)
{
double (*rf) (double,double) = (double(*)(double,double))f;
r = qse_awk_rtx_makerealval (run, rf(rv0,rv1));
}
else
{
QSE_ASSERT (type == FNC_MATH_F);
float (*rf) (float,float) = (float(*)(float,float))f;
r = qse_awk_rtx_makerealval (run, rf(rv0,rv1));
}
2008-12-21 21:35:07 +00:00
if (r == QSE_NULL)
{
qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM);
return -1;
}
qse_awk_rtx_setretval (run, r);
return 0;
}
static int fnc_sin (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_SINL)
FNC_MATH_LD, (void*)sinl
#elif defined(HAVE_SIN)
FNC_MATH_D, (void*)sin
#elif defined(HAVE_SINF)
FNC_MATH_F, (void*)sinf
#else
#error ### no sin function available ###
#endif
);
}
static int fnc_cos (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_COSL)
FNC_MATH_LD, (void*)cosl
#elif defined(HAVE_COS)
FNC_MATH_D, (void*)cos
#elif defined(HAVE_COSF)
FNC_MATH_F, (void*)cosf
#else
#error ### no cos function available ###
#endif
);
}
static int fnc_tan (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_TANL)
FNC_MATH_LD, (void*)tanl
#elif defined(HAVE_TAN)
FNC_MATH_D, (void*)tan
#elif defined(HAVE_TANF)
FNC_MATH_F, (void*)tanf
#else
#error ### no tan function available ###
#endif
);
}
static int fnc_atan (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_ATANL)
FNC_MATH_LD, (void*)atanl
#elif defined(HAVE_ATAN)
FNC_MATH_D, (void*)atan
#elif defined(HAVE_ATANF)
FNC_MATH_F, (void*)atanf
#else
#error ### no atan function available ###
#endif
);
}
static int fnc_atan2 (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_2 (
run, fnm, fnl,
#if defined(HAVE_ATAN2L)
FNC_MATH_LD, (void*)atan2l
#elif defined(HAVE_ATAN2)
FNC_MATH_D, (void*)atan2
#elif defined(HAVE_ATAN2F)
FNC_MATH_F, (void*)atan2f
#else
#error ### no atan2 function available ###
#endif
);
}
static int fnc_log (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_LOGL)
FNC_MATH_LD, (void*)logl
#elif defined(HAVE_LOG)
FNC_MATH_D, (void*)log
#elif defined(HAVE_LOGF)
FNC_MATH_F, (void*)logf
#else
#error ### no log function available ###
#endif
);
}
static int fnc_exp (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_EXPL)
FNC_MATH_LD, (void*)expl
#elif defined(HAVE_EXP)
FNC_MATH_D, (void*)exp
#elif defined(HAVE_EXPF)
FNC_MATH_F, (void*)expf
#else
#error ### no exp function available ###
#endif
);
}
static int fnc_sqrt (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
return fnc_math_1 (
run, fnm, fnl,
#if defined(HAVE_SQRTL)
FNC_MATH_LD, (void*)sqrtl
#elif defined(HAVE_SQRT)
FNC_MATH_D, (void*)sqrt
#elif defined(HAVE_SQRTF)
FNC_MATH_F, (void*)sqrtf
#else
#error ### no sqrt function available ###
#endif
);
}
static int fnc_int (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
2008-12-16 03:56:48 +00:00
{
2008-12-21 21:35:07 +00:00
qse_size_t nargs;
qse_awk_val_t* a0;
qse_long_t lv;
qse_real_t rv;
qse_awk_val_t* r;
2008-12-16 03:56:48 +00:00
int n;
nargs = qse_awk_rtx_getnargs (run);
2008-12-21 21:35:07 +00:00
QSE_ASSERT (nargs == 1);
2008-12-16 03:56:48 +00:00
a0 = qse_awk_rtx_getarg (run, 0);
2008-12-16 03:56:48 +00:00
n = qse_awk_rtx_valtonum (run, a0, &lv, &rv);
2008-12-16 03:56:48 +00:00
if (n == -1) return -1;
2008-12-21 21:35:07 +00:00
if (n == 1) lv = (qse_long_t)rv;
2008-12-16 03:56:48 +00:00
r = qse_awk_rtx_makeintval (run, lv);
2008-12-21 21:35:07 +00:00
if (r == QSE_NULL)
{
qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM);
return -1;
}
qse_awk_rtx_setretval (run, r);
return 0;
}
static int fnc_rand (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
2008-12-21 21:35:07 +00:00
qse_awk_val_t* r;
2008-12-16 03:56:48 +00:00
r = qse_awk_rtx_makeintval (run, rand());
2008-12-21 21:35:07 +00:00
if (r == QSE_NULL)
2008-12-16 03:56:48 +00:00
{
qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM);
2008-12-16 03:56:48 +00:00
return -1;
}
qse_awk_rtx_setretval (run, r);
2008-12-16 03:56:48 +00:00
return 0;
}
static int fnc_srand (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
2008-12-21 21:35:07 +00:00
qse_size_t nargs;
qse_awk_val_t* a0;
qse_long_t lv;
qse_real_t rv;
qse_awk_val_t* r;
int n;
unsigned int prev;
rxtn_t* rxtn;
2009-02-17 02:11:31 +00:00
rxtn = (rxtn_t*) QSE_XTN (run);
nargs = qse_awk_rtx_getnargs (run);
2008-12-21 21:35:07 +00:00
QSE_ASSERT (nargs == 0 || nargs == 1);
prev = rxtn->seed;
if (nargs == 1)
{
a0 = qse_awk_rtx_getarg (run, 0);
n = qse_awk_rtx_valtonum (run, a0, &lv, &rv);
if (n == -1) return -1;
2008-12-21 21:35:07 +00:00
if (n == 1) lv = (qse_long_t)rv;
rxtn->seed = lv;
}
else
{
2008-12-21 21:35:07 +00:00
qse_ntime_t now;
2008-12-21 21:35:07 +00:00
if (qse_gettime(&now) == -1) rxtn->seed >>= 1;
else rxtn->seed = (unsigned int)now;
}
srand (rxtn->seed);
r = qse_awk_rtx_makeintval (run, prev);
2008-12-21 21:35:07 +00:00
if (r == QSE_NULL)
{
qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM);
return -1;
}
qse_awk_rtx_setretval (run, r);
return 0;
}
static int fnc_system (qse_awk_rtx_t* run, const qse_char_t* fnm, qse_size_t fnl)
{
qse_size_t nargs;
qse_awk_val_t* v;
qse_char_t* str, * ptr, * end;
qse_size_t len;
int n = 0;
nargs = qse_awk_rtx_getnargs (run);
QSE_ASSERT (nargs == 1);
v = qse_awk_rtx_getarg (run, 0);
if (v->type == QSE_AWK_VAL_STR)
{
str = ((qse_awk_val_str_t*)v)->ptr;
len = ((qse_awk_val_str_t*)v)->len;
}
2008-12-18 02:39:15 +00:00
else
{
str = qse_awk_rtx_valtostr (
run, v, QSE_AWK_RTX_VALTOSTR_CLEAR, QSE_NULL, &len);
if (str == QSE_NULL) return -1;
}
/* the target name contains a null character.
* make system return -1 */
ptr = str; end = str + len;
while (ptr < end)
{
if (*ptr == QSE_T('\0'))
{
n = -1;
goto skip_system;
}
ptr++;
}
#if defined(_WIN32)
n = _tsystem (str);
#elif defined(QSE_CHAR_IS_MCHAR)
n = system (str);
#else
{
char* mbs;
qse_size_t mbl;
mbs = (char*) qse_awk_alloc (run->awk, len*5+1);
if (mbs == QSE_NULL)
{
n = -1;
goto skip_system;
}
/* at this point, the string is guaranteed to be
* null-terminating. so qse_wcstombs() can be used to convert
* the string, not qse_wcsntombsn(). */
mbl = len * 5;
if (qse_wcstombs (str, mbs, &mbl) != len && mbl >= len * 5)
{
/* not the entire string is converted.
* mbs is not null-terminated properly. */
n = -1;
goto skip_system_mbs;
}
mbs[mbl] = '\0';
n = system (mbs);
skip_system_mbs:
qse_awk_free (run->awk, mbs);
}
#endif
skip_system:
if (v->type != QSE_AWK_VAL_STR) QSE_AWK_FREE (run->awk, str);
v = qse_awk_rtx_makeintval (run, (qse_long_t)n);
if (v == QSE_NULL)
{
/*qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM);*/
return -1;
}
qse_awk_rtx_setretval (run, v);
return 0;
}
2008-12-31 00:08:03 +00:00
#define ADDFNC(awk,name,min,max,fnc) \
if (qse_awk_addfnc (\
2008-12-21 21:35:07 +00:00
(awk), (name), qse_strlen(name), \
0, (min), (max), QSE_NULL, (fnc)) == QSE_NULL) return -1;
2008-12-21 21:35:07 +00:00
static int add_functions (qse_awk_t* awk)
{
ADDFNC (awk, QSE_T("sin"), 1, 1, fnc_sin);
ADDFNC (awk, QSE_T("cos"), 1, 1, fnc_cos);
ADDFNC (awk, QSE_T("tan"), 1, 1, fnc_tan);
ADDFNC (awk, QSE_T("atan"), 1, 1, fnc_atan);
ADDFNC (awk, QSE_T("atan2"), 2, 2, fnc_atan2);
ADDFNC (awk, QSE_T("log"), 1, 1, fnc_log);
ADDFNC (awk, QSE_T("exp"), 1, 1, fnc_exp);
ADDFNC (awk, QSE_T("sqrt"), 1, 1, fnc_sqrt);
ADDFNC (awk, QSE_T("int"), 1, 1, fnc_int);
ADDFNC (awk, QSE_T("rand"), 0, 0, fnc_rand);
ADDFNC (awk, QSE_T("srand"), 0, 1, fnc_srand);
ADDFNC (awk, QSE_T("system"), 1, 1, fnc_system);
return 0;
}