enhanced Awk classes

This commit is contained in:
hyung-hwan 2009-07-09 07:01:45 +00:00
parent b682392d5f
commit 1d88a17c7c
4 changed files with 166 additions and 92 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: Awk.hpp 224 2009-07-07 13:05:10Z hyunghwan.chung $ * $Id: Awk.hpp 225 2009-07-08 13:01:45Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -87,7 +87,7 @@ public:
* and Source::WRITE respectively when called from * and Source::WRITE respectively when called from
* Awk::readSource and Awk::writeSource. * Awk::readSource and Awk::writeSource.
* *
* <pre> * @code
* int openSource (Source& io) * int openSource (Source& io)
* { * {
* if (io.getMode() == Source::READ) * if (io.getMode() == Source::READ)
@ -117,7 +117,7 @@ public:
* } * }
* return -1; * return -1;
* } * }
* </pre> * @endcode
* *
* @return Awk::Source::READ or Awk::Source::WRITE * @return Awk::Source::READ or Awk::Source::WRITE
*/ */
@ -131,7 +131,7 @@ public:
* Awk::closeSource to get the value set in Awk::openSource * Awk::closeSource to get the value set in Awk::openSource
* as shown in the example below. * as shown in the example below.
* *
* <pre> * @code
* int closeSource (Source& io) * int closeSource (Source& io)
* { * {
* if (io.getMode() == Source::READ) * if (io.getMode() == Source::READ)
@ -146,10 +146,10 @@ public:
* } * }
* return -1; * return -1;
* } * }
* </pre> * @endcode
* *
* @return an arbitrary value of type void* set with * @return an arbitrary value of type void* set with
* Source::setHandle or QSE_NULL * Source::setHandle() or QSE_NULL
*/ */
const void* getHandle () const; const void* getHandle () const;
@ -526,7 +526,6 @@ public:
}; };
// end of enum ErrorNumber // end of enum ErrorNumber
// generated by genoptcode.awk // generated by genoptcode.awk
/** Defines options */ /** Defines options */
enum Option enum Option
@ -708,23 +707,12 @@ public:
*/ */
int getGlobal (int id, Argument& global) const; int getGlobal (int id, Argument& global) const;
/**
* Sets a value into the data field
*/
void setData (void* data);
/**
* Gets the value stored in the data field
*/
void* getData () const;
void* alloc (size_t size); void* alloc (size_t size);
void free (void* ptr); void free (void* ptr);
protected: protected:
Awk* awk; Awk* awk;
rtx_t* rtx; rtx_t* rtx;
void* data;
}; };
/** Constructor */ /** Constructor */
@ -829,9 +817,9 @@ public:
* override Awk::openSource, Awk::closeSource, Awk::readSource, * override Awk::openSource, Awk::closeSource, Awk::readSource,
* Awk::writeSource to implement the source code stream. * Awk::writeSource to implement the source code stream.
* *
* @return 0 on success, -1 on failure * @return a Run object on success, QSE_NULL on failure
*/ */
virtual int parse (); virtual Awk::Run* parse ();
/** /**
* Executes the BEGIN block, pattern-action blocks, and the END block. * Executes the BEGIN block, pattern-action blocks, and the END block.
@ -839,6 +827,15 @@ public:
*/ */
virtual int loop (); virtual int loop ();
/**
* Calls a function
*/
virtual int call (
const char_t* name,
const Return* args,
size_t nargs
);
/** /**
* Makes request to abort execution * Makes request to abort execution
*/ */
@ -1077,6 +1074,11 @@ protected:
xstrs_t runarg; xstrs_t runarg;
private: private:
Run runctx;
int init_runctx ();
void fini_runctx ();
static const char_t* xerrstr (awk_t* a, errnum_t num) throw (); static const char_t* xerrstr (awk_t* a, errnum_t num) throw ();
private: private:

View File

