/* * $Id: Awk.cpp,v 1.77 2007/10/14 16:34:57 bacon Exp $ * * {License} */ #include #include #include #include ///////////////////////////////// ASE_BEGIN_NAMESPACE(ASE) ///////////////////////////////// ////////////////////////////////////////////////////////////////// // Awk::Source ////////////////////////////////////////////////////////////////// Awk::Source::Source (Mode mode): mode (mode), handle (ASE_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; } ////////////////////////////////////////////////////////////////// // Awk::Extio ////////////////////////////////////////////////////////////////// Awk::Extio::Extio (extio_t* extio): extio (extio) { } const Awk::char_t* Awk::Extio::getName () const { return extio->name; } const void* Awk::Extio::getHandle () const { return extio->handle; } void Awk::Extio::setHandle (void* handle) { extio->handle = handle; } const Awk::extio_t* Awk::Extio::getRawExtio () const { return extio; } const Awk::run_t* Awk::Extio::getRawRun () const { return extio->run; } ////////////////////////////////////////////////////////////////// // Awk::Pipe ////////////////////////////////////////////////////////////////// Awk::Pipe::Pipe (extio_t* extio): Extio(extio) { } Awk::Pipe::Mode Awk::Pipe::getMode () const { return (Mode)extio->mode; } ////////////////////////////////////////////////////////////////// // Awk::File ////////////////////////////////////////////////////////////////// Awk::File::File (extio_t* extio): Extio(extio) { } Awk::File::Mode Awk::File::getMode () const { return (Mode)extio->mode; } ////////////////////////////////////////////////////////////////// // Awk::Console ////////////////////////////////////////////////////////////////// Awk::Console::Console (extio_t* extio): Extio(extio), filename(ASE_NULL) { } Awk::Console::~Console () { if (filename != ASE_NULL) { ase_awk_free (ase_awk_getrunawk(extio->run), filename); } } int Awk::Console::setFileName (const char_t* name) { if (extio->mode == READ) { return ase_awk_setfilename ( extio->run, name, ase_strlen(name)); } else { return ase_awk_setofilename ( extio->run, name, ase_strlen(name)); } } Awk::Console::Mode Awk::Console::getMode () const { return (Mode)extio->mode; } ////////////////////////////////////////////////////////////////// // Awk::Argument ////////////////////////////////////////////////////////////////// Awk::Argument::Argument (Run& run): run (&run), val (ASE_NULL) { this->inum = 0; this->rnum = 0.0; this->str.ptr = ASE_NULL; this->str.len = 0; } Awk::Argument::Argument (Run* run): run (run), val (ASE_NULL) { this->inum = 0; this->rnum = 0.0; this->str.ptr = ASE_NULL; this->str.len = 0; } Awk::Argument::Argument (): run (ASE_NULL), val (ASE_NULL) { this->inum = 0; this->rnum = 0.0; this->str.ptr = ASE_NULL; this->str.len = 0; } Awk::Argument::~Argument () { clear (); } void Awk::Argument::clear () { if (this->val == ASE_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 */ this->str.ptr = ASE_NULL; this->str.len = 0; } else if (this->val->type == ASE_AWK_VAL_MAP) { ASE_ASSERT (this->run != ASE_NULL); /* when the value is a map, str.ptr and str.len are * used for index iteration in getFirstIndex & getNextIndex */ ase_awk_refdownval (this->run->run, this->val); this->val = ASE_NULL; } else { ASE_ASSERT (this->run != ASE_NULL); if (this->str.ptr != ASE_NULL) { if (this->val->type != ASE_AWK_VAL_STR) { awk_t* awk = this->run->awk->awk; ase_awk_free (awk, this->str.ptr); } this->str.ptr = ASE_NULL; this->str.len = 0; } if (this->val != ASE_NULL) { ase_awk_refdownval (this->run->run, this->val); this->val = ASE_NULL; } } this->rnum = 0.0; this->inum = 0; } void* Awk::Argument::operator new (size_t n, awk_t* awk) throw () { void* ptr = ase_awk_malloc (awk, ASE_SIZEOF(awk) + n); if (ptr == ASE_NULL) return ASE_NULL; *(awk_t**)ptr = awk; return (char*)ptr+ASE_SIZEOF(awk); } void* Awk::Argument::operator new[] (size_t n, awk_t* awk) throw () { void* ptr = ase_awk_malloc (awk, ASE_SIZEOF(awk) + n); if (ptr == ASE_NULL) return ASE_NULL; *(awk_t**)ptr = awk; return (char*)ptr+ASE_SIZEOF(awk); } #if !defined(__BORLANDC__) void Awk::Argument::operator delete (void* ptr, awk_t* awk) { ase_awk_free (awk, (char*)ptr-ASE_SIZEOF(awk)); } void Awk::Argument::operator delete[] (void* ptr, awk_t* awk) { ase_awk_free (awk, (char*)ptr-ASE_SIZEOF(awk)); } #endif void Awk::Argument::operator delete (void* ptr) { void* p = (char*)ptr-ASE_SIZEOF(awk_t*); ase_awk_free (*(awk_t**)p, p); } void Awk::Argument::operator delete[] (void* ptr) { void* p = (char*)ptr-ASE_SIZEOF(awk_t*); ase_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 ASE_ASSERT (this->val == ASE_NULL); ASE_ASSERT (v != ASE_NULL); ase_awk_refupval (this->run->run, v); this->val = v; if (v->type == ASE_AWK_VAL_STR) { int n = ase_awk_valtonum ( this->run->run, v, &this->inum, &this->rnum); if (n == 0) { this->rnum = (ase_real_t)this->inum; return 0; } else if (n == 1) { this->inum = (ase_long_t)this->rnum; return 0; } this->str.ptr = ((ase_awk_val_str_t*)this->val)->buf; this->str.len = ((ase_awk_val_str_t*)this->val)->len; } else if (v->type == ASE_AWK_VAL_INT) { this->inum = ((ase_awk_val_int_t*)v)->val; this->rnum = (ase_real_t)((ase_awk_val_int_t*)v)->val; this->str.ptr = ase_awk_valtostr ( this->run->run, v, 0, ASE_NULL, &this->str.len); if (this->str.ptr != ASE_NULL) return 0; } else if (v->type == ASE_AWK_VAL_REAL) { this->inum = (ase_long_t)((ase_awk_val_real_t*)v)->val; this->rnum = ((ase_awk_val_real_t*)v)->val; this->str.ptr = ase_awk_valtostr ( this->run->run, v, 0, ASE_NULL, &this->str.len); if (this->str.ptr != ASE_NULL) return 0; } else if (v->type == ASE_AWK_VAL_NIL) { this->inum = 0; this->rnum = 0.0; this->str.ptr = ase_awk_valtostr ( this->run->run, v, 0, ASE_NULL, &this->str.len); if (this->str.ptr != ASE_NULL) return 0; } else if (v->type == ASE_AWK_VAL_MAP) { this->inum = 0; this->rnum = 0.0; this->str.ptr = ASE_NULL; this->str.len = 0; return 0; } // an error has occurred ase_awk_refdownval (this->run->run, v); this->val = ASE_NULL; return -1; } int Awk::Argument::init (const char_t* str, size_t len) { ASE_ASSERT (this->val == ASE_NULL); this->str.ptr = (char_t*)str; this->str.len = len; if (ase_awk_strtonum (this->run->run, 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 { if (this->val != ASE_NULL && this->val->type == ASE_AWK_VAL_MAP) { *len = 0; return ASE_T(""); } else if (this->str.ptr == ASE_NULL) { *len = 0; return ASE_T(""); } else { *len = this->str.len; return this->str.ptr; } } bool Awk::Argument::isIndexed () const { if (this->val == ASE_NULL) return false; return this->val->type == ASE_AWK_VAL_MAP; } int Awk::Argument::getIndexed (const char_t* idxptr, Awk::Argument& val) const { return getIndexed (idxptr, ase_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 if (this->val == ASE_NULL) return 0; // not a map. val is just nil. not an error if (this->val->type != ASE_AWK_VAL_MAP) return 0; // get the value from the map. ase_awk_val_map_t* m = (ase_awk_val_map_t*)this->val; ase_awk_pair_t* pair = ase_awk_map_get (m->map, idxptr, idxlen); // the key is not found. it is not an error. val is just nil if (pair == ASE_NULL) return 0; // if val.init fails, it should return an error return val.init ((val_t*)pair->val); } int Awk::Argument::getIndexed (long_t idx, Argument& val) const { val.clear (); // not initialized yet. val is just nil. not an error if (this->val == ASE_NULL) return 0; // not a map. val is just nil. not an error if (this->val->type != ASE_AWK_VAL_MAP) return 0; char_t ri[128]; int rl = Awk::sprintf ( this->run->awk, ri, ASE_COUNTOF(ri), #if ASE_SIZEOF_LONG_LONG > 0 ASE_T("%lld"), (long long)idx #elif ASE_SIZEOF___INT64 > 0 ASE_T("%I64d"), (__int64)idx #elif ASE_SIZEOF_LONG > 0 ASE_T("%ld"), (long)idx #elif ASE_SIZEOF_INT > 0 ASE_T("%d"), (int)idx #else #error unsupported size #endif ); if (rl < 0) { run->setError (ERR_INTERN, 0, ASE_NULL, 0); return -1; } // get the value from the map. ase_awk_val_map_t* m = (ase_awk_val_map_t*)this->val; ase_awk_pair_t* pair = ase_awk_map_get (m->map, ri, rl); // the key is not found. it is not an error. val is just nil if (pair == ASE_NULL) return 0; // if val.init fails, it should return an error return val.init ((val_t*)pair->val); } int Awk::Argument::getFirstIndex (Awk::Argument& val) const { val.clear (); if (this->val == ASE_NULL) return -1; if (this->val->type != ASE_AWK_VAL_MAP) return -1; ase_size_t buckno; ase_awk_val_map_t* m = (ase_awk_val_map_t*)this->val; ase_awk_pair_t* pair = ase_awk_map_getfirstpair (m->map, &buckno); if (pair == ASE_NULL) return 0; // no more key if (val.init (pair->key.ptr, pair->key.len) == -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 (); if (this->val == ASE_NULL) return -1; if (this->val->type != ASE_AWK_VAL_MAP) return -1; ase_awk_val_map_t* m = (ase_awk_val_map_t*)this->val; ase_awk_pair_t* pair = (ase_awk_pair_t*)this->str.ptr; ase_size_t buckno = this->str.len; pair = ase_awk_map_getnextpair (m->map, pair, &buckno); if (pair == ASE_NULL) return 0; if (val.init (pair->key.ptr, pair->key.len) == -1) return -1; // reuse the string field as an interator. this->str.ptr = (char_t*)pair; this->str.len = buckno; return 1; } ////////////////////////////////////////////////////////////////// // Awk::Return ////////////////////////////////////////////////////////////////// Awk::Return::Return (Run& run): run(&run), val(ase_awk_val_nil) { } Awk::Return::Return (Run* run): run(run), val(ase_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) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_val_t* x = ase_awk_makeintval (this->run->run, v); if (x == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refdownval (this->run->run, this->val); this->val = x; ase_awk_refupval (this->run->run, this->val); return 0; } int Awk::Return::set (real_t v) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_val_t* x = ase_awk_makerealval (this->run->run, v); if (x == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refdownval (this->run->run, this->val); this->val = x; ase_awk_refupval (this->run->run, this->val); return 0; } int Awk::Return::set (const char_t* ptr, size_t len) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_val_t* x = ase_awk_makestrval (this->run->run, ptr, len); if (x == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refdownval (this->run->run, this->val); this->val = x; ase_awk_refupval (this->run->run, this->val); return 0; } bool Awk::Return::isIndexed () const { if (this->val == ASE_NULL) return false; return this->val->type == ASE_AWK_VAL_MAP; } int Awk::Return::setIndexed (const char_t* idx, size_t iln, long_t v) { ASE_ASSERT (this->run != ASE_NULL); int opt = this->run->awk->getOption(); if ((opt & OPT_MAPTOVAR) == 0) { /* refer to run_return in run.c */ this->run->setError (ERR_MAPNOTALLOWED, 0, ASE_NULL, 0); return -1; } if (this->val->type != ASE_AWK_VAL_MAP) { ase_awk_val_t* x = ase_awk_makemapval (this->run->run); if (x == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x); ase_awk_val_t* x2 = ase_awk_makeintval (this->run->run, v); if (x2 == ASE_NULL) { ase_awk_refdownval (this->run->run, x); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x2); ase_awk_pair_t* pair = ase_awk_map_put ( ((ase_awk_val_map_t*)x)->map, idx, iln, x2); if (pair == ASE_NULL) { ase_awk_refdownval (this->run->run, x2); ase_awk_refdownval (this->run->run, x); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refdownval (this->run->run, this->val); this->val = x; } else { ase_awk_val_t* x2 = ase_awk_makeintval (this->run->run, v); if (x2 == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x2); ase_awk_pair_t* pair = ase_awk_map_put ( ((ase_awk_val_map_t*)this->val)->map, idx, iln, x2); if (pair == ASE_NULL) { ase_awk_refdownval (this->run->run, x2); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } } return 0; } int Awk::Return::setIndexed (const char_t* idx, size_t iln, real_t v) { ASE_ASSERT (this->run != ASE_NULL); int opt = this->run->awk->getOption(); if ((opt & OPT_MAPTOVAR) == 0) { /* refer to run_return in run.c */ this->run->setError (ERR_MAPNOTALLOWED, 0, ASE_NULL, 0); return -1; } if (this->val->type != ASE_AWK_VAL_MAP) { ase_awk_val_t* x = ase_awk_makemapval (this->run->run); if (x == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x); ase_awk_val_t* x2 = ase_awk_makerealval (this->run->run, v); if (x2 == ASE_NULL) { ase_awk_refdownval (this->run->run, x); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x2); ase_awk_pair_t* pair = ase_awk_map_put ( ((ase_awk_val_map_t*)x)->map, idx, iln, x2); if (pair == ASE_NULL) { ase_awk_refdownval (this->run->run, x2); ase_awk_refdownval (this->run->run, x); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refdownval (this->run->run, this->val); this->val = x; } else { ase_awk_val_t* x2 = ase_awk_makerealval (this->run->run, v); if (x2 == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x2); ase_awk_pair_t* pair = ase_awk_map_put ( ((ase_awk_val_map_t*)this->val)->map, idx, iln, x2); if (pair == ASE_NULL) { ase_awk_refdownval (this->run->run, x2); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } } return 0; } int Awk::Return::setIndexed (const char_t* idx, size_t iln, const char_t* str, size_t sln) { ASE_ASSERT (this->run != ASE_NULL); int opt = this->run->awk->getOption(); if ((opt & OPT_MAPTOVAR) == 0) { /* refer to run_return in run.c */ this->run->setError (ERR_MAPNOTALLOWED, 0, ASE_NULL, 0); return -1; } if (this->val->type != ASE_AWK_VAL_MAP) { ase_awk_val_t* x = ase_awk_makemapval (this->run->run); if (x == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x); ase_awk_val_t* x2 = ase_awk_makestrval (this->run->run, str, sln); if (x2 == ASE_NULL) { ase_awk_refdownval (this->run->run, x); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x2); ase_awk_pair_t* pair = ase_awk_map_put ( ((ase_awk_val_map_t*)x)->map, idx, iln, x2); if (pair == ASE_NULL) { ase_awk_refdownval (this->run->run, x2); ase_awk_refdownval (this->run->run, x); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refdownval (this->run->run, this->val); this->val = x; } else { ase_awk_val_t* x2 = ase_awk_makestrval (this->run->run, str, sln); if (x2 == ASE_NULL) { this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } ase_awk_refupval (this->run->run, x2); ase_awk_pair_t* pair = ase_awk_map_put ( ((ase_awk_val_map_t*)this->val)->map, idx, iln, x2); if (pair == ASE_NULL) { ase_awk_refdownval (this->run->run, x2); this->run->setError (ERR_NOMEM, 0, ASE_NULL, 0); return -1; } } return 0; } int Awk::Return::setIndexed (long_t idx, long_t v) { char_t ri[128]; int rl = Awk::sprintf ( this->run->awk, ri, ASE_COUNTOF(ri), #if ASE_SIZEOF_LONG_LONG > 0 ASE_T("%lld"), (long long)idx #elif ASE_SIZEOF___INT64 > 0 ASE_T("%I64d"), (__int64)idx #elif ASE_SIZEOF_LONG > 0 ASE_T("%ld"), (long)idx #elif ASE_SIZEOF_INT > 0 ASE_T("%d"), (int)idx #else #error unsupported size #endif ); if (rl < 0) { this->run->setError (ERR_INTERN, 0, ASE_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 ( this->run->awk, ri, ASE_COUNTOF(ri), #if ASE_SIZEOF_LONG_LONG > 0 ASE_T("%lld"), (long long)idx #elif ASE_SIZEOF___INT64 > 0 ASE_T("%I64d"), (__int64)idx #elif ASE_SIZEOF_LONG > 0 ASE_T("%ld"), (long)idx #elif ASE_SIZEOF_INT > 0 ASE_T("%d"), (int)idx #else #error unsupported size #endif ); if (rl < 0) { this->run->setError (ERR_INTERN, 0, ASE_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 ( this->run->awk, ri, ASE_COUNTOF(ri), #if ASE_SIZEOF_LONG_LONG > 0 ASE_T("%lld"), (long long)idx #elif ASE_SIZEOF___INT64 > 0 ASE_T("%I64d"), (__int64)idx #elif ASE_SIZEOF_LONG > 0 ASE_T("%ld"), (long)idx #elif ASE_SIZEOF_INT > 0 ASE_T("%d"), (int)idx #else #error unsupported size #endif ); if (rl < 0) { this->run->setError (ERR_INTERN, 0, ASE_NULL, 0); return -1; } return setIndexed (ri, rl, str, sln); } void Awk::Return::clear () { ase_awk_refdownval (this->run->run, this->val); this->val = ase_awk_val_nil; } ////////////////////////////////////////////////////////////////// // Awk::Run ////////////////////////////////////////////////////////////////// Awk::Run::Run (Awk* awk): awk (awk), run (ASE_NULL), callbackFailed (false) { } Awk::Run::Run (Awk* awk, run_t* run): awk (awk), run (run), callbackFailed (false), custom (ASE_NULL) { ASE_ASSERT (this->run != ASE_NULL); } Awk::Run::~Run () { } Awk::Run::operator Awk* () const { return this->awk; } Awk::Run::operator Awk::run_t* () const { return this->run; } void Awk::Run::stop () const { ASE_ASSERT (this->run != ASE_NULL); ase_awk_stop (this->run); } bool Awk::Run::isStop () const { ASE_ASSERT (this->run != ASE_NULL); return ase_awk_isstop (this->run)? true: false; } Awk::ErrorCode Awk::Run::getErrorCode () const { ASE_ASSERT (this->run != ASE_NULL); return (ErrorCode)ase_awk_getrunerrnum (this->run); } Awk::size_t Awk::Run::getErrorLine () const { ASE_ASSERT (this->run != ASE_NULL); return ase_awk_getrunerrlin (this->run); } const Awk::char_t* Awk::Run::getErrorMessage () const { ASE_ASSERT (this->run != ASE_NULL); return ase_awk_getrunerrmsg (this->run); } void Awk::Run::setError (ErrorCode code) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_setrunerror (this->run, code, 0, ASE_NULL, 0); } void Awk::Run::setError (ErrorCode code, size_t line) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_setrunerror (this->run, code, line, ASE_NULL, 0); } void Awk::Run::setError (ErrorCode code, size_t line, const char_t* arg) { ASE_ASSERT (this->run != ASE_NULL); ase_cstr_t x = { arg, ase_strlen(arg) }; ase_awk_setrunerror (this->run, code, line, &x, 1); } void Awk::Run::setError ( ErrorCode code, size_t line, const char_t* arg, size_t len) { ASE_ASSERT (this->run != ASE_NULL); ase_cstr_t x = { arg, len }; ase_awk_setrunerror (this->run, code, line, &x, 1); } void Awk::Run::setErrorWithMessage ( ErrorCode code, size_t line, const char_t* msg) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_setrunerrmsg (this->run, code, line, msg); } int Awk::Run::setGlobal (int id, long_t v) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_val_t* tmp = ase_awk_makeintval (run, v); if (tmp == ASE_NULL) { setError (ERR_NOMEM); return -1; } ase_awk_refupval (run, tmp); int n = ase_awk_setglobal (this->run, id, tmp); ase_awk_refdownval (run, tmp); return n; } int Awk::Run::setGlobal (int id, real_t v) { ASE_ASSERT (this->run != ASE_NULL); ase_awk_val_t* tmp = ase_awk_makerealval (run, v); if (tmp == ASE_NULL) { setError (ERR_NOMEM); return -1; } ase_awk_refupval (run, tmp); int n = ase_awk_setglobal (this->run, id, tmp); ase_awk_refdownval (run, tmp); return n; } int Awk::Run::setGlobal (int id, const char_t* ptr, size_t len) { ASE_ASSERT (run != ASE_NULL); ase_awk_val_t* tmp = ase_awk_makestrval (run, ptr, len); if (tmp == ASE_NULL) { setError (ERR_NOMEM); return -1; } ase_awk_refupval (run, tmp); int n = ase_awk_setglobal (this->run, id, tmp); ase_awk_refdownval (run, tmp); return n; } int Awk::Run::setGlobal (int id, const Return& global) { ASE_ASSERT (this->run != ASE_NULL); return ase_awk_setglobal (this->run, id, global.toVal()); } int Awk::Run::getGlobal (int id, Argument& global) const { ASE_ASSERT (this->run != ASE_NULL); global.clear (); return global.init (ase_awk_getglobal(this->run,id)); } void Awk::Run::setCustom (void* custom) { this->custom = custom; } void* Awk::Run::getCustom () const { return this->custom; } ////////////////////////////////////////////////////////////////// // Awk ////////////////////////////////////////////////////////////////// Awk::Awk (): awk (ASE_NULL), functionMap (ASE_NULL), sourceIn (Source::READ), sourceOut (Source::WRITE), errnum (ERR_NOERR), errlin (0), runCallback (false) { this->errmsg[0] = ASE_T('\0'); } Awk::~Awk () { } Awk::operator Awk::awk_t* () const { return this->awk; } Awk::ErrorCode Awk::getErrorCode () const { return this->errnum; } Awk::size_t Awk::getErrorLine () const { return this->errlin; } const Awk::char_t* Awk::getErrorMessage () const { return this->errmsg; } void Awk::setError (ErrorCode code) { setError (code, 0, ASE_NULL, 0); } void Awk::setError (ErrorCode code, size_t line) { setError (code, line, ASE_NULL, 0); } void Awk::setError (ErrorCode code, size_t line, const char_t* arg) { setError (code, line, arg, ase_strlen(arg)); } void Awk::setError (ErrorCode code, size_t line, const char_t* arg, size_t len) { if (awk != ASE_NULL) { ase_cstr_t x = { arg, len }; ase_awk_seterror (awk, code, line, &x, 1); retrieveError (); } else { this->errnum = code; this->errlin = line; const char_t* es = ase_awk_geterrstr (ASE_NULL, code); ase_strxcpy (this->errmsg, ASE_COUNTOF(this->errmsg), es); } } void Awk::setErrorWithMessage (ErrorCode code, size_t line, const char_t* msg) { if (awk != ASE_NULL) { ase_awk_seterrmsg (awk, code, line, msg); retrieveError (); } else { this->errnum = code; this->errlin = line; ase_strxcpy (this->errmsg, ASE_COUNTOF(this->errmsg), msg); } } void Awk::clearError () { this->errnum = ERR_NOERR; this->errlin = 0; this->errmsg[0] = ASE_T('\0'); } void Awk::retrieveError () { if (this->awk == ASE_NULL) { clearError (); } else { int num; const char_t* msg; ase_awk_geterror (this->awk, &num, &this->errlin, &msg); this->errnum = (ErrorCode)num; ase_strxcpy (this->errmsg, ASE_COUNTOF(this->errmsg), msg); } } int Awk::open () { ASE_ASSERT (awk == ASE_NULL && functionMap == ASE_NULL); ase_awk_prmfns_t prmfns; prmfns.mmgr.malloc = allocMem; prmfns.mmgr.realloc = reallocMem; prmfns.mmgr.free = freeMem; prmfns.mmgr.custom_data = this; prmfns.ccls.is_upper = isUpper; prmfns.ccls.is_lower = isLower; prmfns.ccls.is_alpha = isAlpha; prmfns.ccls.is_digit = isDigit; prmfns.ccls.is_xdigit = isXdigit; prmfns.ccls.is_alnum = isAlnum; prmfns.ccls.is_space = isSpace; prmfns.ccls.is_print = isPrint; prmfns.ccls.is_graph = isGraph; prmfns.ccls.is_cntrl = isCntrl; prmfns.ccls.is_punct = isPunct; prmfns.ccls.to_upper = toUpper; prmfns.ccls.to_lower = toLower; prmfns.ccls.custom_data = this; prmfns.misc.pow = pow; prmfns.misc.sprintf = sprintf; prmfns.misc.dprintf = dprintf; prmfns.misc.custom_data = this; awk = ase_awk_open (&prmfns, this); if (awk == ASE_NULL) { setError (ERR_NOMEM); return -1; } functionMap = ase_awk_map_open ( this, 512, 70, freeFunctionMapValue, awk); if (functionMap == ASE_NULL) { ase_awk_close (awk); awk = ASE_NULL; setError (ERR_NOMEM); return -1; } int opt = OPT_IMPLICIT | OPT_UNIQUEFN | OPT_SHADING | OPT_EXTIO | OPT_BLOCKLESS | OPT_BASEONE | OPT_PABLOCK; ase_awk_setoption (awk, opt); runCallback = false; return 0; } void Awk::close () { if (functionMap != ASE_NULL) { ase_awk_map_close (functionMap); functionMap = ASE_NULL; } if (awk != ASE_NULL) { ase_awk_close (awk); awk = ASE_NULL; } clearError (); runCallback = false; } void Awk::setOption (int opt) { ASE_ASSERT (awk != ASE_NULL); ase_awk_setoption (awk, opt); } int Awk::getOption () const { ASE_ASSERT (awk != ASE_NULL); return ase_awk_getoption (awk); } void Awk::setMaxDepth (int ids, size_t depth) { ASE_ASSERT (awk != ASE_NULL); ase_awk_setmaxdepth (awk, ids, depth); } Awk::size_t Awk::getMaxDepth (int id) const { ASE_ASSERT (awk != ASE_NULL); return ase_awk_getmaxdepth (awk, id); } const Awk::char_t* Awk::getErrorString (ErrorCode num) const { ASE_ASSERT (awk != ASE_NULL); return ase_awk_geterrstr (awk, (int)num); } int Awk::setErrorString (ErrorCode num, const char_t* str) { ASE_ASSERT (awk != ASE_NULL); return ase_awk_seterrstr (awk, (int)num, str); } int Awk::setWord (const char_t* ow, const char_t* nw) { return setWord (ow, ase_strlen(ow), nw, ase_strlen(nw)); } int Awk::setWord ( const char_t* ow, ase_size_t owl, const char_t* nw, ase_size_t nwl) { ASE_ASSERT (awk != ASE_NULL); return ase_awk_setword (awk, ow, owl, nw, nwl); } int Awk::unsetWord (const char_t* ow) { return unsetWord (ow, ase_strlen(ow)); } int Awk::unsetWord (const char_t* ow, ase_size_t owl) { ASE_ASSERT (awk != ASE_NULL); return ase_awk_setword (awk, ow, owl, ASE_NULL, 0); } int Awk::unsetAllWords () { ASE_ASSERT (awk != ASE_NULL); return ase_awk_setword (awk, ASE_NULL, 0, ASE_NULL, 0); } int Awk::parse () { ASE_ASSERT (awk != ASE_NULL); ase_awk_srcios_t srcios; srcios.in = sourceReader; srcios.out = sourceWriter; srcios.custom_data = this; int n = ase_awk_parse (awk, &srcios); if (n == -1) retrieveError (); return n; } int Awk::run (const char_t* main, const char_t** args, size_t nargs) { ASE_ASSERT (awk != ASE_NULL); size_t i; ase_awk_runios_t runios; ase_awk_runcbs_t runcbs; ase_awk_runarg_t* runarg = ASE_NULL; // make sure that the run field is set in Awk::onRunStart. Run runctx (this); runios.pipe = pipeHandler; runios.coproc = ASE_NULL; runios.file = fileHandler; runios.console = consoleHandler; runios.custom_data = this; ase_memset (&runcbs, 0, ASE_SIZEOF(runcbs)); runcbs.on_start = onRunStart; if (runCallback) { runcbs.on_end = onRunEnd; runcbs.on_return = onRunReturn; runcbs.on_statement = onRunStatement; } runcbs.custom_data = &runctx; if (nargs > 0) { runarg = (ase_awk_runarg_t*) ase_awk_malloc ( awk, ASE_SIZEOF(ase_awk_runarg_t)*(nargs+1)); if (runarg == ASE_NULL) { setError (ERR_NOMEM); return -1; } for (i = 0; i < nargs; i++) { runarg[i].len = ase_strlen (args[i]); runarg[i].ptr = ase_awk_strxdup (awk, args[i], runarg[i].len); if (runarg[i].ptr == ASE_NULL) { while (i > 0) ase_awk_free (awk, runarg[--i].ptr); ase_awk_free (awk, runarg); setError (ERR_NOMEM); return -1; } } runarg[i].ptr = ASE_NULL; runarg[i].len = 0; } int n = ase_awk_run (awk, main, &runios, &runcbs, runarg, &runctx); if (n == -1) retrieveError (); if (runarg != ASE_NULL) { while (i > 0) ase_awk_free (awk, runarg[--i].ptr); ase_awk_free (awk, runarg); } return n; } void Awk::stop () { ASE_ASSERT (awk != ASE_NULL); ase_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 = ase_awk_getrunawk (run); pair = ase_awk_map_get (functionMap, name, len); if (pair == ASE_NULL) { run->setError (ERR_FNNONE, 0, name, len); return -1; } FunctionHandler handler; handler = *(FunctionHandler*)ASE_AWK_PAIR_VAL(pair); size_t i, nargs = ase_awk_getnargs(run->run); //Argument* args = ASE_NULL; //try { args = new Argument [nargs]; } catch (...) {} Argument* args = new(awk) Argument[nargs]; if (args == ASE_NULL) { run->setError (ERR_NOMEM, 0, ASE_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 = ase_awk_getarg (run->run, i); if (args[i].init (v) == -1) { run->setError (ERR_NOMEM, 0, ASE_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; } ase_awk_setretval (run->run, ret); return 0; } int Awk::addGlobal (const char_t* name) { ASE_ASSERT (awk != ASE_NULL); int n = ase_awk_addglobal (awk, name, ase_strlen(name)); if (n == -1) retrieveError (); return n; } int Awk::deleteGlobal (const char_t* name) { ASE_ASSERT (awk != ASE_NULL); int n = ase_awk_delglobal (awk, name, ase_strlen(name)); if (n == -1) retrieveError (); return n; } int Awk::addFunction ( const char_t* name, size_t minArgs, size_t maxArgs, FunctionHandler handler) { ASE_ASSERT (awk != ASE_NULL); FunctionHandler* tmp = (FunctionHandler*) ase_awk_malloc (awk, ASE_SIZEOF(handler)); if (tmp == ASE_NULL) { setError (ERR_NOMEM); return -1; } //ase_memcpy (tmp, &handler, ASE_SIZEOF(handler)); *tmp = handler; size_t nameLen = ase_strlen(name); void* p = ase_awk_addfunc (awk, name, nameLen, 0, minArgs, maxArgs, ASE_NULL, functionHandler); if (p == ASE_NULL) { ase_awk_free (awk, tmp); retrieveError (); return -1; } pair_t* pair = ase_awk_map_put (functionMap, name, nameLen, tmp); if (pair == ASE_NULL) { ase_awk_delfunc (awk, name, nameLen); ase_awk_free (awk, tmp); setError (ERR_NOMEM); return -1; } return 0; } int Awk::deleteFunction (const char_t* name) { ASE_ASSERT (awk != ASE_NULL); size_t nameLen = ase_strlen(name); int n = ase_awk_delfunc (awk, name, nameLen); if (n == 0) ase_awk_map_remove (functionMap, name, nameLen); else retrieveError (); return n; } void Awk::enableRunCallback () { runCallback = true; } void Awk::disableRunCallback () { runCallback = false; } void Awk::triggerOnRunStart (Run& run) { if (runCallback) onRunStart (run); } void Awk::onRunStart (Run& run) { } void Awk::onRunEnd (Run& run) { } void Awk::onRunReturn (Run& run, const Argument& ret) { } void Awk::onRunStatement (Run& run, size_t line) { } Awk::ssize_t Awk::sourceReader ( int cmd, void* arg, char_t* data, size_t count) { Awk* awk = (Awk*)arg; switch (cmd) { case ASE_AWK_IO_OPEN: return awk->openSource (awk->sourceIn); case ASE_AWK_IO_CLOSE: return awk->closeSource (awk->sourceIn); case ASE_AWK_IO_READ: return awk->readSource (awk->sourceIn, data, count); } return -1; } Awk::ssize_t Awk::sourceWriter ( int cmd, void* arg, char_t* data, size_t count) { Awk* awk = (Awk*)arg; switch (cmd) { case ASE_AWK_IO_OPEN: return awk->openSource (awk->sourceOut); case ASE_AWK_IO_CLOSE: return awk->closeSource (awk->sourceOut); case ASE_AWK_IO_WRITE: return awk->writeSource (awk->sourceOut, data, count); } return -1; } Awk::ssize_t Awk::pipeHandler ( int cmd, void* arg, char_t* data, size_t count) { extio_t* extio = (extio_t*)arg; Awk* awk = (Awk*)extio->custom_data; ASE_ASSERT ((extio->type & 0xFF) == ASE_AWK_EXTIO_PIPE); Pipe pipe (extio); switch (cmd) { case ASE_AWK_IO_OPEN: return awk->openPipe (pipe); case ASE_AWK_IO_CLOSE: return awk->closePipe (pipe); case ASE_AWK_IO_READ: return awk->readPipe (pipe, data, count); case ASE_AWK_IO_WRITE: return awk->writePipe (pipe, data, count); case ASE_AWK_IO_FLUSH: return awk->flushPipe (pipe); case ASE_AWK_IO_NEXT: return -1; } return -1; } Awk::ssize_t Awk::fileHandler ( int cmd, void* arg, char_t* data, size_t count) { extio_t* extio = (extio_t*)arg; Awk* awk = (Awk*)extio->custom_data; ASE_ASSERT ((extio->type & 0xFF) == ASE_AWK_EXTIO_FILE); File file (extio); switch (cmd) { case ASE_AWK_IO_OPEN: return awk->openFile (file); case ASE_AWK_IO_CLOSE: return awk->closeFile (file); case ASE_AWK_IO_READ: return awk->readFile (file, data, count); case ASE_AWK_IO_WRITE: return awk->writeFile (file, data, count); case ASE_AWK_IO_FLUSH: return awk->flushFile (file); case ASE_AWK_IO_NEXT: return -1; } return -1; } Awk::ssize_t Awk::consoleHandler ( int cmd, void* arg, char_t* data, size_t count) { extio_t* extio = (extio_t*)arg; Awk* awk = (Awk*)extio->custom_data; ASE_ASSERT ((extio->type & 0xFF) == ASE_AWK_EXTIO_CONSOLE); Console console (extio); switch (cmd) { case ASE_AWK_IO_OPEN: return awk->openConsole (console); case ASE_AWK_IO_CLOSE: return awk->closeConsole (console); case ASE_AWK_IO_READ: return awk->readConsole (console, data, count); case ASE_AWK_IO_WRITE: return awk->writeConsole (console, data, count); case ASE_AWK_IO_FLUSH: return awk->flushConsole (console); case ASE_AWK_IO_NEXT: return awk->nextConsole (console); } return -1; } int Awk::functionHandler ( run_t* run, const char_t* name, size_t len) { Run* ctx = (Run*) ase_awk_getruncustomdata (run); Awk* awk = ctx->awk; return awk->dispatchFunction (ctx, name, len); } void Awk::freeFunctionMapValue (void* owner, void* value) { Awk* awk = (Awk*)owner; ase_awk_free (awk->awk, value); } void Awk::onRunStart (run_t* run, void* custom) { Run* r = (Run*)custom; // the actual run_t value for the run-time callback is set here. // r here refers to runctx declared in Awk::run. As onRunStart // is executed immediately after the run method is invoked, // the run field can be set safely here. This seems to be the // only place to acquire the run_t value safely as Awk::run // is blocking. r->run = run; r->callbackFailed = false; r->awk->triggerOnRunStart (*r); } void Awk::onRunEnd (run_t* run, int errnum, void* custom) { Run* r = (Run*)custom; if (errnum == ERR_NOERR && r->callbackFailed) { ase_awk_setrunerror ( r->run, ERR_NOMEM, 0, ASE_NULL, 0); } r->awk->onRunEnd (*r); } void Awk::onRunReturn (run_t* run, val_t* ret, void* custom) { Run* r = (Run*)custom; if (r->callbackFailed) return; Argument x (r); if (x.init (ret) == -1) { r->callbackFailed = true; } else { r->awk->onRunReturn (*r, x); } } void Awk::onRunStatement (run_t* run, size_t line, void* custom) { Run* r = (Run*)custom; if (r->callbackFailed) return; r->awk->onRunStatement (*r, line); } void* Awk::allocMem (void* custom, size_t n) { return ((Awk*)custom)->allocMem (n); } void* Awk::reallocMem (void* custom, void* ptr, size_t n) { return ((Awk*)custom)->reallocMem (ptr, n); } void Awk::freeMem (void* custom, void* ptr) { ((Awk*)custom)->freeMem (ptr); } Awk::bool_t Awk::isUpper (void* custom, cint_t c) { return ((Awk*)custom)->isUpper (c); } Awk::bool_t Awk::isLower (void* custom, cint_t c) { return ((Awk*)custom)->isLower (c); } Awk::bool_t Awk::isAlpha (void* custom, cint_t c) { return ((Awk*)custom)->isAlpha (c); } Awk::bool_t Awk::isDigit (void* custom, cint_t c) { return ((Awk*)custom)->isDigit (c); } Awk::bool_t Awk::isXdigit (void* custom, cint_t c) { return ((Awk*)custom)->isXdigit (c); } Awk::bool_t Awk::isAlnum (void* custom, cint_t c) { return ((Awk*)custom)->isAlnum (c); } Awk::bool_t Awk::isSpace (void* custom, cint_t c) { return ((Awk*)custom)->isSpace (c); } Awk::bool_t Awk::isPrint (void* custom, cint_t c) { return ((Awk*)custom)->isPrint (c); } Awk::bool_t Awk::isGraph (void* custom, cint_t c) { return ((Awk*)custom)->isGraph (c); } Awk::bool_t Awk::isCntrl (void* custom, cint_t c) { return ((Awk*)custom)->isCntrl (c); } Awk::bool_t Awk::isPunct (void* custom, cint_t c) { return ((Awk*)custom)->isPunct (c); } Awk::cint_t Awk::toUpper (void* custom, cint_t c) { return ((Awk*)custom)->toUpper (c); } Awk::cint_t Awk::toLower (void* custom, cint_t c) { return ((Awk*)custom)->toLower (c); } Awk::real_t Awk::pow (void* custom, real_t x, real_t y) { return ((Awk*)custom)->pow (x, y); } int Awk::sprintf (void* custom, char_t* buf, size_t size, const char_t* fmt, ...) { va_list ap; va_start (ap, fmt); int n = ((Awk*)custom)->vsprintf (buf, size, fmt, ap); va_end (ap); return n; } void Awk::dprintf (void* custom, const char_t* fmt, ...) { va_list ap; va_start (ap, fmt); ((Awk*)custom)->vdprintf (fmt, ap); va_end (ap); } ///////////////////////////////// ASE_END_NAMESPACE(ASE) /////////////////////////////////