From 1d88a17c7cfc95905aca52aeaeeabe1760d10cc7 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 9 Jul 2009 07:01:45 +0000 Subject: [PATCH] enhanced Awk classes --- qse/include/qse/awk/Awk.hpp | 42 +++++++------ qse/lib/awk/Awk.cpp | 121 ++++++++++++++++++++++++------------ qse/lib/awk/StdAwk.cpp | 11 +++- qse/samples/awk/awk05.cpp | 84 ++++++++++++++++--------- 4 files changed, 166 insertions(+), 92 deletions(-) diff --git a/qse/include/qse/awk/Awk.hpp b/qse/include/qse/awk/Awk.hpp index f16ef5c8..ce0039ea 100644 --- a/qse/include/qse/awk/Awk.hpp +++ b/qse/include/qse/awk/Awk.hpp @@ -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. @@ -87,7 +87,7 @@ public: * and Source::WRITE respectively when called from * Awk::readSource and Awk::writeSource. * - *
+		 * @code
 		 * int openSource (Source& io)
 		 * {
 		 * 	if (io.getMode() == Source::READ)
@@ -117,7 +117,7 @@ public:
 		 * 	}
 		 * 	return -1;
 		 * }
-		 * 
+ * @endcode * * @return Awk::Source::READ or Awk::Source::WRITE */ @@ -131,7 +131,7 @@ public: * Awk::closeSource to get the value set in Awk::openSource * as shown in the example below. * - *
+		 * @code
 		 * int closeSource (Source& io)
 		 * {
 		 * 	if (io.getMode() == Source::READ)
@@ -146,10 +146,10 @@ public:
 		 * 	}
 		 * 	return -1;
 		 * }
