diff --git a/qse/include/qse/awk/Awk.hpp b/qse/include/qse/awk/Awk.hpp index 80eaa143..868a0473 100644 --- a/qse/include/qse/awk/Awk.hpp +++ b/qse/include/qse/awk/Awk.hpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.hpp 230 2009-07-13 08:51:23Z hyunghwan.chung $ + * $Id: Awk.hpp 231 2009-07-13 10:03:53Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -58,6 +58,15 @@ public: class Run; friend class Run; +protected: + class NoSource; + +public: + /** + * The Awk::Source class is an abstract class to encapsulate + * source script I/O. The Awk::parse function requires a concrete + * object instantiated from its child class. + */ class Source { public: @@ -67,6 +76,10 @@ public: WRITE /**< source code write. */ }; + /** + * The Awk::Source::Data class is used to deliver information + * needed for source script I/O. + */ class Data { public: @@ -116,11 +129,27 @@ public: virtual ssize_t read (Data& io, char_t* buf, size_t len) = 0; virtual ssize_t write (Data& io, char_t* buf, size_t len) = 0; + /** + * special value to indicate no source + */ + static NoSource NONE; + private: Source (const Source&); Source& operator= (const Source&); }; +protected: + class NoSource: public Source + { + public: + int open (Data& io) { return -1; } + int close (Data& io) { return 0; } + ssize_t read (Data& io, char_t* buf, size_t len) { return 0; } + ssize_t write (Data& io, char_t* buf, size_t len) { return 0; } + }; + +public: /** * The RIOBase class is a base class to represent runtime I/O context. * The Console, File, Pipe classes inherit this class to implement @@ -861,14 +890,14 @@ public: /** * Parses the source code. * - * Awk::parse parses the source code read from the input stream and - * writes the parse tree to the output stream. A child class should - * override Awk::openSource, Awk::closeSource, Awk::readSource, - * Awk::writeSource to implement the source code stream. + * Awk::parse parses the source code read from the input stream @a in + * and writes the parse tree to the output stream @out. To disable + * deparsing, you may set @a out to Awk::Source::NONE. However, it + * is not legal to specify Awk::Source::NONE for @a in. * - * @return a Run object on success, QSE_NULL on failure + * @return a Run object on success, #QSE_NULL on failure */ - virtual Awk::Run* parse (Source* in, Source* out); + virtual Awk::Run* parse (Source& in, Source& out); /** * Executes the BEGIN block, pattern-action blocks, and the END block. diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index 80adc46d..fbb421b8 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp 230 2009-07-13 08:51:23Z hyunghwan.chung $ + * $Id: Awk.cpp 231 2009-07-13 10:03:53Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -39,6 +39,8 @@ struct rxtn_t Awk::Run* run; }; +Awk::NoSource Awk::Source::NONE; + ////////////////////////////////////////////////////////////////// // Awk::RIO ////////////////////////////////////////////////////////////////// @@ -1275,14 +1277,20 @@ int Awk::unsetAllWords () return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0); } -Awk::Run* Awk::parse (Source* in, Source* out) +Awk::Run* Awk::parse (Source& in, Source& out) { QSE_ASSERT (awk != QSE_NULL); + if (&in == &Source::NONE) + { + setError (ERR_INVAL); + return QSE_NULL; + } + fini_runctx (); - sourceReader = in; - sourceWriter = out; + sourceReader = ∈ + sourceWriter = (&out == &Source::NONE)? QSE_NULL: &out; qse_awk_sio_t sio; sio.in = readSource; diff --git a/qse/samples/awk/awk05.cpp b/qse/samples/awk/awk05.cpp index 3b7c168e..108e3bc8 100644 --- a/qse/samples/awk/awk05.cpp +++ b/qse/samples/awk/awk05.cpp @@ -52,7 +52,7 @@ static int run_awk (QSE::StdAwk& awk) QSE::StdAwk::SourceFile out (QSE_T("awk05.out")); // parse the script string and deparse it to awk05.out. - if (awk.parse (&in, &out) == QSE_NULL) return -1; + if (awk.parse (in, out) == QSE_NULL) return -1; // execute the BEGIN, pattern-action, END blocks. return awk.loop (); diff --git a/qse/samples/awk/awk06.cpp b/qse/samples/awk/awk06.cpp index 079da862..e165d693 100644 --- a/qse/samples/awk/awk06.cpp +++ b/qse/samples/awk/awk06.cpp @@ -43,7 +43,7 @@ static int run_awk (QSE::StdAwk& awk) QSE::StdAwk::SourceFile out (QSE_T("awk06.out")); // parse the script and deparse it to awk06.out - run = awk.parse (&in, &out); + run = awk.parse (in, out); if (run == QSE_NULL) return -1; QSE::StdAwk::Value arg[2]; @@ -52,16 +52,16 @@ static int run_awk (QSE::StdAwk& awk) // ret = add (-20, 51) QSE::StdAwk::Value ret; - if (awk.call (QSE_T("add"), &ret, arg, 2) <= -1) return -1; + if (awk.call (QSE_T("add"), &ret, arg, QSE_COUNTOF(arg)) <= -1) return -1; // ret = mul (ret, 51); arg[0] = ret; - if (awk.call (QSE_T("mul"), &ret, arg, 2) <= -1) return -1; + if (awk.call (QSE_T("mul"), &ret, arg, QSE_COUNTOF(arg)) <= -1) return -1; // ret = div (ret, 2); arg[0] = ret; if (arg[1].setReal (run, 2) <= -1) return -1; - if (awk.call (QSE_T("div"), &ret, arg, 2) <= -1) return -1; + if (awk.call (QSE_T("div"), &ret, arg, QSE_COUNTOF(arg)) <= -1) return -1; // output the result in various types qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)ret.toInt()); diff --git a/qse/samples/awk/awk07.cpp b/qse/samples/awk/awk07.cpp index dd18e554..d33c53d1 100644 --- a/qse/samples/awk/awk07.cpp +++ b/qse/samples/awk/awk07.cpp @@ -33,7 +33,7 @@ static int run_awk (QSE::StdAwk& awk) { QSE::StdAwk::Run* run; - const qse_char_t* script = QSE_T( + QSE::StdAwk::SourceString in (QSE_T( "function pa (x) {\n" " reset ret;\n" " for (i in x) { print i, \"=>\", x[i]; ret += x[i]; }\n" @@ -44,15 +44,13 @@ static int run_awk (QSE::StdAwk& awk) " for (i in x) { ret[-i] = -x[i]; }\n" " return ret;\n" "}" - ); + )); - QSE::StdAwk::SourceString in (script); - QSE::StdAwk::SourceFile out (QSE_T("awk07.out")); - - // parse the script and deparse it to awk07.out - run = awk.parse (&in, &out); + // parse the script and perform no deparsing + run = awk.parse (in, QSE::StdAwk::Source::NONE); if (run == QSE_NULL) return -1; + // prepare an indexed parameter QSE::StdAwk::Value arg[1]; for (int i = 1; i <= 5; i++)