qse/qse/lib/awk/Awk.cpp

1789 lines
37 KiB
C++
Raw Normal View History

/*
* $Id: Awk.cpp 206 2009-06-21 13:33:05Z hyunghwan.chung $
*
2009-02-04 08:39:21 +00:00
Copyright 2006-2009 Chung, Hyung-Hwan.
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-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"
/////////////////////////////////
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;
};
2008-12-21 21:35:07 +00:00
Awk::Source::Source (Mode mode): mode (mode), handle (QSE_NULL)
{
}
Awk::Source::Mode Awk::Source::getMode () const
{
return this->mode;
}
const void* Awk::Source::getHandle () const
{
return this->handle;
}
void Awk::Source::setHandle (void* handle)
{
this->handle = handle;
}
//////////////////////////////////////////////////////////////////
2009-02-16 08:31:34 +00:00
// Awk::RIO
//////////////////////////////////////////////////////////////////
Awk::RIO::RIO (rtx_t* rtx, rio_arg_t* riod): rtx (rtx), riod (riod)
{
}
2009-02-16 08:31:34 +00:00
const Awk::char_t* Awk::RIO::getName () const
{
2009-02-16 08:31:34 +00:00
return this->riod->name;
}
2009-02-16 08:31:34 +00:00
const void* Awk::RIO::getHandle () const
{
2009-02-16 08:31:34 +00:00
return this->riod->handle;
}
2009-02-16 08:31:34 +00:00
void Awk::RIO::setHandle (void* handle)
{
2009-02-16 08:31:34 +00:00
this->riod->handle = handle;
}
Awk::RIO::operator Awk* () const
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (this->rtx);
2009-02-16 08:31:34 +00:00
return rxtn->run->awk;
}
2009-02-16 08:31:34 +00:00
Awk::RIO::operator Awk::awk_t* () const
{
2009-02-16 08:31:34 +00:00
return qse_awk_rtx_getawk (this->rtx);
}
Awk::RIO::operator Awk::rio_arg_t* () const
{
2009-02-16 08:31:34 +00:00
return this->riod;
}
2009-02-16 08:31:34 +00:00
Awk::RIO::operator Awk::rtx_t* () const
{
2009-02-16 08:31:34 +00:00
return this->rtx;
}
//////////////////////////////////////////////////////////////////
// Awk::Pipe
//////////////////////////////////////////////////////////////////
Awk::Pipe::Pipe (rtx_t* rtx, rio_arg_t* riod): RIO (rtx, riod)
{
}
Awk::Pipe::Mode Awk::Pipe::getMode () const
{
2009-02-16 08:31:34 +00:00
return (Mode)riod->mode;
}
//////////////////////////////////////////////////////////////////
// Awk::File
//////////////////////////////////////////////////////////////////
Awk::File::File (rtx_t* rtx, rio_arg_t* riod): RIO (rtx, riod)
{
}
Awk::File::Mode Awk::File::getMode () const
{
2009-02-16 08:31:34 +00:00
return (Mode)riod->mode;
}
//////////////////////////////////////////////////////////////////
// Awk::Console
//////////////////////////////////////////////////////////////////
Awk::Console::Console (rtx_t* rtx, rio_arg_t* riod):
2009-02-16 08:31:34 +00:00
RIO (rtx, 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)
{
2009-02-16 08:31:34 +00:00
if (riod->mode == READ)
{
return qse_awk_rtx_setfilename (
2009-02-16 08:31:34 +00:00
this->rtx, name, qse_strlen(name));
}
else
{
return qse_awk_rtx_setofilename (
2009-02-16 08:31:34 +00:00
this->rtx, name, qse_strlen(name));
}
}
int Awk::Console::setFNR (long_t fnr)
{
2008-12-21 21:35:07 +00:00
qse_awk_val_t* tmp;
int n;
2009-02-16 08:31:34 +00:00
tmp = qse_awk_rtx_makeintval (this->rtx, fnr);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
2009-02-16 08:31:34 +00:00
qse_awk_rtx_refupval (this->rtx, tmp);
n = qse_awk_rtx_setgbl (this->rtx, QSE_AWK_GBL_FNR, tmp);
qse_awk_rtx_refdownval (this->rtx, tmp);
return n;
}
Awk::Console::Mode Awk::Console::getMode () const
{
2009-02-16 08:31:34 +00:00
return (Mode)riod->mode;
}
//////////////////////////////////////////////////////////////////
// Awk::Argument
//////////////////////////////////////////////////////////////////
2008-12-21 21:35:07 +00:00
Awk::Argument::Argument (Run& run): run (&run), val (QSE_NULL)
{
this->inum = 0;
this->rnum = 0.0;
2008-12-21 21:35:07 +00:00
this->str.ptr = QSE_NULL;
this->str.len = 0;
}
2008-12-21 21:35:07 +00:00
Awk::Argument::Argument (Run* run): run (run), val (QSE_NULL)
{
this->inum = 0;
this->rnum = 0.0;
2008-12-21 21:35:07 +00:00
this->str.ptr = QSE_NULL;
this->str.len = 0;
}
2008-12-21 21:35:07 +00:00
Awk::Argument::Argument (): run (QSE_NULL), val (QSE_NULL)
{
this->inum = 0;
this->rnum = 0.0;
2008-12-21 21:35:07 +00:00
this->str.ptr = QSE_NULL;
this->str.len = 0;
}
Awk::Argument::~Argument ()
{
clear ();
}
void Awk::Argument::clear ()
{
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL)
{
/* case 1. not initialized.
* case 2. initialized with the second init.
* none of the cases creates a new string so the sttring
* that str.ptr is pointing at doesn't have to be freed */
2008-12-21 21:35:07 +00:00
this->str.ptr = QSE_NULL;
this->str.len = 0;
}
2008-12-21 21:35:07 +00:00
else if (QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
/* when the value is a map, str.ptr and str.len are
* used for index iteration in getFirstIndex & getNextIndex */
qse_awk_rtx_refdownval (this->run->run, this->val);
2008-12-21 21:35:07 +00:00
this->val = QSE_NULL;
}
else
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
2008-12-21 21:35:07 +00:00
if (this->str.ptr != QSE_NULL)
{
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_STR)
{
awk_t* awk = this->run->awk->awk;
2008-12-21 21:35:07 +00:00
qse_awk_free (awk, this->str.ptr);
}
2008-12-21 21:35:07 +00:00
this->str.ptr = QSE_NULL;
this->str.len = 0;
}
2008-12-21 21:35:07 +00:00
if (this->val != QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, this->val);
2008-12-21 21:35:07 +00:00
this->val = QSE_NULL;
}
}
this->rnum = 0.0;
this->inum = 0;
}
void* Awk::Argument::operator new (size_t n, awk_t* awk) throw ()
{
2008-12-21 21:35:07 +00:00
void* ptr = qse_awk_alloc (awk, QSE_SIZEOF(awk) + n);
if (ptr == QSE_NULL) return QSE_NULL;
*(awk_t**)ptr = awk;
2008-12-21 21:35:07 +00:00
return (char*)ptr+QSE_SIZEOF(awk);
}
void* Awk::Argument::operator new[] (size_t n, awk_t* awk) throw ()
{
2008-12-21 21:35:07 +00:00
void* ptr = qse_awk_alloc (awk, QSE_SIZEOF(awk) + n);
if (ptr == QSE_NULL) return QSE_NULL;
*(awk_t**)ptr = awk;
2008-12-21 21:35:07 +00:00
return (char*)ptr+QSE_SIZEOF(awk);
}
#if !defined(__BORLANDC__)
void Awk::Argument::operator delete (void* ptr, awk_t* awk)
{
2008-12-21 21:35:07 +00:00
qse_awk_free (awk, (char*)ptr-QSE_SIZEOF(awk));
}
void Awk::Argument::operator delete[] (void* ptr, awk_t* awk)
{
2008-12-21 21:35:07 +00:00
qse_awk_free (awk, (char*)ptr-QSE_SIZEOF(awk));
}
#endif
void Awk::Argument::operator delete (void* ptr)
{
2008-12-21 21:35:07 +00:00
void* p = (char*)ptr-QSE_SIZEOF(awk_t*);
qse_awk_free (*(awk_t**)p, p);
}
void Awk::Argument::operator delete[] (void* ptr)
{
2008-12-21 21:35:07 +00:00
void* p = (char*)ptr-QSE_SIZEOF(awk_t*);
qse_awk_free (*(awk_t**)p, p);
}
int Awk::Argument::init (val_t* v)
{
// this method is used internally only
// and should never be called more than once
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->val == QSE_NULL);
QSE_ASSERT (v != QSE_NULL);
qse_awk_rtx_refupval (this->run->run, v);
this->val = v;
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_STR)
{
int n = qse_awk_rtx_valtonum (
this->run->run, v, &this->inum, &this->rnum);
if (n == 0)
{
2008-12-21 21:35:07 +00:00
this->rnum = (qse_real_t)this->inum;
this->str.ptr = ((qse_awk_val_str_t*)this->val)->ptr;
2008-12-21 21:35:07 +00:00
this->str.len = ((qse_awk_val_str_t*)this->val)->len;
return 0;
}
else if (n == 1)
{
2008-12-21 21:35:07 +00:00
this->inum = (qse_long_t)this->rnum;
this->str.ptr = ((qse_awk_val_str_t*)this->val)->ptr;
2008-12-21 21:35:07 +00:00
this->str.len = ((qse_awk_val_str_t*)this->val)->len;
return 0;
}
}
2008-12-21 21:35:07 +00:00
else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_INT)
{
2008-12-21 21:35:07 +00:00
this->inum = ((qse_awk_val_int_t*)v)->val;
this->rnum = (qse_real_t)((qse_awk_val_int_t*)v)->val;
this->str.ptr = qse_awk_rtx_valtocpldup (
this->run->run, v, &this->str.len);
2008-12-21 21:35:07 +00:00
if (this->str.ptr != QSE_NULL) return 0;
}
2008-12-21 21:35:07 +00:00
else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_REAL)
{
2008-12-21 21:35:07 +00:00
this->inum = (qse_long_t)((qse_awk_val_real_t*)v)->val;
this->rnum = ((qse_awk_val_real_t*)v)->val;
this->str.ptr = qse_awk_rtx_valtocpldup (
this->run->run, v, &this->str.len);
2008-12-21 21:35:07 +00:00
if (this->str.ptr != QSE_NULL) return 0;
}
2008-12-21 21:35:07 +00:00
else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_NIL)
{
this->inum = 0;
this->rnum = 0.0;
this->str.ptr = qse_awk_rtx_valtocpldup (
this->run->run, v, &this->str.len);
2008-12-21 21:35:07 +00:00
if (this->str.ptr != QSE_NULL) return 0;
}
2008-12-21 21:35:07 +00:00
else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_MAP)
{
this->inum = 0;
this->rnum = 0.0;
2008-12-21 21:35:07 +00:00
this->str.ptr = QSE_NULL;
this->str.len = 0;
return 0;
}
// an error has occurred
qse_awk_rtx_refdownval (this->run->run, v);
2008-12-21 21:35:07 +00:00
this->val = QSE_NULL;
return -1;
}
int Awk::Argument::init (const char_t* str, size_t len)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->val == QSE_NULL);
this->str.ptr = (char_t*)str;
this->str.len = len;
if (qse_awk_rtx_strtonum (
this->run->run, 0,
str, len, &this->inum, &this->rnum) == 0)
{
this->rnum = (real_t)this->inum;
}
else
{
this->inum = (long_t)this->rnum;
}
return 0;
}
Awk::long_t Awk::Argument::toInt () const
{
return this->inum;
}
Awk::real_t Awk::Argument::toReal () const
{
return this->rnum;
}
const Awk::char_t* Awk::Argument::toStr (size_t* len) const
{
2008-12-21 21:35:07 +00:00
if (this->val != QSE_NULL &&
QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP)
{
*len = 0;
2008-12-21 21:35:07 +00:00
return QSE_T("");
}
2008-12-21 21:35:07 +00:00
else if (this->str.ptr == QSE_NULL)
{
*len = 0;
2008-12-21 21:35:07 +00:00
return QSE_T("");
}
else
{
*len = this->str.len;
return this->str.ptr;
}
}
bool Awk::Argument::isIndexed () const
{
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL) return false;
return QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP;
}
int Awk::Argument::getIndexed (const char_t* idxptr, Awk::Argument& val) const
{
2008-12-21 21:35:07 +00:00
return getIndexed (idxptr, qse_strlen(idxptr), val);
}
int Awk::Argument::getIndexed (
const char_t* idxptr, size_t idxlen, Awk::Argument& val) const
{
val.clear ();
// not initialized yet. val is just nil. not an error
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL) return 0;
// not a map. val is just nil. not an error
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) return 0;
// get the value from the map.
2008-12-21 21:35:07 +00:00
qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val;
pair_t* pair = qse_map_search (m->map, idxptr, idxlen);
// the key is not found. it is not an error. val is just nil
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL) return 0;
// if val.init fails, it should return an error
2008-12-21 21:35:07 +00:00
return val.init ((val_t*)QSE_MAP_VPTR(pair));
}
int Awk::Argument::getIndexed (long_t idx, Argument& val) const
{
val.clear ();
// not initialized yet. val is just nil. not an error
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL) return 0;
// not a map. val is just nil. not an error
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) return 0;
char_t ri[128];
int rl = Awk::sprintf (
(awk_t*)this->run->awk, ri, QSE_COUNTOF(ri),
2008-12-21 21:35:07 +00:00
#if QSE_SIZEOF_LONG_LONG > 0
QSE_T("%lld"), (long long)idx
#elif QSE_SIZEOF___INT64 > 0
QSE_T("%I64d"), (__int64)idx
#elif QSE_SIZEOF_LONG > 0
QSE_T("%ld"), (long)idx
#elif QSE_SIZEOF_INT > 0
QSE_T("%d"), (int)idx
#else
#error unsupported size
#endif
);
if (rl < 0)
{
2008-12-21 21:35:07 +00:00
run->setError (ERR_INTERN, 0, QSE_NULL, 0);
return -1;
}
// get the value from the map.
2008-12-21 21:35:07 +00:00
qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val;
pair_t* pair = qse_map_search (m->map, ri, rl);
// the key is not found. it is not an error. val is just nil
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL) return 0;
// if val.init fails, it should return an error
2008-12-21 21:35:07 +00:00
return val.init ((val_t*)QSE_MAP_VPTR(pair));
}
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;
if (QSE_AWK_VAL_TYPE(this->val) != 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_map_getfirstpair (m->map, &buckno);
if (pair == QSE_NULL) return 0; // no more key
if (val.init (
2008-12-21 21:35:07 +00:00
(qse_char_t*)QSE_MAP_KPTR(pair),
QSE_MAP_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;
if (QSE_AWK_VAL_TYPE(this->val) != 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;
2008-12-21 21:35:07 +00:00
pair = qse_map_getnextpair (m->map, pair, &buckno);
if (pair == QSE_NULL) return 0;
if (val.init (
2008-12-21 21:35:07 +00:00
(qse_char_t*)QSE_MAP_KPTR(pair),
QSE_MAP_KLEN(pair)) == -1) return -1;
// reuse the string field as an interator.
this->str.ptr = (char_t*)pair;
this->str.len = buckno;
return 1;
}
//////////////////////////////////////////////////////////////////
// Awk::Return
//////////////////////////////////////////////////////////////////
2008-12-21 21:35:07 +00:00
Awk::Return::Return (Run& run): run(&run), val(qse_awk_val_nil)
{
}
2008-12-21 21:35:07 +00:00
Awk::Return::Return (Run* run): run(run), val(qse_awk_val_nil)
{
}
Awk::Return::~Return ()
{
clear ();
}
Awk::val_t* Awk::Return::toVal () const
{
return this->val;
}
Awk::Return::operator Awk::val_t* () const
{
return this->val;
}
int Awk::Return::set (long_t v)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_val_t* x = qse_awk_rtx_makeintval (this->run->run, v);
2008-12-21 21:35:07 +00:00
if (x == QSE_NULL) return -1;
qse_awk_rtx_refdownval (this->run->run, this->val);
this->val = x;
qse_awk_rtx_refupval (this->run->run, this->val);
return 0;
}
int Awk::Return::set (real_t v)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_val_t* x = qse_awk_rtx_makerealval (this->run->run, v);
2008-12-21 21:35:07 +00:00
if (x == QSE_NULL) return -1;
qse_awk_rtx_refdownval (this->run->run, this->val);
this->val = x;
qse_awk_rtx_refupval (this->run->run, this->val);
return 0;
}
int Awk::Return::set (const char_t* ptr, size_t len)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_val_t* x = qse_awk_rtx_makestrval (this->run->run, ptr, len);
2008-12-21 21:35:07 +00:00
if (x == QSE_NULL) return -1;
qse_awk_rtx_refdownval (this->run->run, this->val);
this->val = x;
qse_awk_rtx_refupval (this->run->run, this->val);
return 0;
}
bool Awk::Return::isIndexed () const
{
2008-12-21 21:35:07 +00:00
if (this->val == QSE_NULL) return false;
return QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP;
}
int Awk::Return::setIndexed (const char_t* idx, size_t iln, long_t v)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
int opt = this->run->awk->getOption();
if ((opt & OPT_MAPTOVAR) == 0)
{
/* refer to run_return in run.c */
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_MAPNOTALLOWED, 0, QSE_NULL, 0);
return -1;
}
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP)
{
qse_awk_val_t* x = qse_awk_rtx_makemapval (this->run->run);
2008-12-21 21:35:07 +00:00
if (x == QSE_NULL) return -1;
qse_awk_rtx_refupval (this->run->run, x);
qse_awk_val_t* x2 = qse_awk_rtx_makeintval (this->run->run, v);
2008-12-21 21:35:07 +00:00
if (x2 == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x);
return -1;
}
qse_awk_rtx_refupval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_upsert (
((qse_awk_val_map_t*)x)->map,
(char_t*)idx, iln, x2, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x2);
qse_awk_rtx_refdownval (this->run->run, x);
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
qse_awk_rtx_refdownval (this->run->run, this->val);
this->val = x;
}
else
{
qse_awk_val_t* x2 = qse_awk_rtx_makeintval (this->run->run, v);
2008-12-21 21:35:07 +00:00
if (x2 == QSE_NULL) return -1;
qse_awk_rtx_refupval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_upsert (
((qse_awk_val_map_t*)this->val)->map,
(char_t*)idx, iln, x2, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
}
return 0;
}
int Awk::Return::setIndexed (const char_t* idx, size_t iln, real_t v)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
int opt = this->run->awk->getOption();
if ((opt & OPT_MAPTOVAR) == 0)
{
/* refer to run_return in run.c */
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_MAPNOTALLOWED, 0, QSE_NULL, 0);
return -1;
}
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP)
{
qse_awk_val_t* x = qse_awk_rtx_makemapval (this->run->run);
2008-12-21 21:35:07 +00:00
if (x == QSE_NULL) return -1;
qse_awk_rtx_refupval (this->run->run, x);
qse_awk_val_t* x2 = qse_awk_rtx_makerealval (this->run->run, v);
2008-12-21 21:35:07 +00:00
if (x2 == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x);
return -1;
}
qse_awk_rtx_refupval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_upsert (
((qse_awk_val_map_t*)x)->map,
(char_t*)idx, iln, x2, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x2);
qse_awk_rtx_refdownval (this->run->run, x);
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
qse_awk_rtx_refdownval (this->run->run, this->val);
this->val = x;
}
else
{
qse_awk_val_t* x2 = qse_awk_rtx_makerealval (this->run->run, v);
2008-12-21 21:35:07 +00:00
if (x2 == QSE_NULL) return -1;
qse_awk_rtx_refupval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_upsert (
((qse_awk_val_map_t*)this->val)->map,
(char_t*)idx, iln, x2, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
}
return 0;
}
int Awk::Return::setIndexed (const char_t* idx, size_t iln, const char_t* str, size_t sln)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
int opt = this->run->awk->getOption();
if ((opt & OPT_MAPTOVAR) == 0)
{
/* refer to run_return in run.c */
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_MAPNOTALLOWED, 0, QSE_NULL, 0);
return -1;
}
2008-12-21 21:35:07 +00:00
if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP)
{
qse_awk_val_t* x = qse_awk_rtx_makemapval (this->run->run);
2008-12-21 21:35:07 +00:00
if (x == QSE_NULL) return -1;
qse_awk_rtx_refupval (this->run->run, x);
qse_awk_val_t* x2 = qse_awk_rtx_makestrval (this->run->run, str, sln);
2008-12-21 21:35:07 +00:00
if (x2 == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x);
return -1;
}
qse_awk_rtx_refupval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_upsert (
((qse_awk_val_map_t*)x)->map,
(char_t*)idx, iln, x2, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x2);
qse_awk_rtx_refdownval (this->run->run, x);
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
qse_awk_rtx_refdownval (this->run->run, this->val);
this->val = x;
}
else
{
qse_awk_val_t* x2 = qse_awk_rtx_makestrval (this->run->run, str, sln);
2008-12-21 21:35:07 +00:00
if (x2 == QSE_NULL) return -1;
qse_awk_rtx_refupval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_upsert (
((qse_awk_val_map_t*)this->val)->map,
(char_t*)idx, iln, x2, 0);
2008-12-21 21:35:07 +00:00
if (pair == QSE_NULL)
{
qse_awk_rtx_refdownval (this->run->run, x2);
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
}
return 0;
}
int Awk::Return::setIndexed (long_t idx, long_t v)
{
char_t ri[128];
int rl = Awk::sprintf (
(awk_t*)this->run->awk, ri, QSE_COUNTOF(ri),
2008-12-21 21:35:07 +00:00
#if QSE_SIZEOF_LONG_LONG > 0
QSE_T("%lld"), (long long)idx
#elif QSE_SIZEOF___INT64 > 0
QSE_T("%I64d"), (__int64)idx
#elif QSE_SIZEOF_LONG > 0
QSE_T("%ld"), (long)idx
#elif QSE_SIZEOF_INT > 0
QSE_T("%d"), (int)idx
#else
#error unsupported size
#endif
);
if (rl < 0)
{
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_INTERN, 0, QSE_NULL, 0);
return -1;
}
return setIndexed (ri, rl, v);
}
int Awk::Return::setIndexed (long_t idx, real_t v)
{
char_t ri[128];
int rl = Awk::sprintf (
(awk_t*)this->run->awk, ri, QSE_COUNTOF(ri),
2008-12-21 21:35:07 +00:00
#if QSE_SIZEOF_LONG_LONG > 0
QSE_T("%lld"), (long long)idx
#elif QSE_SIZEOF___INT64 > 0
QSE_T("%I64d"), (__int64)idx
#elif QSE_SIZEOF_LONG > 0
QSE_T("%ld"), (long)idx
#elif QSE_SIZEOF_INT > 0
QSE_T("%d"), (int)idx
#else
#error unsupported size
#endif
);
if (rl < 0)
{
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_INTERN, 0, QSE_NULL, 0);
return -1;
}
return setIndexed (ri, rl, v);
}
int Awk::Return::setIndexed (long_t idx, const char_t* str, size_t sln)
{
char_t ri[128];
int rl = Awk::sprintf (
(awk_t*)this->run->awk, ri, QSE_COUNTOF(ri),
2008-12-21 21:35:07 +00:00
#if QSE_SIZEOF_LONG_LONG > 0
QSE_T("%lld"), (long long)idx
#elif QSE_SIZEOF___INT64 > 0
QSE_T("%I64d"), (__int64)idx
#elif QSE_SIZEOF_LONG > 0
QSE_T("%ld"), (long)idx
#elif QSE_SIZEOF_INT > 0
QSE_T("%d"), (int)idx
#else
#error unsupported size
#endif
);
if (rl < 0)
{
2008-12-21 21:35:07 +00:00
this->run->setError (ERR_INTERN, 0, QSE_NULL, 0);
return -1;
}
return setIndexed (ri, rl, str, sln);
}
void Awk::Return::clear ()
{
qse_awk_rtx_refdownval (this->run->run, this->val);
2008-12-21 21:35:07 +00:00
this->val = qse_awk_val_nil;
}
//////////////////////////////////////////////////////////////////
// Awk::Run
//////////////////////////////////////////////////////////////////
2009-02-17 02:11:31 +00:00
Awk::Run::Run (Awk* awk): awk (awk), run (QSE_NULL)
{
}
2009-02-17 02:11:31 +00:00
Awk::Run::Run (Awk* awk, rtx_t* run): awk (awk), run (run), data (QSE_NULL)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != 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
{
return this->run;
}
void Awk::Run::stop () const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_rtx_stop (this->run);
}
bool Awk::Run::isStop () const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
return qse_awk_rtx_shouldstop (this->run)? true: false;
}
2009-06-02 07:33:01 +00:00
Awk::ErrorNumber Awk::Run::getErrorNumber () const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
2009-06-02 07:33:01 +00:00
return (ErrorNumber)qse_awk_rtx_geterrnum (this->run);
}
Awk::size_t Awk::Run::getErrorLine () const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
return qse_awk_rtx_geterrlin (this->run);
}
const Awk::char_t* Awk::Run::getErrorMessage () const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
return qse_awk_rtx_geterrmsg (this->run);
}
2009-06-02 07:33:01 +00:00
void Awk::Run::setError (ErrorNumber code)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_rtx_seterror (this->run, (errnum_t)code, 0, QSE_NULL);
}
2009-06-02 07:33:01 +00:00
void Awk::Run::setError (ErrorNumber code, size_t line)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_rtx_seterror (this->run, (errnum_t)code, line, QSE_NULL);
}
2009-06-02 07:33:01 +00:00
void Awk::Run::setError (ErrorNumber code, size_t line, const char_t* arg)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_cstr_t x = { arg, qse_strlen(arg) };
qse_awk_rtx_seterror (this->run, (errnum_t)code, line, &x);
}
void Awk::Run::setError (
2009-06-02 07:33:01 +00:00
ErrorNumber code, size_t line, const char_t* arg, size_t len)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_cstr_t x = { arg, len };
qse_awk_rtx_seterror (this->run, (errnum_t)code, line, &x);
}
void Awk::Run::setErrorWithMessage (
2009-06-02 07:33:01 +00:00
ErrorNumber code, size_t line, const char_t* msg)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_errinf_t errinf;
errinf.num = (errnum_t)code;
errinf.lin = line;
qse_strxcpy (errinf.msg, QSE_COUNTOF(errinf.msg), msg);
qse_awk_rtx_seterrinf (this->run, &errinf);
}
int Awk::Run::setGlobal (int id, long_t v)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_val_t* tmp = qse_awk_rtx_makeintval (run, v);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
qse_awk_rtx_refupval (run, tmp);
int n = qse_awk_rtx_setgbl (this->run, id, tmp);
qse_awk_rtx_refdownval (run, tmp);
return n;
}
int Awk::Run::setGlobal (int id, real_t v)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
qse_awk_val_t* tmp = qse_awk_rtx_makerealval (run, v);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
qse_awk_rtx_refupval (run, tmp);
int n = qse_awk_rtx_setgbl (this->run, id, tmp);
qse_awk_rtx_refdownval (run, tmp);
return n;
}
int Awk::Run::setGlobal (int id, const char_t* ptr, size_t len)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (run != QSE_NULL);
qse_awk_val_t* tmp = qse_awk_rtx_makestrval (run, ptr, len);
2008-12-21 21:35:07 +00:00
if (tmp == QSE_NULL) return -1;
qse_awk_rtx_refupval (run, tmp);
int n = qse_awk_rtx_setgbl (this->run, id, tmp);
qse_awk_rtx_refdownval (run, tmp);
return n;
}
int Awk::Run::setGlobal (int id, const Return& gbl)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
return qse_awk_rtx_setgbl (this->run, id, gbl.toVal());
}
int Awk::Run::getGlobal (int id, Argument& gbl) const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (this->run != QSE_NULL);
gbl.clear ();
return gbl.init (qse_awk_rtx_getgbl(this->run,id));
}
void Awk::Run::setData (void* data)
{
2008-08-21 04:58:19 +00:00
this->data = data;
}
void* Awk::Run::getData () const
{
2008-08-21 04:58:19 +00:00
return this->data;
}
//////////////////////////////////////////////////////////////////
// Awk
//////////////////////////////////////////////////////////////////
Awk::Awk () throw (): awk (QSE_NULL), functionMap (QSE_NULL),
2008-02-29 00:50:10 +00:00
sourceIn (Source::READ), sourceOut (Source::WRITE),
errnum (ERR_NOERR), errlin (0), runCallback (false)
{
2008-12-21 21:35:07 +00:00
this->errmsg[0] = QSE_T('\0');
}
Awk::operator Awk::awk_t* () const
{
return this->awk;
}
2009-06-02 07:33:01 +00:00
Awk::ErrorNumber Awk::getErrorNumber () const
{
return this->errnum;
}
Awk::size_t Awk::getErrorLine () const
{
return this->errlin;
}
const Awk::char_t* Awk::getErrorMessage () const
{
return this->errmsg;
}
2009-06-02 07:33:01 +00:00
void Awk::setError (ErrorNumber code)
{
2008-12-21 21:35:07 +00:00
setError (code, 0, QSE_NULL, 0);
}
2009-06-02 07:33:01 +00:00
void Awk::setError (ErrorNumber code, size_t line)
{
2008-12-21 21:35:07 +00:00
setError (code, line, QSE_NULL, 0);
}
2009-06-02 07:33:01 +00:00
void Awk::setError (ErrorNumber code, size_t line, const char_t* arg)
{
2008-12-21 21:35:07 +00:00
setError (code, line, arg, qse_strlen(arg));
}
2009-06-02 07:33:01 +00:00
void Awk::setError (ErrorNumber code, size_t line, const char_t* arg, size_t len)
{
2008-12-21 21:35:07 +00:00
if (awk != QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_cstr_t x = { arg, len };
qse_awk_seterror (awk, (errnum_t)code, line, &x);
retrieveError ();
}
else
{
this->errnum = code;
this->errlin = line;
qse_strxcpy (this->errmsg, QSE_COUNTOF(this->errmsg),
QSE_T("not ready to set an error message"));
}
}
2009-06-02 07:33:01 +00:00
void Awk::setErrorWithMessage (ErrorNumber code, size_t line, const char_t* msg)
{
2008-12-21 21:35:07 +00:00
if (awk != QSE_NULL)
{
qse_awk_errinf_t errinf;
errinf.num = (errnum_t)code;
errinf.lin = line;
qse_strxcpy (errinf.msg, QSE_COUNTOF(errinf.msg), msg);
qse_awk_seterrinf (awk, &errinf);
retrieveError ();
}
else
{
this->errnum = code;
this->errlin = line;
2008-12-21 21:35:07 +00:00
qse_strxcpy (this->errmsg, QSE_COUNTOF(this->errmsg), msg);
}
}
void Awk::clearError ()
{
this->errnum = ERR_NOERR;
this->errlin = 0;
2008-12-21 21:35:07 +00:00
this->errmsg[0] = QSE_T('\0');
}
void Awk::retrieveError ()
{
2008-12-21 21:35:07 +00:00
if (this->awk == QSE_NULL)
{
clearError ();
}
else
{
errnum_t num;
const char_t* msg;
2008-12-21 21:35:07 +00:00
qse_awk_geterror (this->awk, &num, &this->errlin, &msg);
2009-06-02 07:33:01 +00:00
this->errnum = (ErrorNumber)num;
2008-12-21 21:35:07 +00:00
qse_strxcpy (this->errmsg, QSE_COUNTOF(this->errmsg), msg);
}
}
void Awk::retrieveError (rtx_t* rtx)
{
errnum_t num;
const char_t* msg;
qse_awk_rtx_geterror (rtx, &num, &this->errlin, &msg);
2009-06-02 07:33:01 +00:00
this->errnum = (ErrorNumber)num;
qse_strxcpy (this->errmsg, QSE_COUNTOF(this->errmsg), msg);
}
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, QSE_SIZEOF(xtn_t), &prm);
2008-12-21 21:35:07 +00:00
if (awk == QSE_NULL)
{
setError (ERR_NOMEM);
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);
2008-12-21 21:35:07 +00:00
//functionMap = qse_map_open (
// this, 512, 70, freeFunctionMapValue, QSE_NULL,
// qse_awk_getmmgr(awk));
functionMap = qse_map_open (
qse_awk_getmmgr(awk), QSE_SIZEOF(this), 512, 70);
if (functionMap == QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_awk_close (awk);
awk = QSE_NULL;
setError (ERR_NOMEM);
return -1;
}
2009-02-17 02:11:31 +00:00
*(Awk**)QSE_XTN(functionMap) = this;
2008-12-21 21:35:07 +00:00
qse_map_setcopier (functionMap, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);
qse_map_setfreeer (functionMap, QSE_MAP_VAL, freeFunctionMapValue);
qse_map_setscale (functionMap, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t));
runCallback = false;
return 0;
}
void Awk::close ()
{
2008-12-21 21:35:07 +00:00
if (functionMap != QSE_NULL)
{
2008-12-21 21:35:07 +00:00
qse_map_close (functionMap);
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 ();
runCallback = false;
}
void Awk::setOption (int opt)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
qse_awk_setoption (awk, opt);
}
int Awk::getOption () const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
return qse_awk_getoption (awk);
}
void Awk::setMaxDepth (int ids, size_t depth)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
qse_awk_setmaxdepth (awk, ids, depth);
}
Awk::size_t Awk::getMaxDepth (int id) const
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
return qse_awk_getmaxdepth (awk, id);
}
2009-06-02 07:33:01 +00:00
const Awk::char_t* Awk::getErrorString (ErrorNumber num) const
{
QSE_ASSERT (dflerrstr != QSE_NULL);
return dflerrstr (awk, (errnum_t)num);
}
const Awk::char_t* Awk::xerrstr (awk_t* a, errnum_t num) throw ()
{
Awk* awk = *(Awk**)QSE_XTN(a);
try
{
2009-06-02 07:33:01 +00:00
return awk->getErrorString ((ErrorNumber)num);
}
catch (...)
{
return awk->dflerrstr (a, num);
}
}
int Awk::getWord (
2008-12-21 21:35:07 +00:00
const char_t* ow, qse_size_t owl,
const char_t** nw, qse_size_t* nwl)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
return qse_awk_getword (awk, ow, owl, nw, nwl);
}
int Awk::setWord (const char_t* ow, const char_t* nw)
{
2008-12-21 21:35:07 +00:00
return setWord (ow, qse_strlen(ow), nw, qse_strlen(nw));
}
int Awk::setWord (
2008-12-21 21:35:07 +00:00
const char_t* ow, qse_size_t owl,
const char_t* nw, qse_size_t nwl)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
return qse_awk_setword (awk, ow, owl, nw, nwl);
}
int Awk::unsetWord (const char_t* ow)
{
2008-12-21 21:35:07 +00:00
return unsetWord (ow, qse_strlen(ow));
}
2008-12-21 21:35:07 +00:00
int Awk::unsetWord (const char_t* ow, qse_size_t owl)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
return qse_awk_setword (awk, ow, owl, QSE_NULL, 0);
}
int Awk::unsetAllWords ()
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0);
}
int Awk::parse ()
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
qse_awk_sio_t sio;
sio.in = sourceReader;
sio.out = sourceWriter;
int n = qse_awk_parse (awk, &sio);
if (n == -1) retrieveError ();
return n;
}
int Awk::run (const char_t** args, size_t nargs)
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
size_t i;
qse_awk_rio_t rio;
qse_awk_rcb_t rcb;
qse_xstr_t* runarg = QSE_NULL;
// note that the run field is set below after qse_awk_rtx_open() is
// executed.
Run runctx (this);
rio.pipe = pipeHandler;
rio.file = fileHandler;
rio.console = consoleHandler;
if (runCallback)
{
QSE_MEMSET (&rcb, 0, QSE_SIZEOF(rcb));
// TODO: deprecate onRunStart and onRunEnd
rcb.on_loop_enter = onRunEnter;
rcb.on_loop_exit = onRunExit;
rcb.on_statement = onRunStatement;
rcb.data = &runctx;
}
if (nargs > 0)
{
runarg = (qse_xstr_t*) qse_awk_alloc (
awk, QSE_SIZEOF(qse_xstr_t)*(nargs+1));
2008-12-21 21:35:07 +00:00
if (runarg == QSE_NULL)
{
setError (ERR_NOMEM);
return -1;
}
for (i = 0; i < nargs; i++)
{
2008-12-21 21:35:07 +00:00
runarg[i].len = qse_strlen (args[i]);
runarg[i].ptr = qse_awk_strxdup (awk, args[i], runarg[i].len);
if (runarg[i].ptr == QSE_NULL)
{
2008-12-21 21:35:07 +00:00
while (i > 0) qse_awk_free (awk, runarg[--i].ptr);
qse_awk_free (awk, runarg);
setError (ERR_NOMEM);
return -1;
}
}
2008-12-21 21:35:07 +00:00
runarg[i].ptr = QSE_NULL;
runarg[i].len = 0;
}
2009-02-13 04:55:25 +00:00
int n = 0;
rtx_t* rtx = qse_awk_rtx_open (
2009-02-16 08:31:34 +00:00
awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg);
2009-02-13 04:55:25 +00:00
if (rtx == QSE_NULL)
{
retrieveError();
n = -1;
}
else
{
runctx.run = rtx;
2009-02-16 08:31:34 +00:00
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
rxtn->run = &runctx;
2009-02-13 04:55:25 +00:00
if (runCallback) qse_awk_rtx_setrcb (rtx, &rcb);
2009-02-13 04:55:25 +00:00
n = qse_awk_rtx_loop (rtx);
if (n == -1) retrieveError (rtx);
2009-02-13 04:55:25 +00:00
qse_awk_rtx_close (rtx);
}
2009-02-26 04:35:22 +00:00
if (nargs > 0)
{
2009-02-26 04:35:22 +00:00
QSE_ASSERT (runarg != QSE_NULL);
2008-12-21 21:35:07 +00:00
while (i > 0) qse_awk_free (awk, runarg[--i].ptr);
qse_awk_free (awk, runarg);
}
return n;
}
void Awk::stop ()
{
2008-12-21 21:35:07 +00:00
QSE_ASSERT (awk != QSE_NULL);
2009-02-02 04:12:49 +00:00
qse_awk_stopall (awk);
}
int Awk::dispatchFunction (Run* run, const char_t* name, size_t len)
{
pair_t* pair;
awk_t* awk = run->awk->awk;
//awk = qse_awk_rtx_getawk (run);
2008-12-21 21:35:07 +00:00
pair = qse_map_search (functionMap, name, len);
if (pair == QSE_NULL)
{
2009-02-03 03:54:32 +00:00
run->setError (ERR_FUNNONE, 0, name, len);
return -1;
}
FunctionHandler handler;
2008-12-21 21:35:07 +00:00
handler = *(FunctionHandler*)QSE_MAP_VPTR(pair);
size_t i, nargs = qse_awk_rtx_getnargs(run->run);
2008-12-21 21:35:07 +00:00
//Argument* args = QSE_NULL;
//try { args = new Argument [nargs]; } catch (...) {}
Argument* args = new(awk) Argument[nargs];
2008-12-21 21:35:07 +00:00
if (args == QSE_NULL)
{
2008-12-21 21:35:07 +00:00
run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
return -1;
}
for (i = 0; i < nargs; i++)
{
args[i].run = run; // dirty late initialization
// due to c++ array creation limitation.
val_t* v = qse_awk_rtx_getarg (run->run, i);
if (args[i].init (v) == -1)
{
2008-12-21 21:35:07 +00:00
run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
delete[] args;
return -1;
}
}
Return ret (run);
int n = (this->*handler) (*run, ret, args, nargs, name, len);
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->run, ret);
return 0;
}
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;
}
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::addFunction (
const char_t* name, size_t minArgs, size_t maxArgs,
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)
{
setError (ERR_NOMEM);
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,
2008-12-21 21:35:07 +00:00
0, minArgs, maxArgs, QSE_NULL,
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;
}
2008-12-21 21:35:07 +00:00
pair_t* pair = qse_map_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);
setError (ERR_NOMEM);
return -1;
}
return 0;
}
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);
2008-12-21 21:35:07 +00:00
if (n == 0) qse_map_delete (functionMap, name, nameLen);
else retrieveError ();
return n;
}
void Awk::enableRunCallback ()
{
runCallback = true;
}
void Awk::disableRunCallback ()
{
runCallback = false;
}
bool Awk::onRunEnter (Run& run)
{
return true;
}
void Awk::onRunExit (Run& run, const Argument& ret)
{
}
void Awk::onRunStatement (Run& run, size_t line)
{
}
Awk::ssize_t Awk::sourceReader (
2009-02-17 02:11:31 +00:00
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_OPEN:
2009-02-16 08:31:34 +00:00
return xtn->awk->openSource (xtn->awk->sourceIn);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_CLOSE:
2009-02-16 08:31:34 +00:00
return xtn->awk->closeSource (xtn->awk->sourceIn);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_READ:
2009-02-16 08:31:34 +00:00
return xtn->awk->readSource (xtn->awk->sourceIn, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_WRITE:
return -1;
}
return -1;
}
Awk::ssize_t Awk::sourceWriter (
2009-02-17 02:11:31 +00:00
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count)
{
2009-02-17 02:11:31 +00:00
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_OPEN:
2009-02-16 08:31:34 +00:00
return xtn->awk->openSource (xtn->awk->sourceOut);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_CLOSE:
2009-02-16 08:31:34 +00:00
return xtn->awk->closeSource (xtn->awk->sourceOut);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_WRITE:
2009-02-16 08:31:34 +00:00
return xtn->awk->writeSource (xtn->awk->sourceOut, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_SIO_READ:
return -1;
}
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-02-16 08:31:34 +00:00
Pipe pipe (rtx, riod);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_OPEN:
return awk->openPipe (pipe);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_CLOSE:
return awk->closePipe (pipe);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_READ:
return awk->readPipe (pipe, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_WRITE:
return awk->writePipe (pipe, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_FLUSH:
return awk->flushPipe (pipe);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_NEXT:
return -1;
}
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-02-16 08:31:34 +00:00
File file (rtx, riod);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_OPEN:
return awk->openFile (file);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_CLOSE:
return awk->closeFile (file);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_READ:
return awk->readFile (file, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_WRITE:
return awk->writeFile (file, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_FLUSH:
return awk->flushFile (file);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_NEXT:
return -1;
}
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-02-16 08:31:34 +00:00
Console console (rtx, riod);
switch (cmd)
{
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_OPEN:
return awk->openConsole (console);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_CLOSE:
return awk->closeConsole (console);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_READ:
return awk->readConsole (console, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_WRITE:
return awk->writeConsole (console, data, count);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_FLUSH:
return awk->flushConsole (console);
2009-02-17 02:11:31 +00:00
case QSE_AWK_RIO_NEXT:
return awk->nextConsole (console);
}
return -1;
}
2009-02-16 08:31:34 +00:00
int Awk::functionHandler (rtx_t* rtx, const char_t* name, size_t len)
{
2009-02-17 02:11:31 +00:00
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
2009-02-16 08:31:34 +00:00
return rxtn->run->awk->dispatchFunction (rxtn->run, name, len);
}
void Awk::freeFunctionMapValue (map_t* map, void* dptr, size_t dlen)
{
2009-02-17 02:11:31 +00:00
Awk* awk = *(Awk**) QSE_XTN (map);
2008-12-21 21:35:07 +00:00
qse_awk_free (awk->awk, dptr);
}
2009-02-16 08:31:34 +00:00
int Awk::onRunEnter (rtx_t* run, void* data)
{
Run* r = (Run*)data;
return r->awk->onRunEnter(*r)? 0: -1;
}
2009-02-16 08:31:34 +00:00
void Awk::onRunExit (rtx_t* run, val_t* ret, void* data)
{
2008-08-21 04:58:19 +00:00
Run* r = (Run*)data;
Argument x (r);
2009-02-17 02:11:31 +00:00
if (x.init (ret) == -1)
qse_awk_rtx_seterrnum (r->run, (errnum_t)ERR_NOMEM);
else r->awk->onRunExit (*r, x);
}
2009-02-16 08:31:34 +00:00
void Awk::onRunStatement (rtx_t* run, size_t line, void* data)
{
2008-08-21 04:58:19 +00:00
Run* r = (Run*)data;
r->awk->onRunStatement (*r, line);
}
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)
/////////////////////////////////