-		 * 
+ * @endcode * * @return an arbitrary value of type void* set with - * Source::setHandle or QSE_NULL + * Source::setHandle() or QSE_NULL */ const void* getHandle () const; @@ -526,7 +526,6 @@ public: }; // end of enum ErrorNumber - // generated by genoptcode.awk /** Defines options */ enum Option @@ -708,23 +707,12 @@ public: */ 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 free (void* ptr); protected: Awk* awk; rtx_t* rtx; - void* data; }; /** Constructor */ @@ -829,9 +817,9 @@ public: * override Awk::openSource, Awk::closeSource, Awk::readSource, * 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. @@ -839,6 +827,15 @@ public: */ virtual int loop (); + /** + * Calls a function + */ + virtual int call ( + const char_t* name, + const Return* args, + size_t nargs + ); + /** * Makes request to abort execution */ @@ -1077,6 +1074,11 @@ protected: xstrs_t runarg; private: + Run runctx; + + int init_runctx (); + void fini_runctx (); + static const char_t* xerrstr (awk_t* a, errnum_t num) throw (); private: diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index 2e5f61e6..f234960c 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -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. @@ -226,8 +226,8 @@ void Awk::Argument::clear () { /* 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 */ + * none of the cases. create a new string so the sttring + * that str.ptr is pointing to doesn't have to be freed */ this->str.ptr = QSE_NULL; 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); } @@ -1062,23 +1062,14 @@ int Awk::Run::getGlobal (int id, Argument& gbl) const 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 () throw (): awk (QSE_NULL), functionMap (QSE_NULL), 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'); @@ -1238,6 +1229,7 @@ int Awk::open () void Awk::close () { + fini_runctx (); clearArguments (); if (functionMap != QSE_NULL) @@ -1337,31 +1329,34 @@ int Awk::unsetAllWords () return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0); } -int Awk::parse () +Awk::Run* Awk::parse () { QSE_ASSERT (awk != QSE_NULL); - qse_awk_sio_t sio; + fini_runctx (); + qse_awk_sio_t sio; sio.in = sourceReader; sio.out = sourceWriter; int n = qse_awk_parse (awk, &sio); - if (n == -1) retrieveError (); - return n; + if (n <= -1) + { + 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_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.file = fileHandler; rio.console = consoleHandler; @@ -1374,29 +1369,75 @@ int Awk::loop () rcb.on_statement = onStatement; rcb.udd = &runctx; } - - int n = 0; + rtx_t* rtx = qse_awk_rtx_open ( awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg.ptr); if (rtx == QSE_NULL) { retrieveError(); - n = -1; + return -1; } - else + + runctx.rtx = rtx; + + rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx); + rxtn->run = &runctx; + + if (runCallback) qse_awk_rtx_setrcb (rtx, &rcb); + return 0; +} + +void Awk::fini_runctx () +{ + if (runctx.rtx != QSE_NULL) { - runctx.rtx = rtx; + qse_awk_rtx_close (runctx.rtx); + runctx.rtx = QSE_NULL; + } +} - rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx); - rxtn->run = &runctx; +int Awk::loop () +{ + QSE_ASSERT (awk != QSE_NULL); + QSE_ASSERT (runctx.rtx != QSE_NULL); - if (runCallback) qse_awk_rtx_setrcb (rtx, &rcb); - n = qse_awk_rtx_loop (rtx); - if (n == -1) retrieveError (rtx); - qse_awk_rtx_close (rtx); + 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; + } + + for (size_t i = 0; i < nargs; i++) ptr[i] = args[i].val; } - return n; + 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 () @@ -1410,8 +1451,6 @@ 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); - pair = qse_map_search (functionMap, name, len); if (pair == QSE_NULL) { @@ -1495,9 +1534,11 @@ void Awk::xstrs_t::clear (awk_t* awk) { if (this->ptr != QSE_NULL) { + while (this->len > 0) + qse_awk_free (awk, this->ptr[--this->len].ptr); + qse_awk_free (awk, this->ptr); this->ptr = QSE_NULL; - this->len = 0; this->capa = 0; } } diff --git a/qse/lib/awk/StdAwk.cpp b/qse/lib/awk/StdAwk.cpp index 3cf9f4eb..5e6638ea 100644 --- a/qse/lib/awk/StdAwk.cpp +++ b/qse/lib/awk/StdAwk.cpp @@ -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. @@ -480,8 +480,10 @@ int StdAwk::open_console_in (Console& io) map = ((qse_awk_val_map_t*)argv)->map; QSE_ASSERT (map != QSE_NULL); + // ok to find ARGV[runarg_index] as ARGV[0] + // has been skipped. ibuflen = qse_awk_longtostr ( - rtx->awk, runarg_index + 1, + rtx->awk, runarg_index, 10, QSE_NULL, ibuf, QSE_COUNTOF(ibuf) ); @@ -622,6 +624,11 @@ int StdAwk::openConsole (Console& io) { runarg_count = 0; runarg_index = 0; + if (runarg.len > 0) + { + // skip ARGV[0] + runarg_index++; + } return open_console_in (io); } else diff --git a/qse/samples/awk/awk05.cpp b/qse/samples/awk/awk05.cpp index 2abec132..c6421646 100644 --- a/qse/samples/awk/awk05.cpp +++ b/qse/samples/awk/awk05.cpp @@ -32,7 +32,7 @@ # include #endif -class TestAwk; +class MyAwk; #ifdef _WIN32 static BOOL WINAPI stop_run (DWORD ctrl_type); #else @@ -42,13 +42,13 @@ static void stop_run (int sig); static void set_intr_run (void); static void unset_intr_run (void); -TestAwk* app_awk = QSE_NULL; +MyAwk* app_awk = QSE_NULL; static bool verbose = false; -class TestAwk: public QSE::StdAwk +class MyAwk: public QSE::StdAwk { public: - TestAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL) + MyAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL) { #ifdef _WIN32 @@ -56,7 +56,7 @@ public: #endif } - ~TestAwk () + ~MyAwk () { close (); } @@ -83,13 +83,13 @@ public: if (idLastSleep <= -1) goto failure; 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, - (FunctionHandler)&TestAwk::sumintarray) <= -1) goto failure; + (FunctionHandler)&MyAwk::sumintarray) <= -1) goto failure; if (addFunction (QSE_T("arrayindices"), 1, 1, - (FunctionHandler)&TestAwk::arrayindices) <= -1) goto failure; + (FunctionHandler)&MyAwk::arrayindices) <= -1) goto failure; return 0; failure: @@ -190,7 +190,7 @@ public: return 0; } - int parse (const char_t* in, const char_t* out) + Run* parse (const char_t* in, const char_t* out) { srcInName = in; srcOutName = out; @@ -199,13 +199,13 @@ public: protected: - bool onRunEnter (Run& run) + bool onLoopEnter (Run& run) { set_intr_run (); return true; } - void onRunExit (Run& run, const Argument& ret) + void onLoopExit (Run& run, const Argument& ret) { unset_intr_run (); @@ -414,29 +414,29 @@ static void unset_intr_run (void) 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 { const qse_char_t* name; - TestAwk::Option opt; + MyAwk::Option opt; } otab[] = { - { QSE_T("implicit"), TestAwk::OPT_IMPLICIT }, - { QSE_T("explicit"), TestAwk::OPT_EXPLICIT }, - { QSE_T("bxor"), TestAwk::OPT_BXOR }, - { QSE_T("shift"), TestAwk::OPT_SHIFT }, - { QSE_T("idiv"), TestAwk::OPT_IDIV }, - { QSE_T("rio"), TestAwk::OPT_RIO }, - { QSE_T("rwpipe"), TestAwk::OPT_RWPIPE }, - { QSE_T("newline"), TestAwk::OPT_NEWLINE }, - { QSE_T("stripspaces"), TestAwk::OPT_STRIPSPACES }, - { QSE_T("nextofile"), TestAwk::OPT_NEXTOFILE }, - { QSE_T("crlf"), TestAwk::OPT_CRLF }, - { QSE_T("reset"), TestAwk::OPT_RESET }, - { QSE_T("maptovar"), TestAwk::OPT_MAPTOVAR }, - { QSE_T("pablock"), TestAwk::OPT_PABLOCK } + { QSE_T("implicit"), MyAwk::OPT_IMPLICIT }, + { QSE_T("explicit"), MyAwk::OPT_EXPLICIT }, + { QSE_T("bxor"), MyAwk::OPT_BXOR }, + { QSE_T("shift"), MyAwk::OPT_SHIFT }, + { QSE_T("idiv"), MyAwk::OPT_IDIV }, + { QSE_T("rio"), MyAwk::OPT_RIO }, + { QSE_T("rwpipe"), MyAwk::OPT_RWPIPE }, + { QSE_T("newline"), MyAwk::OPT_NEWLINE }, + { QSE_T("stripspaces"), MyAwk::OPT_STRIPSPACES }, + { QSE_T("nextofile"), MyAwk::OPT_NEXTOFILE }, + { QSE_T("crlf"), MyAwk::OPT_CRLF }, + { QSE_T("reset"), MyAwk::OPT_RESET }, + { QSE_T("maptovar"), MyAwk::OPT_MAPTOVAR }, + { QSE_T("pablock"), MyAwk::OPT_PABLOCK } }; 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[]) { - TestAwk awk; + MyAwk awk; + MyAwk::Run* run; int mode = 0; 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) { - 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; } @@ -616,7 +625,8 @@ static int awk_main (int argc, qse_char_t* argv[]) 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"), awk.getErrorLine(), awk.getErrorMessage()); @@ -635,6 +645,20 @@ static int awk_main (int argc, qse_char_t* argv[]) 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; awk.close ();