@ -1,5 +1,5 @@
/* /*
* $Id: Awk.cpp 224 2009-07-07 13:05:10Z hyunghwan.chung $ * $Id: Awk.cpp 225 2009-07-08 13:01:45Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -226,8 +226,8 @@ void Awk::Argument::clear ()
{ {
/* case 1. not initialized. /* case 1. not initialized.
* case 2. initialized with the second init. * case 2. initialized with the second init.
* none of the cases creates a new string so the sttring * none of the cases. create a new string so the sttring
* that str.ptr is pointing at doesn't have to be freed */ * that str.ptr is pointing to doesn't have to be freed */
this->str.ptr = QSE_NULL; this->str.ptr = QSE_NULL;
this->str.len = 0; this->str.len = 0;
} }
@ -918,7 +918,7 @@ Awk::Run::Run (Awk* awk): awk (awk), rtx (QSE_NULL)
{ {
} }
Awk::Run::Run (Awk* awk, rtx_t* rtx): awk (awk), rtx (rtx), data (QSE_NULL) Awk::Run::Run (Awk* awk, rtx_t* rtx): awk (awk), rtx (rtx)
{ {
QSE_ASSERT (this->rtx != QSE_NULL); QSE_ASSERT (this->rtx != QSE_NULL);
} }
@ -1062,23 +1062,14 @@ int Awk::Run::getGlobal (int id, Argument& gbl) const
return gbl.init (qse_awk_rtx_getgbl (this->rtx, id)); return gbl.init (qse_awk_rtx_getgbl (this->rtx, id));
} }
void Awk::Run::setData (void* data)
{
this->data = data;
}
void* Awk::Run::getData () const
{
return this->data;
}
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// Awk // Awk
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
Awk::Awk () throw (): awk (QSE_NULL), functionMap (QSE_NULL), Awk::Awk () throw (): awk (QSE_NULL), functionMap (QSE_NULL),
sourceIn (Source::READ), sourceOut (Source::WRITE), sourceIn (Source::READ), sourceOut (Source::WRITE),
errnum (ERR_NOERR), errlin (0), runCallback (false) errnum (ERR_NOERR), errlin (0), runCallback (false),
runctx (this)
{ {
this->errmsg[0] = QSE_T('\0'); this->errmsg[0] = QSE_T('\0');
@ -1238,6 +1229,7 @@ int Awk::open ()
void Awk::close () void Awk::close ()
{ {
fini_runctx ();
clearArguments (); clearArguments ();
if (functionMap != QSE_NULL) if (functionMap != QSE_NULL)
@ -1337,31 +1329,34 @@ int Awk::unsetAllWords ()
return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0); return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0);
} }
int Awk::parse () Awk::Run* Awk::parse ()
{ {
QSE_ASSERT (awk != QSE_NULL); QSE_ASSERT (awk != QSE_NULL);
qse_awk_sio_t sio; fini_runctx ();
qse_awk_sio_t sio;
sio.in = sourceReader; sio.in = sourceReader;
sio.out = sourceWriter; sio.out = sourceWriter;
int n = qse_awk_parse (awk, &sio); int n = qse_awk_parse (awk, &sio);
if (n == -1) retrieveError (); if (n <= -1)
return n; {
retrieveError ();
return QSE_NULL;
}
if (init_runctx () <= -1) return QSE_NULL;
return &runctx;
} }
int Awk::loop () int Awk::init_runctx ()
{ {
QSE_ASSERT (awk != QSE_NULL); if (runctx.rtx != QSE_NULL) return 0;
qse_awk_rio_t rio; qse_awk_rio_t rio;
qse_awk_rcb_t rcb; qse_awk_rcb_t rcb;
// note that the run field is set below after qse_awk_rtx_open() is
// executed.
Run runctx (this);
rio.pipe = pipeHandler; rio.pipe = pipeHandler;
rio.file = fileHandler; rio.file = fileHandler;
rio.console = consoleHandler; rio.console = consoleHandler;
@ -1375,28 +1370,74 @@ int Awk::loop ()
rcb.udd = &runctx; rcb.udd = &runctx;
} }
int n = 0;
rtx_t* rtx = qse_awk_rtx_open ( rtx_t* rtx = qse_awk_rtx_open (
awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg.ptr); awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg.ptr);
if (rtx == QSE_NULL) if (rtx == QSE_NULL)
{ {
retrieveError(); retrieveError();
n = -1; return -1;
} }
else
{
runctx.rtx = rtx; runctx.rtx = rtx;
rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx); rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx);
rxtn->run = &runctx; rxtn->run = &runctx;
if (runCallback) qse_awk_rtx_setrcb (rtx, &rcb); if (runCallback) qse_awk_rtx_setrcb (rtx, &rcb);
n = qse_awk_rtx_loop (rtx); return 0;
if (n == -1) retrieveError (rtx); }
qse_awk_rtx_close (rtx);
void Awk::fini_runctx ()
{
if (runctx.rtx != QSE_NULL)
{
qse_awk_rtx_close (runctx.rtx);
runctx.rtx = QSE_NULL;
}
}
int Awk::loop ()
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (runctx.rtx != QSE_NULL);
int n = qse_awk_rtx_loop (runctx.rtx);
if (n <= -1) retrieveError (runctx.rtx);
return n;
}
int Awk::call (const char_t* name, const Return* args, size_t nargs)
{
QSE_ASSERT (awk != QSE_NULL);
QSE_ASSERT (runctx.rtx != QSE_NULL);
val_t** ptr = QSE_NULL;
if (args != QSE_NULL)
{
ptr = (val_t**) qse_awk_alloc (awk, QSE_SIZEOF(val_t*) * nargs);
if (ptr == QSE_NULL)
{
runctx.setError (ERR_NOMEM);
return -1;
} }
return n; for (size_t i = 0; i < nargs; i++) ptr[i] = args[i].val;
}
val_t* ret = qse_awk_rtx_call (runctx.rtx, name, ptr, nargs);
if (ptr != QSE_NULL) qse_awk_free (awk, ptr);
if (ret == QSE_NULL)
{
retrieveError (runctx.rtx);
return -1;
}
// TODO: how can i store it???
qse_awk_rtx_refdownval (runctx.rtx, ret);
return 0;
} }
void Awk::stop () void Awk::stop ()
@ -1410,8 +1451,6 @@ int Awk::dispatchFunction (Run* run, const char_t* name, size_t len)
pair_t* pair; pair_t* pair;
awk_t* awk = run->awk->awk; awk_t* awk = run->awk->awk;
//awk = qse_awk_rtx_getawk (run);
pair = qse_map_search (functionMap, name, len); pair = qse_map_search (functionMap, name, len);
if (pair == QSE_NULL) if (pair == QSE_NULL)
{ {
@ -1495,9 +1534,11 @@ void Awk::xstrs_t::clear (awk_t* awk)
{ {
if (this->ptr != QSE_NULL) if (this->ptr != QSE_NULL)
{ {
while (this->len > 0)
qse_awk_free (awk, this->ptr[--this->len].ptr);
qse_awk_free (awk, this->ptr); qse_awk_free (awk, this->ptr);
this->ptr = QSE_NULL; this->ptr = QSE_NULL;
this->len = 0;
this->capa = 0; this->capa = 0;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: StdAwk.cpp 224 2009-07-07 13:05:10Z hyunghwan.chung $ * $Id: StdAwk.cpp 225 2009-07-08 13:01:45Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -480,8 +480,10 @@ int StdAwk::open_console_in (Console& io)
map = ((qse_awk_val_map_t*)argv)->map; map = ((qse_awk_val_map_t*)argv)->map;
QSE_ASSERT (map != QSE_NULL); QSE_ASSERT (map != QSE_NULL);
// ok to find ARGV[runarg_index] as ARGV[0]
// has been skipped.
ibuflen = qse_awk_longtostr ( ibuflen = qse_awk_longtostr (
rtx->awk, runarg_index + 1, rtx->awk, runarg_index,
10, QSE_NULL, 10, QSE_NULL,
ibuf, QSE_COUNTOF(ibuf) ibuf, QSE_COUNTOF(ibuf)
); );
@ -622,6 +624,11 @@ int StdAwk::openConsole (Console& io)
{ {
runarg_count = 0; runarg_count = 0;
runarg_index = 0; runarg_index = 0;
if (runarg.len > 0)
{
// skip ARGV[0]
runarg_index++;
}
return open_console_in (io); return open_console_in (io);
} }
else else

View File

@ -32,7 +32,7 @@
# include <errno.h> # include <errno.h>
#endif #endif
class TestAwk; class MyAwk;
#ifdef _WIN32 #ifdef _WIN32
static BOOL WINAPI stop_run (DWORD ctrl_type); static BOOL WINAPI stop_run (DWORD ctrl_type);
#else #else
@ -42,13 +42,13 @@ static void stop_run (int sig);
static void set_intr_run (void); static void set_intr_run (void);
static void unset_intr_run (void); static void unset_intr_run (void);
TestAwk* app_awk = QSE_NULL; MyAwk* app_awk = QSE_NULL;
static bool verbose = false; static bool verbose = false;
class TestAwk: public QSE::StdAwk class MyAwk: public QSE::StdAwk
{ {
public: public:
TestAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL) MyAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -56,7 +56,7 @@ public:
#endif #endif
} }
~TestAwk () ~MyAwk ()
{ {
close (); close ();
} }
@ -83,13 +83,13 @@ public:
if (idLastSleep <= -1) goto failure; if (idLastSleep <= -1) goto failure;
if (addFunction (QSE_T("sleep"), 1, 1, if (addFunction (QSE_T("sleep"), 1, 1,
(FunctionHandler)&TestAwk::sleep) <= -1) goto failure; (FunctionHandler)&MyAwk::sleep) <= -1) goto failure;
if (addFunction (QSE_T("sumintarray"), 1, 1, if (addFunction (QSE_T("sumintarray"), 1, 1,
(FunctionHandler)&TestAwk::sumintarray) <= -1) goto failure; (FunctionHandler)&MyAwk::sumintarray) <= -1) goto failure;
if (addFunction (QSE_T("arrayindices"), 1, 1, if (addFunction (QSE_T("arrayindices"), 1, 1,
(FunctionHandler)&TestAwk::arrayindices) <= -1) goto failure; (FunctionHandler)&MyAwk::arrayindices) <= -1) goto failure;
return 0; return 0;
failure: failure:
@ -190,7 +190,7 @@ public:
return 0; return 0;
} }
int parse (const char_t* in, const char_t* out) Run* parse (const char_t* in, const char_t* out)
{ {
srcInName = in; srcInName = in;
srcOutName = out; srcOutName = out;
@ -199,13 +199,13 @@ public:
protected: protected:
bool onRunEnter (Run& run) bool onLoopEnter (Run& run)
{ {
set_intr_run (); set_intr_run ();
return true; return true;
} }
void onRunExit (Run& run, const Argument& ret) void onLoopExit (Run& run, const Argument& ret)
{ {
unset_intr_run (); unset_intr_run ();
@ -414,29 +414,29 @@ static void unset_intr_run (void)
static void print_error (const qse_char_t* msg) static void print_error (const qse_char_t* msg)
{ {
qse_printf (QSE_T("Error: %s\n"), msg); qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
} }
static struct static struct
{ {
const qse_char_t* name; const qse_char_t* name;
TestAwk::Option opt; MyAwk::Option opt;
} otab[] = } otab[] =
{ {
{ QSE_T("implicit"), TestAwk::OPT_IMPLICIT }, { QSE_T("implicit"), MyAwk::OPT_IMPLICIT },
{ QSE_T("explicit"), TestAwk::OPT_EXPLICIT }, { QSE_T("explicit"), MyAwk::OPT_EXPLICIT },
{ QSE_T("bxor"), TestAwk::OPT_BXOR }, { QSE_T("bxor"), MyAwk::OPT_BXOR },
{ QSE_T("shift"), TestAwk::OPT_SHIFT }, { QSE_T("shift"), MyAwk::OPT_SHIFT },
{ QSE_T("idiv"), TestAwk::OPT_IDIV }, { QSE_T("idiv"), MyAwk::OPT_IDIV },
{ QSE_T("rio"), TestAwk::OPT_RIO }, { QSE_T("rio"), MyAwk::OPT_RIO },
{ QSE_T("rwpipe"), TestAwk::OPT_RWPIPE }, { QSE_T("rwpipe"), MyAwk::OPT_RWPIPE },
{ QSE_T("newline"), TestAwk::OPT_NEWLINE }, { QSE_T("newline"), MyAwk::OPT_NEWLINE },
{ QSE_T("stripspaces"), TestAwk::OPT_STRIPSPACES }, { QSE_T("stripspaces"), MyAwk::OPT_STRIPSPACES },
{ QSE_T("nextofile"), TestAwk::OPT_NEXTOFILE }, { QSE_T("nextofile"), MyAwk::OPT_NEXTOFILE },
{ QSE_T("crlf"), TestAwk::OPT_CRLF }, { QSE_T("crlf"), MyAwk::OPT_CRLF },
{ QSE_T("reset"), TestAwk::OPT_RESET }, { QSE_T("reset"), MyAwk::OPT_RESET },
{ QSE_T("maptovar"), TestAwk::OPT_MAPTOVAR }, { QSE_T("maptovar"), MyAwk::OPT_MAPTOVAR },
{ QSE_T("pablock"), TestAwk::OPT_PABLOCK } { QSE_T("pablock"), MyAwk::OPT_PABLOCK }
}; };
static void print_usage (const qse_char_t* argv0) static void print_usage (const qse_char_t* argv0)
@ -470,7 +470,8 @@ static void print_usage (const qse_char_t* argv0)
static int awk_main (int argc, qse_char_t* argv[]) static int awk_main (int argc, qse_char_t* argv[])
{ {
TestAwk awk; MyAwk awk;
MyAwk::Run* run;
int mode = 0; int mode = 0;
const qse_char_t* srcin = QSE_T(""); const qse_char_t* srcin = QSE_T("");
@ -480,7 +481,15 @@ static int awk_main (int argc, qse_char_t* argv[])
if (awk.open() <= -1) if (awk.open() <= -1)
{ {
qse_fprintf (stderr, QSE_T("cannot open awk\n")); print_error (awk.getErrorMessage());
return -1;
}
// ARGV[0]
if (awk.addArgument (QSE_T("awk05")) <= -1)
{
print_error (awk.getErrorMessage());
awk.close ();
return -1; return -1;
} }
@ -616,7 +625,8 @@ static int awk_main (int argc, qse_char_t* argv[])
return -1; return -1;
} }
if (awk.parse (srcin, srcout) <= -1) run = awk.parse (srcin, srcout);
if (run == QSE_NULL)
{ {
qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"), qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"),
awk.getErrorLine(), awk.getErrorMessage()); awk.getErrorLine(), awk.getErrorMessage());
@ -635,6 +645,20 @@ static int awk_main (int argc, qse_char_t* argv[])
return -1; return -1;
} }
#if 0
MyAwk::Return args[2];
args[0].setRun (run);
args[1].setRun (run);
if (awk.call (QSE_T("add"), args, 2) <= -1)
{
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
awk.getErrorLine(), awk.getErrorMessage());
awk.close ();
}
#endif
app_awk = QSE_NULL; app_awk = QSE_NULL;
awk.close (); awk.close ();