qse/qse/lib/awk/Awk.cpp

1819 lines
36 KiB
C++
Raw Normal View History

/*
* $Id: Awk.cpp 363 2010-10-27 12:54:37Z hyunghwan.chung $
2009-09-16 04:01:02 +00:00
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
2008-12-21 21:35:07 +00:00
#include <qse/awk/Awk.hpp>
#include <qse/cmn/str.h>
2008-08-19 05:21:48 +00:00
#include "../cmn/mem.h"
2009-02-17 02:11:31 +00:00
#include "awk.h"
// enable this once addFunction() is extended with argument spec (rxv...).
//#define PASS_BY_REFERENCE
/////////////////////////////////
QSE_BEGIN_NAMESPACE(QSE)
/////////////////////////////////
//////////////////////////////////////////////////////////////////
// Awk::Source
//////////////////////////////////////////////////////////////////
struct xtn_t
{
Awk* awk;
};
2009-02-16 08:31:34 +00:00
struct rxtn_t
{
Awk::Run* run;
};
Awk::NoSource Awk::Source::NONE;
//////////////////////////////////////////////////////////////////
2009-02-16 08:31:34 +00:00
// Awk::RIO
//////////////////////////////////////////////////////////////////
2009-07-07 06:37:25 +00:00
Awk::RIOBase::RIOBase (Run* run, rio_arg_t* riod): run (run), riod (riod)
{
}
const Awk::char_t* Awk::RIOBase::getName () const
{
2009-02-16 08:31:34 +00:00
return this->riod->name;
}
const void* Awk::RIOBase::getHandle () const
{
2009-02-16 08:31:34 +00:00
return this->riod->handle;
}
void Awk::RIOBase::setHandle (void* handle)
{
2009-02-16 08:31:34 +00:00
this->riod->handle = handle;
}
Awk::RIOBase::operator Awk* () const
{
2009-07-07 06:37:25 +00:00
return this->run->awk;
}
Awk::RIOBase::operator Awk::awk_t* () const
{
QSE_ASSERT (qse_awk_rtx_getawk(this->run->rtx) == this->run->awk->awk);
return this->run->awk->awk;
}
Awk::RIOBase::operator Awk::rio_arg_t* () const
{
2009-02-16 08:31:34 +00:00
return this->riod;
}
Awk::RIOBase::operator Awk::Run* () const
{
return this->run;
}
Awk::RIOBase::operator Awk::rtx_t* () const
{
2009-07-07 06:37:25 +00:00
return this->run->rtx;
}
//////////////////////////////////////////////////////////////////
// Awk::Pipe
//////////////////////////////////////////////////////////////////
2009-07-07 06:37:25 +00:00
Awk::Pipe::Pipe (Run* run, rio_arg_t* riod): RIOBase (run, riod)
{
}
Awk::Pipe::Mode Awk::Pipe::getMode () const
{
2009-02-16 08:31:34 +00:00
return (Mode)riod->mode;
}
Awk::Pipe::CloseMode Awk::Pipe::getCloseMode () const
{
return (CloseMode)riod->rwcmode;
}
//////////////////////////////////////////////////////////////////
// Awk::File
//////////////////////////////////////////////////////////////////
2009-07-07 06:37:25 +00:00
Awk::File::File (Run* run, rio_arg_t* riod): RIOBase (run, riod)
{
}
Awk::File::Mode Awk::File::getMode () const
{
2009-02-16 08:31:34 +00:00
return (Mode)riod->mode;
}
//////////////////////////////////////////////////////////////////
// Awk::Console
//////////////////////////////////////////////////////////////////
2009-07-07 06:37:25 +00:00
Awk::Console::Console (Run* run, rio_arg_t* riod):
RIOBase (run, riod), filename (QSE_NULL)
{
}
Awk::Console::~Console ()
{
2008-12-21 21:35:07 +00:00
if (filename != QSE_NULL)
{
qse_awk_free ((awk_t*)this, filename);
}
}
int Awk::Console::setFileName (const char_t* name)
{
if (this->getMode() == READ)
{
return qse_awk_rtx_setfilename (
2009-07-07 06:37:25 +00:00
this->run->rtx, name, qse_strlen(name));
}
else
{
return qse_awk_rtx_setofilename (
2009-07-07 06:37:25 +00:00
this->run->rtx, name, qse_strlen(name));
}
}
int Awk::Console::setFNR (long_t fnr)
{
2009-07-11 08:05:51 +00:00
val_t* tmp;
int n;
2009-07-07 06:37:25 +00:00
tmp = qse_awk_rtx_makeintval (this->run->rtx, fnr);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
2009-07-07 06:37:25 +00:00
qse_awk_rtx_refupval (this->run->rtx, tmp);
n = qse_awk_rtx_setgbl (this->run->rtx, QSE_AWK_GBL_FNR, tmp);
qse_awk_rtx_refdownval (this->run->rtx, tmp);
return n;
}
Awk::Console::Mode Awk::Console::getMode () const
{
2009-02-16 08:31:34 +00:00
return (Mode)riod->mode;
}
2009-07-11 08:05:51 +00:00
//////////////////////////////////////////////////////////////////
// Awk::Value
//////////////////////////////////////////////////////////////////
const Awk::char_t* Awk::Value::EMPTY_STRING = QSE_T("");
Awk::Value::IndexIterator Awk::Value::IndexIterator::END;
Awk::Value::IntIndex::IntIndex (long_t x)
{
ptr = buf;
len = 0;
#define NTOC(n) ((n) + QSE_T('0'))
int base = 10;
long_t last = x % base;
long_t y = 0;
int dig = 0;
if (x < 0) buf[len++] = QSE_T('-');
x = x / base;
if (x < 0) x = -x;
while (x > 0)
{
y = y * base + (x % base);
x = x / base;
dig++;
}
while (y > 0)
{
buf[len++] = NTOC (y % base);
y = y / base;
dig--;
}
while (dig > 0)
{
dig--;
buf[len++] = QSE_T('0');
}
if (last < 0) last = -last;
buf[len++] = NTOC(last);
buf[len] = QSE_T('\0');
#undef NTOC
}
void* Awk::Value::operator new (size_t n, Run* run) throw ()
{
void* ptr = qse_awk_rtx_alloc (run->rtx, QSE_SIZEOF(run) + n);
if (ptr == QSE_NULL) return QSE_NULL;
*(Run**)ptr = run;
return (char*)ptr+QSE_SIZEOF(run);
}
2009-07-16 04:43:31 +00:00
void* Awk::Value::operator new[] (size_t n, Run* run) throw ()
{
void* ptr = qse_awk_rtx_alloc (run->rtx, QSE_SIZEOF(run) + n);
if (ptr == QSE_NULL) return QSE_NULL;
*(Run**)ptr = run;
return (char*)ptr+QSE_SIZEOF(run);
}
#if !defined(__BORLANDC__)
2009-07-16 04:43:31 +00:00
void Awk::Value::operator delete (void* ptr, Run* run)
{
qse_awk_rtx_free (run->rtx, (char*)ptr-QSE_SIZEOF(run));
}
2009-07-16 04:43:31 +00:00
void Awk::Value::operator delete[] (void* ptr, Run* run)
{
qse_awk_rtx_free (run->rtx, (char*)ptr-QSE_SIZEOF(run));
}
#endif
2009-07-16 04:43:31 +00:00
void Awk::Value::operator delete (void* ptr)
{
void* p = (char*)ptr-QSE_SIZEOF(Run*);
qse_awk_rtx_free ((*(Run**)p)->rtx, p);
}
2009-07-16 04:43:31 +00:00
void Awk::Value::operator delete[] (void* ptr)
{
void* p = (char*)ptr-QSE_SIZEOF(Run*);
qse_awk_rtx_free ((*(Run**)p)->rtx, p);
}
Awk::Value::Value (): run (QSE_NULL), val (qse_awk_val_nil)
{
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
}
Awk::Value::Value (Run& run): run (&run), val (qse_awk_val_nil)
{
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
}
Awk::Value::Value (Run* run): run (run), val (qse_awk_val_nil)
{
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
}
2009-07-11 08:05:51 +00:00
Awk::Value::Value (const Value& v): run (v.run), val (v.val)
{
if (run != QSE_NULL)
qse_awk_rtx_refupval (run->rtx, val);
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
2009-07-11 08:05:51 +00:00
}
Awk::Value::~Value ()
{
if (run != QSE_NULL)
{
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refdownval (run->rtx, val);
if (cached.str.ptr != QSE_NULL)
qse_awk_rtx_free (run->rtx, cached.str.ptr);
}
2009-07-11 08:05:51 +00:00
}
Awk::Value& Awk::Value::operator= (const Value& v)
{
if (this == &v) return *this;
2009-07-11 08:05:51 +00:00
if (run != QSE_NULL)
{
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refdownval (run->rtx, val);
if (cached.str.ptr != QSE_NULL)
{
qse_awk_rtx_free (run->rtx, cached.str.ptr);
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
}
}
2009-07-11 08:05:51 +00:00
run = v.run;
val = v.val;
if (run != QSE_NULL)
qse_awk_rtx_refupval (run->rtx, val);
return *this;
}
void Awk::Value::clear ()
{
if (run != QSE_NULL)
{
qse_awk_rtx_refdownval (run->rtx, val);
if (cached.str.ptr != QSE_NULL)
{
qse_awk_rtx_free (run->rtx, cached.str.ptr);
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
}
2009-07-11 08:05:51 +00:00
run = QSE_NULL;
val = qse_awk_val_nil;
}
}
Awk::Value::operator Awk::long_t () const
{
long_t v;
if (getInt (&v) <= -1) v = 0;
return v;
}
Awk::Value::operator Awk::real_t () const
{
real_t v;
if (getReal (&v) <= -1) v = 0.0;
return v;
}
Awk::Value::operator const Awk::char_t* () const
{
2009-08-21 05:28:03 +00:00
const Awk::char_t* ptr;
size_t len;
2009-08-21 05:28:03 +00:00
if (Awk::Value::getStr (&ptr, &len) <= -1) ptr = QSE_T("");
return ptr;
}
int Awk::Value::getInt (long_t* v) const
{
long_t lv = 0;
QSE_ASSERT (val != QSE_NULL);
if (run != QSE_NULL &&
val->type != QSE_AWK_VAL_NIL &&
val->type != QSE_AWK_VAL_MAP)
{
real_t rv;
int n = qse_awk_rtx_valtonum (run->rtx, val, &lv, &rv);
if (n <= -1)
{
2009-07-15 08:08:48 +00:00
run->awk->retrieveError (run);
return -1;
}
if (n >= 1) lv = (long_t)rv;
}
*v = lv;
return 0;
}
int Awk::Value::getReal (real_t* v) const
{
real_t rv = 0;
QSE_ASSERT (val != QSE_NULL);
if (run != QSE_NULL &&
val->type != QSE_AWK_VAL_NIL &&
val->type != QSE_AWK_VAL_MAP)
{
long_t lv;
int n = qse_awk_rtx_valtonum (run->rtx, val, &lv, &rv);
if (n <= -1)
{
2009-07-15 08:08:48 +00:00
run->awk->retrieveError (run);
return -1;
}
if (n == 0) rv = (real_t)lv;
}
*v = rv;
return 0;
}
int Awk::Value::getStr (const char_t** str, size_t* len) const
{
const char_t* p = EMPTY_STRING;
size_t l = 0;
QSE_ASSERT (val != QSE_NULL);
if (run != QSE_NULL &&
val->type != QSE_AWK_VAL_NIL &&
val->type != QSE_AWK_VAL_MAP)
{
if (val->type == QSE_AWK_VAL_STR)
{
p = ((qse_awk_val_str_t*)val)->ptr;
l = ((qse_awk_val_str_t*)val)->len;
}
else
{
if (cached.str.ptr == QSE_NULL)
{
qse_awk_rtx_valtostr_out_t out;
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
if (qse_awk_rtx_valtostr (
run->rtx, val, &out) == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
run->awk->retrieveError (run);
return -1;
}
p = out.u.cpldup.ptr;
l = out.u.cpldup.len;
cached.str.ptr = out.u.cpldup.ptr;
cached.str.len = out.u.cpldup.len;
}
else
{
p = cached.str.ptr;
l = cached.str.len;
}
}
}
*str = p;
*len = l;
return 0;
}
int Awk::Value::setVal (val_t* v)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setVal (run, v);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setVal (Run* r, val_t* v)
2009-07-11 08:05:51 +00:00
{
if (run != QSE_NULL)
{
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refdownval (run->rtx, val);
if (cached.str.ptr != QSE_NULL)
{
qse_awk_rtx_free (run->rtx, cached.str.ptr);
cached.str.ptr = QSE_NULL;
cached.str.len = 0;
}
}
QSE_ASSERT (cached.str.ptr == QSE_NULL);
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refupval (r->rtx, v);
run = r;
val = v;
return 0;
}
int Awk::Value::setInt (long_t v)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setInt (run, v);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setInt (Run* r, long_t v)
2009-07-11 08:05:51 +00:00
{
val_t* tmp;
tmp = qse_awk_rtx_makeintval (r->rtx, v);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
int n = setVal (r, tmp);
2009-07-11 08:05:51 +00:00
QSE_ASSERT (n == 0);
return n;
}
int Awk::Value::setReal (real_t v)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setReal (run, v);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setReal (Run* r, real_t v)
2009-07-11 08:05:51 +00:00
{
val_t* tmp;
tmp = qse_awk_rtx_makerealval (r->rtx, v);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
int n = setVal (r, tmp);
2009-07-11 08:05:51 +00:00
QSE_ASSERT (n == 0);
return n;
}
int Awk::Value::setStr (const char_t* str, size_t len)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setStr (run, str, len);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setStr (Run* r, const char_t* str, size_t len)
2009-07-11 08:05:51 +00:00
{
val_t* tmp;
tmp = qse_awk_rtx_makestrval (r->rtx, str, len);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
int n = setVal (r, tmp);
QSE_ASSERT (n == 0);
return n;
}
int Awk::Value::setStr (const char_t* str)
{
if (run == QSE_NULL) return -1;
return setStr (run, str);
}
int Awk::Value::setStr (Run* r, const char_t* str)
{
val_t* tmp;
tmp = qse_awk_rtx_makestrval0 (r->rtx, str);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
int n = setVal (r, tmp);
2009-07-11 08:05:51 +00:00
QSE_ASSERT (n == 0);
return n;
}
int Awk::Value::setIndexedVal (const Index& idx, val_t* v)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setIndexedVal (run, idx, v);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v)
2009-07-11 08:05:51 +00:00
{
QSE_ASSERT (r != QSE_NULL);
2009-07-11 08:05:51 +00:00
if (val->type != QSE_AWK_VAL_MAP)
{
/* the previous value is not a map.
* a new map value needs to be created first */
val_t* map = qse_awk_rtx_makemapval (r->rtx);
if (map == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refupval (r->rtx, map);
qse_awk_rtx_refupval (r->rtx, v);
/* update the map with a given value */
pair_t* pair = qse_htb_upsert (
2009-07-11 08:05:51 +00:00
((qse_awk_val_map_t*)map)->map,
(char_t*)idx.ptr, idx.len, v, 0);
2009-07-11 08:05:51 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (r->rtx, v);
qse_awk_rtx_refdownval (r->rtx, map);
2009-09-16 04:01:02 +00:00
r->setError (QSE_AWK_ENOMEM);
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
2009-07-11 08:05:51 +00:00
return -1;
}
if (run != QSE_NULL)
qse_awk_rtx_refdownval (run->rtx, val);
run = r;
val = map;
}
else
{
QSE_ASSERT (run != QSE_NULL);
// if the previous value is a map, things are a bit simpler
// however it needs to check if the runtime context matches
// with the previous one.
if (run != r)
{
// it can't span across multiple runtime contexts
2009-09-16 04:01:02 +00:00
run->setError (QSE_AWK_EINVAL);
2009-07-15 08:08:48 +00:00
run->awk->retrieveError (run);
2009-07-11 08:05:51 +00:00
return -1;
}
qse_awk_rtx_refupval (r->rtx, v);
pair_t* pair = qse_htb_upsert (
2009-07-11 08:05:51 +00:00
((qse_awk_val_map_t*)val)->map,
(char_t*)idx.ptr, idx.len, v, 0);
2009-07-11 08:05:51 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (r->rtx, v);
2009-09-16 04:01:02 +00:00
run->setError (QSE_AWK_ENOMEM);
2009-07-15 08:08:48 +00:00
run->awk->retrieveError (run);
2009-07-11 08:05:51 +00:00
return -1;
}
}
return 0;
}
int Awk::Value::setIndexedInt (const Index& idx, long_t v)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setIndexedInt (run, idx, v);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setIndexedInt (Run* r, const Index& idx, long_t v)
2009-07-11 08:05:51 +00:00
{
val_t* tmp;
tmp = qse_awk_rtx_makeintval (r->rtx, v);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refupval (r->rtx, tmp);
int n = setIndexedVal (r, idx, tmp);
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refdownval (r->rtx, tmp);
return n;
}
int Awk::Value::setIndexedReal (const Index& idx, real_t v)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setIndexedReal (run, idx, v);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setIndexedReal (Run* r, const Index& idx, real_t v)
2009-07-11 08:05:51 +00:00
{
val_t* tmp;
tmp = qse_awk_rtx_makerealval (r->rtx, v);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refupval (r->rtx, tmp);
int n = setIndexedVal (r, idx, tmp);
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refdownval (r->rtx, tmp);
return n;
}
int Awk::Value::setIndexedStr (const Index& idx, const char_t* str, size_t len)
2009-07-11 08:05:51 +00:00
{
if (run == QSE_NULL) return -1;
return setIndexedStr (run, idx, str, len);
2009-07-11 08:05:51 +00:00
}
int Awk::Value::setIndexedStr (
Run* r, const Index& idx, const char_t* str, size_t len)
2009-07-11 08:05:51 +00:00
{
val_t* tmp;
tmp = qse_awk_rtx_makestrval (r->rtx, str, len);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refupval (r->rtx, tmp);
int n = setIndexedVal (r, idx, tmp);
qse_awk_rtx_refdownval (r->rtx, tmp);
return n;
}
int Awk::Value::setIndexedStr (const Index& idx, const char_t* str)
{
if (run == QSE_NULL) return -1;
return setIndexedStr (run, idx, str);
}
int Awk::Value::setIndexedStr (Run* r, const Index& idx, const char_t* str)
{
val_t* tmp;
tmp = qse_awk_rtx_makestrval0 (r->rtx, str);
if (tmp == QSE_NULL)
{
2009-07-15 08:08:48 +00:00
r->awk->retrieveError (r);
return -1;
}
qse_awk_rtx_refupval (r->rtx, tmp);
int n = setIndexedVal (r, idx, tmp);
2009-07-11 08:05:51 +00:00
qse_awk_rtx_refdownval (r->rtx, tmp);
return n;
}
2009-07-11 08:05:51 +00:00
bool Awk::Value::isIndexed () const
{
QSE_ASSERT (val != QSE_NULL);
return val->type == QSE_AWK_VAL_MAP;
}
int Awk::Value::getIndexed (const Index& idx, Value* v) const
2009-07-11 08:05:51 +00:00
{
QSE_ASSERT (val != QSE_NULL);
// not a map. v is just nil. not an error
if (val->type != QSE_AWK_VAL_MAP)
{
v->clear ();
2009-07-11 08:05:51 +00:00
return 0;
}
// get the value from the map.
qse_awk_val_map_t* m = (qse_awk_val_map_t*)val;
pair_t* pair = qse_htb_search (m->map, idx.ptr, idx.len);
2009-07-11 08:05:51 +00:00
// the key is not found. it is not an error. v is just nil
if (pair == QSE_NULL)
{
v->clear ();
2009-07-11 08:05:51 +00:00
return 0;
}
// if v.set fails, it should return an error
return v->setVal (run, (val_t*)QSE_HTB_VPTR(pair));
}
Awk::Value::IndexIterator Awk::Value::getFirstIndex (Index* idx) const
{
QSE_ASSERT (val != QSE_NULL);
if (val->type != QSE_AWK_VAL_MAP) return IndexIterator::END;
size_t buckno;
qse_awk_val_map_t* m = (qse_awk_val_map_t*)val;
pair_t* pair = qse_htb_getfirstpair (m->map, &buckno);
if (pair == QSE_NULL) return IndexIterator::END; // no more key
idx->ptr = (const char_t*)QSE_HTB_KPTR(pair);
idx->len = QSE_HTB_KLEN(pair);
return IndexIterator (pair, buckno);
}
Awk::Value::IndexIterator Awk::Value::getNextIndex (
Index* idx, const IndexIterator& iter) const
{
QSE_ASSERT (val != QSE_NULL);
if (val->type != QSE_AWK_VAL_MAP) return IndexIterator::END;
qse_awk_val_map_t* m = (qse_awk_val_map_t*)val;
pair_t* pair = (pair_t*)iter.pair;
size_t buckno = iter.buckno;
pair = qse_htb_getnextpair (m->map, pair, &buckno);
if (pair == QSE_NULL) return IndexIterator::END;
idx->ptr = (const char_t*)QSE_HTB_KPTR(pair);
idx->len = QSE_HTB_KLEN(pair);
return IndexIterator (pair, buckno);
}
#if 0
int Awk::Argument::getFirstIndex (Awk::Argument& val) const
{
val.clear ();
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL) return -1;
2009-07-02 07:14:39 +00:00
if (this->val->type != QSE_AWK_VAL_MAP) return -1;
2008-12-21 21:35:07 +00:00
qse_size_t buckno;
qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val;
pair_t* pair = qse_htb_getfirstpair (m->map, &buckno);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL) return 0; // no more key
if (val.init (
(qse_char_t*)QSE_HTB_KPTR(pair),
QSE_HTB_KLEN(pair)) == -1) return -1;
// reuse the string field as an interator.
this->str.ptr = (char_t*)pair;
this->str.len = buckno;
return 1;
}
int Awk::Argument::getNextIndex (Awk::Argument& val) const
{
val.clear ();
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL) return -1;
2009-07-02 07:14:39 +00:00
if (this->val->type != QSE_AWK_VAL_MAP) return -1;
2008-12-21 21:35:07 +00:00
qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val;
2008-02-13 01:39:56 +00:00
pair_t* pair = (pair_t*)this->str.ptr;
2008-12-21 21:35:07 +00:00
qse_size_t buckno = this->str.len;
pair = qse_htb_getnextpair (m->map, pair, &buckno);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL) return 0;
if (val.init (
(qse_char_t*)QSE_HTB_KPTR(pair),
QSE_HTB_KLEN(pair)) == -1) return -1;
// reuse the string field as an interator.
this->str.ptr = (char_t*)pair;
this->str.len = buckno;
return 1;
}
#endif
//////////////////////////////////////////////////////////////////
// Awk::Run
//////////////////////////////////////////////////////////////////
2009-07-07 06:37:25 +00:00
Awk::Run::Run (Awk* awk): awk (awk), rtx (QSE_NULL)
{
}
2009-07-09 07:01:45 +00:00
Awk::Run::Run (Awk* awk, rtx_t* rtx): awk (awk), rtx (rtx)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
}
Awk::Run::~Run ()
{
}
Awk::Run::operator Awk* () const
{
return this->awk;
}
2009-02-16 08:31:34 +00:00
Awk::Run::operator Awk::rtx_t* () const
{
2009-07-07 06:37:25 +00:00
return this->rtx;
}
2009-07-16 04:43:31 +00:00
void Awk::Run::stop () const
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
qse_awk_rtx_stop (this->rtx);
}
bool Awk::Run::pendingStop () const
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
return qse_awk_rtx_pendingstop (this->rtx)? true: false;
}
2009-09-16 04:01:02 +00:00
Awk::errnum_t Awk::Run::getErrorNumber () const
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
2009-09-16 04:01:02 +00:00
return qse_awk_rtx_geterrnum (this->rtx);
}
Awk::loc_t Awk::Run::getErrorLocation () const
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
return *qse_awk_rtx_geterrloc (this->rtx);
}
2009-07-16 04:43:31 +00:00
const Awk::char_t* Awk::Run::getErrorMessage () const
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
return qse_awk_rtx_geterrmsg (this->rtx);
}
2009-09-16 04:01:02 +00:00
void Awk::Run::setError (errnum_t code, const cstr_t* args, const loc_t* loc)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
2009-09-16 04:01:02 +00:00
qse_awk_rtx_seterror (this->rtx, code, args, loc);
}
void Awk::Run::setErrorWithMessage (
2009-09-16 04:01:02 +00:00
errnum_t code, const char_t* msg, const loc_t* loc)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
2009-07-16 04:43:31 +00:00
errinf_t errinf;
QSE_MEMSET (&errinf, 0, QSE_SIZEOF(errinf));
2009-09-16 04:01:02 +00:00
errinf.num = code;
if (loc == QSE_NULL) errinf.loc = *loc;
qse_strxcpy (errinf.msg, QSE_COUNTOF(errinf.msg), msg);
2009-07-07 06:37:25 +00:00
qse_awk_rtx_seterrinf (this->rtx, &errinf);
}
int Awk::Run::setGlobal (int id, long_t v)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
2009-07-11 08:05:51 +00:00
val_t* tmp = qse_awk_rtx_makeintval (this->rtx, v);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
2009-07-07 06:37:25 +00:00
qse_awk_rtx_refupval (this->rtx, tmp);
int n = qse_awk_rtx_setgbl (this->rtx, id, tmp);
qse_awk_rtx_refdownval (this->rtx, tmp);
return n;
}
int Awk::Run::setGlobal (int id, real_t v)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
2009-07-11 08:05:51 +00:00
val_t* tmp = qse_awk_rtx_makerealval (this->rtx, v);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
2009-07-07 06:37:25 +00:00
qse_awk_rtx_refupval (this->rtx, tmp);
int n = qse_awk_rtx_setgbl (this->rtx, id, tmp);
qse_awk_rtx_refdownval (this->rtx, tmp);
return n;
}
int Awk::Run::setGlobal (int id, const char_t* ptr, size_t len)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
2009-07-11 08:05:51 +00:00
val_t* tmp = qse_awk_rtx_makestrval (this->rtx, ptr, len);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
2009-07-07 06:37:25 +00:00
qse_awk_rtx_refupval (this->rtx, tmp);
int n = qse_awk_rtx_setgbl (this->rtx, id, tmp);
qse_awk_rtx_refdownval (this->rtx, tmp);
return n;
}
int Awk::Run::setGlobal (int id, const Value& gbl)
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
return qse_awk_rtx_setgbl (this->rtx, id, (val_t*)gbl);
}
int Awk::Run::getGlobal (int id, Value& g) const
{
2009-07-07 06:37:25 +00:00
QSE_ASSERT (this->rtx != QSE_NULL);
return g.setVal ((Run*)this, qse_awk_rtx_getgbl (this->rtx, id));
}
//////////////////////////////////////////////////////////////////
// Awk
//////////////////////////////////////////////////////////////////
Awk::Awk (Mmgr* mmgr):
Mmged (mmgr), awk (QSE_NULL), functionMap (QSE_NULL), runctx (this)
{
QSE_MEMSET (&errinf, 0, QSE_SIZEOF(errinf));
2009-09-16 04:01:02 +00:00
errinf.num = QSE_AWK_ENOERR;
}
2009-07-16 04:43:31 +00:00
Awk::operator Awk::awk_t* () const
{
return this->awk;
}
2009-09-16 04:01:02 +00:00
const Awk::char_t* Awk::getErrorString (errnum_t num) const
2009-07-15 08:08:48 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (dflerrstr != QSE_NULL);
2009-09-16 04:01:02 +00:00
return dflerrstr (awk, num);
2009-07-15 08:08:48 +00:00
}
2009-07-16 04:43:31 +00:00
const Awk::char_t* Awk::xerrstr (awk_t* a, errnum_t num)
2009-07-15 08:08:48 +00:00
{
Awk* awk = *(Awk**)QSE_XTN(a);
2009-09-16 04:01:02 +00:00
return awk->getErrorString (num);
2009-07-15 08:08:48 +00:00
}
2009-09-16 04:01:02 +00:00
Awk::errnum_t Awk::getErrorNumber () const
{
2009-09-16 04:01:02 +00:00
return this->errinf.num;
}
Awk::loc_t Awk::getErrorLocation () const
{
return this->errinf.loc;
}
2009-07-16 04:43:31 +00:00
const Awk::char_t* Awk::getErrorMessage () const
{
2009-07-16 04:43:31 +00:00
return this->errinf.msg;
}
2009-09-16 04:01:02 +00:00
void Awk::setError (errnum_t code, const cstr_t* args, const loc_t* loc)
{
2008-12-21 21:35:07 +00:00
if (awk != QSE_NULL)
{
2009-09-16 04:01:02 +00:00
qse_awk_seterror (awk, code, args, loc);
retrieveError ();
}
else
{
QSE_MEMSET (&errinf, 0, QSE_SIZEOF(errinf));
2009-09-16 04:01:02 +00:00
errinf.num = code;
if (loc != QSE_NULL) errinf.loc = *loc;
2009-07-16 04:43:31 +00:00
qse_strxcpy (errinf.msg, QSE_COUNTOF(errinf.msg),
QSE_T("not ready to set an error message"));
}
}
2009-09-16 04:01:02 +00:00
void Awk::setErrorWithMessage (errnum_t code, const char_t* msg, const loc_t* loc)
{
QSE_MEMSET (&errinf, 0, QSE_SIZEOF(errinf));
2009-09-16 04:01:02 +00:00
errinf.num = code;
if (loc != QSE_NULL) errinf.loc = *loc;
qse_strxcpy (errinf.msg, QSE_COUNTOF(errinf.msg), msg);
if (awk != QSE_NULL) qse_awk_seterrinf (awk, &errinf);
}
void Awk::clearError ()
{
QSE_MEMSET (&errinf, 0, QSE_SIZEOF(errinf));
2009-09-16 04:01:02 +00:00
errinf.num = QSE_AWK_ENOERR;
}
void Awk::retrieveError ()
{
2008-12-21 21:35:07 +00:00
if (this->awk == QSE_NULL)
{
clearError ();
}
else
{
2009-07-16 04:43:31 +00:00
qse_awk_geterrinf (this->awk, &errinf);
}
}
2009-07-15 08:08:48 +00:00
void Awk::retrieveError (Run* run)
{
2009-07-15 08:08:48 +00:00
QSE_ASSERT (run != QSE_NULL);
if (run->rtx == QSE_NULL) return;
2009-07-16 04:43:31 +00:00
qse_awk_rtx_geterrinf (run->rtx, &errinf);
}
2009-07-15 08:08:48 +00:00
2009-07-16 04:43:31 +00:00
static void free_function_map_value (
Awk::htb_t* map, void* dptr, Awk::size_t dlen)
2009-07-16 04:43:31 +00:00
{
Awk* awk = *(Awk**) QSE_XTN (map);
qse_awk_free ((Awk::awk_t*)*awk, dptr);
}
2009-07-16 04:43:31 +00:00
int Awk::open ()
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk == QSE_NULL && functionMap == QSE_NULL);
2009-02-17 02:11:31 +00:00
qse_awk_prm_t prm;
prm.pow = pow;
prm.sprintf = sprintf;
awk = qse_awk_open (this->getMmgr(), QSE_SIZEOF(xtn_t), &prm);
2008-12-21 21:35:07 +00:00
if (awk == QSE_NULL)
{
2009-09-16 04:01:02 +00:00
setError (QSE_AWK_ENOMEM);
return -1;
}
// associate this Awk object with the underlying awk object
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
xtn->awk = this;
dflerrstr = qse_awk_geterrstr (awk);
qse_awk_seterrstr (awk, xerrstr);
functionMap = qse_htb_open (
qse_awk_getmmgr(awk), QSE_SIZEOF(this), 512, 70,
QSE_SIZEOF(qse_char_t), 1
);
2008-12-21 21:35:07 +00:00
if (functionMap == QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_awk_close (awk);
awk = QSE_NULL;
2009-09-16 04:01:02 +00:00
setError (QSE_AWK_ENOMEM);
return -1;
}
2009-02-17 02:11:31 +00:00
*(Awk**)QSE_XTN(functionMap) = this;
static qse_htb_mancbs_t mancbs =
{
{
QSE_HTB_COPIER_INLINE,
QSE_HTB_COPIER_DEFAULT
},
{
QSE_HTB_FREEER_DEFAULT,
free_function_map_value
},
QSE_HTB_HASHER_DEFAULT,
QSE_HTB_COMPER_DEFAULT,
QSE_HTB_KEEPER_DEFAULT,
QSE_HTB_SIZER_DEFAULT
};
qse_htb_setmancbs (functionMap, &mancbs);
#if 0
qse_htb_setscale (functionMap, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t));
qse_htb_setcopier (functionMap, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE);
qse_htb_setfreeer (functionMap, QSE_HTB_VAL, free_function_map_value);
#endif
return 0;
}
2009-07-16 04:43:31 +00:00
void Awk::close ()
{
2009-07-09 07:01:45 +00:00
fini_runctx ();
2009-07-02 07:14:39 +00:00
clearArguments ();
2008-12-21 21:35:07 +00:00
if (functionMap != QSE_NULL)
{
qse_htb_close (functionMap);
2008-12-21 21:35:07 +00:00
functionMap = QSE_NULL;
}
2008-12-21 21:35:07 +00:00
if (awk != QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_awk_close (awk);
awk = QSE_NULL;
}
clearError ();
}
2009-07-16 04:43:31 +00:00
Awk::Run* Awk::parse (Source& in, Source& out)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
if (&in == &Source::NONE)
{
2009-09-16 04:01:02 +00:00
setError (QSE_AWK_EINVAL);
return QSE_NULL;
}
2009-07-09 07:01:45 +00:00
fini_runctx ();
sourceReader = &in;
sourceWriter = (&out == &Source::NONE)? QSE_NULL: &out;
2009-07-10 06:46:14 +00:00
2009-07-09 07:01:45 +00:00
qse_awk_sio_t sio;
2009-07-10 06:46:14 +00:00
sio.in = readSource;
sio.out = (sourceWriter == QSE_NULL)? QSE_NULL: writeSource;
int n = qse_awk_parse (awk, &sio);
2009-07-09 07:01:45 +00:00
if (n <= -1)
{
retrieveError ();
return QSE_NULL;
}
if (init_runctx () <= -1) return QSE_NULL;
return &runctx;
}
int Awk::loop (Value* ret)
2009-07-16 04:43:31 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (runctx.rtx != QSE_NULL);
val_t* rv = qse_awk_rtx_loop (runctx.rtx);
if (rv == QSE_NULL)
{
retrieveError (&runctx);
return -1;
}
ret->setVal (&runctx, rv);
qse_awk_rtx_refdownval (runctx.rtx, rv);
return 0;
2009-07-16 04:43:31 +00:00
}
int Awk::call (
const char_t* name, Value* ret,
const Value* args, size_t nargs)
2009-07-16 04:43:31 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (runctx.rtx != QSE_NULL);
val_t* buf[16];
val_t** ptr = QSE_NULL;
if (args != QSE_NULL)
{
if (nargs <= QSE_COUNTOF(buf)) ptr = buf;
else
{
ptr = (val_t**) qse_awk_alloc (
awk, QSE_SIZEOF(val_t*) * nargs);
if (ptr == QSE_NULL)
{
2009-09-16 04:01:02 +00:00
runctx.setError (QSE_AWK_ENOMEM);
2009-07-16 04:43:31 +00:00
retrieveError (&runctx);
return -1;
}
}
for (size_t i = 0; i < nargs; i++) ptr[i] = (val_t*)args[i];
}
val_t* rv = qse_awk_rtx_call (runctx.rtx, name, ptr, nargs);
if (ptr != QSE_NULL && ptr != buf) qse_awk_free (awk, ptr);
if (rv == QSE_NULL)
{
retrieveError (&runctx);
return -1;
}
ret->setVal (&runctx, rv);
qse_awk_rtx_refdownval (runctx.rtx, rv);
return 0;
}
void Awk::stop ()
{
QSE_ASSERT (awk != QSE_NULL);
qse_awk_stopall (awk);
}
int Awk::init_runctx ()
{
2009-07-09 07:01:45 +00:00
if (runctx.rtx != QSE_NULL) return 0;
qse_awk_rio_t rio;
rio.pipe = pipeHandler;
rio.file = fileHandler;
rio.console = consoleHandler;
rtx_t* rtx = qse_awk_rtx_open (
2009-07-02 07:14:39 +00:00
awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg.ptr);
2009-02-13 04:55:25 +00:00
if (rtx == QSE_NULL)
{
retrieveError();
2009-07-09 07:01:45 +00:00
return -1;
2009-02-13 04:55:25 +00:00
}
2009-02-16 08:31:34 +00:00
2009-07-09 07:01:45 +00:00
runctx.rtx = rtx;
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
rxtn->run = &runctx;
2009-02-13 04:55:25 +00:00
2009-07-09 07:01:45 +00:00
return 0;
}
2009-07-16 04:43:31 +00:00
void Awk::fini_runctx ()
2009-07-09 07:01:45 +00:00
{
if (runctx.rtx != QSE_NULL)
{
qse_awk_rtx_close (runctx.rtx);
runctx.rtx = QSE_NULL;
2009-02-13 04:55:25 +00:00
}
2009-07-09 07:01:45 +00:00
}
2009-02-13 04:55:25 +00:00
2009-07-16 04:43:31 +00:00
int Awk::getOption () const
2009-07-09 07:01:45 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
2009-07-16 04:43:31 +00:00
return qse_awk_getoption (awk);
}
2009-07-16 04:43:31 +00:00
void Awk::setOption (int opt)
2009-07-09 07:01:45 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
2009-07-16 04:43:31 +00:00
qse_awk_setoption (awk, opt);
}
2009-07-16 04:43:31 +00:00
void Awk::setMaxDepth (int ids, size_t depth)
{
QSE_ASSERT (awk != QSE_NULL);
qse_awk_setmaxdepth (awk, ids, depth);
2009-07-09 07:01:45 +00:00
}
2009-09-15 07:29:55 +00:00
Awk::size_t Awk::getMaxDepth (depth_t id) const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
2009-07-16 04:43:31 +00:00
return qse_awk_getmaxdepth (awk, id);
}
2009-07-16 04:43:31 +00:00
int Awk::dispatch_function (Run* run, const cstr_t* name)
{
pair_t* pair;
pair = qse_htb_search (functionMap, name->ptr, name->len);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
2009-09-16 04:01:02 +00:00
run->setError (QSE_AWK_EFUNNF, name);
return -1;
}
FunctionHandler handler;
handler = *(FunctionHandler*)QSE_HTB_VPTR(pair);
2009-07-07 06:37:25 +00:00
size_t i, nargs = qse_awk_rtx_getnargs(run->rtx);
Value buf[16];
Value* args;
if (nargs <= QSE_COUNTOF(buf)) args = buf;
else
{
args = new(run) Value[nargs];
if (args == QSE_NULL)
{
2009-09-16 04:01:02 +00:00
run->setError (QSE_AWK_ENOMEM);
return -1;
}
}
for (i = 0; i < nargs; i++)
{
2009-07-07 06:37:25 +00:00
val_t* v = qse_awk_rtx_getarg (run->rtx, i);
#ifdef PASS_BY_REFERENCE
QSE_ASSERT (v->type == QSE_AWK_VAL_REF);
val_t** ref = (val_t**)((qse_awk_val_ref_t*)v)->adr;
if (args[i].setVal (run, *ref) == -1)
{
2009-09-16 04:01:02 +00:00
run->setError (QSE_AWK_ENOMEM);
if (args != buf) delete[] args;
return -1;
}
#else
if (args[i].setVal (run, v) == -1)
{
2009-09-16 04:01:02 +00:00
run->setError (QSE_AWK_ENOMEM);
if (args != buf) delete[] args;
return -1;
}
#endif
}
Value ret (run);
2009-07-16 04:43:31 +00:00
int n;
try { n = (this->*handler) (*run, ret, args, nargs, name); }
catch (...) { n = -1; }
#ifdef PASS_BY_REFERENCE
if (n >= 0)
{
for (i = 0; i < nargs; i++)
{
QSE_ASSERTX (args[i].run == run,
"Do NOT change Run from function handler");
val_t* v = qse_awk_rtx_getarg (run->rtx, i);
val_t* nv = args[i].toVal();
if (nv == v) continue;
QSE_ASSERT (v->type == QSE_AWK_VAL_REF);
val_t** ref = (val_t**)((qse_awk_val_ref_t*)v)->adr;
qse_awk_rtx_refdownval (run->rtx, *ref);
*ref = nv;
qse_awk_rtx_refupval (run->rtx, *ref);
}
}
#endif
if (args != buf) delete[] args;
if (n <= -1)
{
/* this is really the handler error. the underlying engine
* will take care of the error code. */
return -1;
}
qse_awk_rtx_setretval (run->rtx, ret.toVal());
return 0;
}
2009-07-16 04:43:31 +00:00
int Awk::xstrs_t::add (awk_t* awk, const char_t* arg, size_t len)
2009-07-02 07:14:39 +00:00
{
if (this->len >= this->capa)
2009-07-02 07:14:39 +00:00
{
qse_xstr_t* ptr;
size_t capa = this->capa;
2009-07-02 07:14:39 +00:00
capa += 64;
ptr = (qse_xstr_t*) qse_awk_realloc (
awk, this->ptr, QSE_SIZEOF(qse_xstr_t)*(capa+1));
if (ptr == QSE_NULL) return -1;
2009-07-02 07:14:39 +00:00
this->ptr = ptr;
this->capa = capa;
2009-07-02 07:14:39 +00:00
}
this->ptr[this->len].len = len;
this->ptr[this->len].ptr = qse_awk_strxdup (awk, arg, len);
if (this->ptr[this->len].ptr == QSE_NULL) return -1;
2009-07-02 07:14:39 +00:00
this->len++;
this->ptr[this->len].len = 0;
this->ptr[this->len].ptr = QSE_NULL;
2009-07-02 07:14:39 +00:00
return 0;
}
2009-07-16 04:43:31 +00:00
void Awk::xstrs_t::clear (awk_t* awk)
{
if (this->ptr != QSE_NULL)
{
2009-07-09 07:01:45 +00:00
while (this->len > 0)
qse_awk_free (awk, this->ptr[--this->len].ptr);
qse_awk_free (awk, this->ptr);
this->ptr = QSE_NULL;
this->capa = 0;
}
}
2009-07-16 04:43:31 +00:00
int Awk::addArgument (const char_t* arg, size_t len)
{
QSE_ASSERT (awk != QSE_NULL);
int n = runarg.add (awk, arg, len);
2009-09-16 04:01:02 +00:00
if (n <= -1) setError (QSE_AWK_ENOMEM);
return n;
}
2009-07-16 04:43:31 +00:00
int Awk::addArgument (const char_t* arg)
2009-07-02 07:14:39 +00:00
{
return addArgument (arg, qse_strlen(arg));
}
2009-07-16 04:43:31 +00:00
void Awk::clearArguments ()
2009-07-02 07:14:39 +00:00
{
runarg.clear (awk);
2009-07-02 07:14:39 +00:00
}
2009-07-16 04:43:31 +00:00
int Awk::addGlobal (const char_t* name)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
int n = qse_awk_addgbl (awk, name, qse_strlen(name));
if (n <= -1) retrieveError ();
return n;
}
2009-07-16 04:43:31 +00:00
int Awk::deleteGlobal (const char_t* name)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
int n = qse_awk_delgbl (awk, name, qse_strlen(name));
if (n <= -1) retrieveError ();
return n;
}
int Awk::findGlobal (const char_t* name)
{
QSE_ASSERT (awk != QSE_NULL);
int n = qse_awk_findgbl (awk, name, qse_strlen(name));
if (n <= -1) retrieveError ();
return n;
}
2009-07-16 04:43:31 +00:00
int Awk::setGlobal (int id, const Value& v)
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (runctx.rtx != QSE_NULL);
if (v.run != &runctx)
{
2009-09-16 04:01:02 +00:00
setError (QSE_AWK_EINVAL);
return -1;
}
int n = runctx.setGlobal (id, v);
if (n <= -1) retrieveError ();
return n;
}
2009-07-16 04:43:31 +00:00
int Awk::getGlobal (int id, Value& v)
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (runctx.rtx != QSE_NULL);
int n = runctx.getGlobal (id, v);
if (n <= -1) retrieveError ();
return n;
}
int Awk::addFunction (
const char_t* name, size_t minArgs, size_t maxArgs,
2009-07-16 04:43:31 +00:00
FunctionHandler handler)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
FunctionHandler* tmp = (FunctionHandler*)
2008-12-21 21:35:07 +00:00
qse_awk_alloc (awk, QSE_SIZEOF(handler));
if (tmp == QSE_NULL)
{
2009-09-16 04:01:02 +00:00
setError (QSE_AWK_ENOMEM);
return -1;
}
2008-12-21 21:35:07 +00:00
//QSE_MEMCPY (tmp, &handler, QSE_SIZEOF(handler));
*tmp = handler;
2008-12-21 21:35:07 +00:00
size_t nameLen = qse_strlen(name);
void* p = qse_awk_addfnc (
awk, name, nameLen,
0, minArgs, maxArgs,
#ifdef PASS_BY_REFERENCE
QSE_T("R"), // pass all arguments by reference
#else
QSE_NULL,
#endif
functionHandler);
2008-12-21 21:35:07 +00:00
if (p == QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_awk_free (awk, tmp);
retrieveError ();
return -1;
}
pair_t* pair = qse_htb_upsert (
functionMap, (char_t*)name, nameLen, tmp, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_delfnc (awk, name, nameLen);
2008-12-21 21:35:07 +00:00
qse_awk_free (awk, tmp);
2009-09-16 04:01:02 +00:00
setError (QSE_AWK_ENOMEM);
return -1;
}
return 0;
}
2009-07-16 04:43:31 +00:00
int Awk::deleteFunction (const char_t* name)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
2008-12-21 21:35:07 +00:00
size_t nameLen = qse_strlen(name);
int n = qse_awk_delfnc (awk, name, nameLen);
if (n == 0) qse_htb_delete (functionMap, name, nameLen);
else retrieveError ();
return n;
}
2009-07-19 06:02:24 +00:00
int Awk::getWord (const cstr_t* ow, cstr_t* nw)
2009-07-15 08:08:48 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
2009-07-19 06:02:24 +00:00
return qse_awk_getword (awk, ow, nw);
2009-07-15 08:08:48 +00:00
}
2009-07-19 06:02:24 +00:00
int Awk::setWord (const cstr_t* ow, const cstr_t* nw)
2009-07-15 08:08:48 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
2009-07-19 06:02:24 +00:00
return qse_awk_setword (awk, ow, nw);
2009-07-15 08:08:48 +00:00
}
2009-07-19 06:02:24 +00:00
int Awk::unsetWord (const cstr_t* w)
2009-07-15 08:08:48 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
2009-07-19 06:02:24 +00:00
return qse_awk_unsetword (awk, w);
2009-07-15 08:08:48 +00:00
}
2009-07-19 06:02:24 +00:00
void Awk::unsetAllWords ()
2009-07-15 08:08:48 +00:00
{
QSE_ASSERT (awk != QSE_NULL);
2009-07-19 06:02:24 +00:00
qse_awk_unsetallwords (awk);
2009-07-15 08:08:48 +00:00
}
2009-07-10 06:46:14 +00:00
Awk::ssize_t Awk::readSource (
2009-07-27 20:31:58 +00:00
awk_t* awk, sio_cmd_t cmd, sio_arg_t* arg,
char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
2009-08-10 21:29:59 +00:00
Source::Data sdat (xtn->awk, Source::READ, arg);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_OPEN:
2009-08-10 21:29:59 +00:00
return xtn->awk->sourceReader->open (sdat);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_CLOSE:
2009-08-10 21:29:59 +00:00
return xtn->awk->sourceReader->close (sdat);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_READ:
2009-08-10 21:29:59 +00:00
return xtn->awk->sourceReader->read (sdat, data, count);
2009-07-10 06:46:14 +00:00
default:
2009-02-17 02:11:31 +00:00
return -1;
}
}
2009-07-10 06:46:14 +00:00
Awk::ssize_t Awk::writeSource (
2009-07-27 20:31:58 +00:00
awk_t* awk, qse_awk_sio_cmd_t cmd, sio_arg_t* arg,
char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
2009-08-10 21:29:59 +00:00
Source::Data sdat (xtn->awk, Source::WRITE, arg);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_OPEN:
2009-08-10 21:29:59 +00:00
return xtn->awk->sourceWriter->open (sdat);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_CLOSE:
2009-08-10 21:29:59 +00:00
return xtn->awk->sourceWriter->close (sdat);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_WRITE:
2009-08-10 21:29:59 +00:00
return xtn->awk->sourceWriter->write (sdat, data, count);
2009-07-10 06:46:14 +00:00
default:
2009-02-17 02:11:31 +00:00
return -1;
}
}
Awk::ssize_t Awk::pipeHandler (
rtx_t* rtx, rio_cmd_t cmd, rio_arg_t* riod,
2009-02-17 02:11:31 +00:00
char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
Awk* awk = rxtn->run->awk;
2009-02-16 08:31:34 +00:00
QSE_ASSERT ((riod->type & 0xFF) == QSE_AWK_RIO_PIPE);
2009-07-07 06:37:25 +00:00
Pipe pipe (rxtn->run, riod);
2009-07-16 04:43:31 +00:00
try
{
switch (cmd)
{
case QSE_AWK_RIO_OPEN:
return awk->openPipe (pipe);
case QSE_AWK_RIO_CLOSE:
return awk->closePipe (pipe);
2009-07-16 04:43:31 +00:00
case QSE_AWK_RIO_READ:
return awk->readPipe (pipe, data, count);
case QSE_AWK_RIO_WRITE:
return awk->writePipe (pipe, data, count);
2009-07-16 04:43:31 +00:00
case QSE_AWK_RIO_FLUSH:
return awk->flushPipe (pipe);
2009-07-16 04:43:31 +00:00
default:
return -1;
}
}
catch (...)
{
return -1;
}
}
Awk::ssize_t Awk::fileHandler (
rtx_t* rtx, rio_cmd_t cmd, rio_arg_t* riod,
2009-02-17 02:11:31 +00:00
char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
Awk* awk = rxtn->run->awk;
2009-02-16 08:31:34 +00:00
QSE_ASSERT ((riod->type & 0xFF) == QSE_AWK_RIO_FILE);
2009-07-07 06:37:25 +00:00
File file (rxtn->run, riod);
2009-07-16 04:43:31 +00:00
try
{
2009-07-16 04:43:31 +00:00
switch (cmd)
{
case QSE_AWK_RIO_OPEN:
return awk->openFile (file);
case QSE_AWK_RIO_CLOSE:
return awk->closeFile (file);
2009-07-16 04:43:31 +00:00
case QSE_AWK_RIO_READ:
return awk->readFile (file, data, count);
case QSE_AWK_RIO_WRITE:
return awk->writeFile (file, data, count);
2009-07-16 04:43:31 +00:00
case QSE_AWK_RIO_FLUSH:
return awk->flushFile (file);
2009-07-16 04:43:31 +00:00
default:
return -1;
}
}
catch (...)
{
return -1;
}
}
Awk::ssize_t Awk::consoleHandler (
rtx_t* rtx, rio_cmd_t cmd, rio_arg_t* riod,
2009-02-17 02:11:31 +00:00
char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
Awk* awk = rxtn->run->awk;
2009-02-16 08:31:34 +00:00
QSE_ASSERT ((riod->type & 0xFF) == QSE_AWK_RIO_CONSOLE);
2009-07-07 06:37:25 +00:00
Console console (rxtn->run, riod);
2009-07-16 04:43:31 +00:00
try
{
2009-07-16 04:43:31 +00:00
switch (cmd)
{
case QSE_AWK_RIO_OPEN:
return awk->openConsole (console);
case QSE_AWK_RIO_CLOSE:
return awk->closeConsole (console);
case QSE_AWK_RIO_READ:
return awk->readConsole (console, data, count);
case QSE_AWK_RIO_WRITE:
return awk->writeConsole (console, data, count);
case QSE_AWK_RIO_FLUSH:
return awk->flushConsole (console);
case QSE_AWK_RIO_NEXT:
return awk->nextConsole (console);
default:
return -1;
}
}
catch (...)
{
return -1;
}
}
2009-07-16 04:43:31 +00:00
int Awk::functionHandler (rtx_t* rtx, const cstr_t* name)
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-07-16 04:43:31 +00:00
return rxtn->run->awk->dispatch_function (rxtn->run, name);
}
Awk::real_t Awk::pow (awk_t* awk, real_t x, real_t y)
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
return xtn->awk->pow (x, y);
}
int Awk::sprintf (awk_t* awk, char_t* buf, size_t size,
const char_t* fmt, ...)
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
va_list ap;
va_start (ap, fmt);
int n = xtn->awk->vsprintf (buf, size, fmt, ap);
va_end (ap);
return n;
}
/////////////////////////////////
QSE_END_NAMESPACE(QSE)
/////////////////////////////////