diff --git a/ase/awk/Awk.cpp b/ase/awk/Awk.cpp index 6df16c10..68b229a4 100644 --- a/ase/awk/Awk.cpp +++ b/ase/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp,v 1.23 2007/05/12 17:05:07 bacon Exp $ + * $Id: Awk.cpp,v 1.27 2007/05/13 14:57:43 bacon Exp $ */ #include @@ -29,50 +29,82 @@ namespace ASE this->handle = handle; } - Awk::Extio::Extio (const char_t* name): name(name), handle(ASE_NULL) + Awk::Extio::Extio (ase_awk_extio_t* extio): extio (extio) { } const Awk::char_t* Awk::Extio::getName () const { - return this->name; + return extio->name; } const void* Awk::Extio::getHandle () const { - return this->handle; + return extio->handle; } void Awk::Extio::setHandle (void* handle) { - this->handle = handle; + extio->handle = handle; } - Awk::Pipe::Pipe (char_t* name, Mode mode): Extio(name), mode(mode) + ase_awk_run_t* Awk::Extio::getRun () const + { + return extio->run; + } + + ase_awk_t* Awk::Extio::getAwk () const + { + return ase_awk_getrunawk(extio->run); + } + + Awk::Pipe::Pipe (ase_awk_extio_t* extio): Extio(extio) { } - Awk::File::File (char_t* name, Mode mode): Extio(name), mode(mode) + Awk::File::File (ase_awk_extio_t* extio): Extio(extio) { } - Awk::Console::Console (char_t* name, Mode mode): Extio(name), mode(mode) + Awk::Console::Console (ase_awk_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::Pipe::Mode Awk::Pipe::getMode () const { - return this->mode; + return (Mode)extio->mode; } Awk::File::Mode Awk::File::getMode () const { - return this->mode; + return (Mode)extio->mode; } Awk::Console::Mode Awk::Console::getMode () const { - return this->mode; + return (Mode)extio->mode; } Awk::Argument::Argument (): run (ASE_NULL), val (ASE_NULL) @@ -308,11 +340,13 @@ namespace ASE return ase_awk_parse (awk, &srcios); } - int Awk::run (const char_t* main, const char_t** args) + 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_runarg_t* runarg = ASE_NULL; runios.pipe = pipeHandler; runios.coproc = ASE_NULL; @@ -320,8 +354,53 @@ namespace ASE runios.console = consoleHandler; runios.custom_data = this; - return ase_awk_run ( - awk, main, &runios, ASE_NULL, ASE_NULL, this); + if (nargs > 0) + { + runarg = (ase_awk_runarg_t*) ase_awk_malloc ( + awk, ASE_SIZEOF(ase_awk_runarg_t)*(nargs+1)); + + if (runarg == ASE_NULL) + { + // TODO: SET ERROR INFO + 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) + { + if (i > 0) + { + for (i-- ; i > 0; i--) + { + ase_awk_free (awk, runarg[i].ptr); + } + } + + // TODO: SET ERROR INFO + return -1; + } + } + + runarg[i].ptr = ASE_NULL; + runarg[i].len = 0; + } + + int n = ase_awk_run ( + awk, main, &runios, ASE_NULL, runarg, this); + + if (runarg != ASE_NULL) + { + for (i--; i > 0; i--) + { + ase_awk_free (awk, runarg[i].ptr); + } + ase_awk_free (awk, runarg); + } + + return n; } int Awk::open () @@ -549,32 +628,23 @@ namespace ASE ASE_ASSERT ((epa->type & 0xFF) == ASE_AWK_EXTIO_PIPE); - Pipe pipe (epa->name, (Pipe::Mode)epa->mode); - ssize_t n; + Pipe pipe (epa); switch (cmd) { case ASE_AWK_IO_OPEN: - n = awk->openPipe (pipe); - if (n >= 0) epa->handle = (void*)pipe.getHandle(); - return n; - + return awk->openPipe (pipe); case ASE_AWK_IO_CLOSE: - pipe.setHandle (epa->handle); return awk->closePipe (pipe); case ASE_AWK_IO_READ: - pipe.setHandle (epa->handle); return awk->readPipe (pipe, data, count); case ASE_AWK_IO_WRITE: - pipe.setHandle (epa->handle); return awk->writePipe (pipe, data, count); case ASE_AWK_IO_FLUSH: - pipe.setHandle (epa->handle); return awk->flushPipe (pipe); case ASE_AWK_IO_NEXT: - pipe.setHandle (epa->handle); return awk->nextPipe (pipe); } @@ -589,32 +659,23 @@ namespace ASE ASE_ASSERT ((epa->type & 0xFF) == ASE_AWK_EXTIO_FILE); - File file (epa->name, (File::Mode)epa->mode); - ssize_t n; + File file (epa); switch (cmd) { case ASE_AWK_IO_OPEN: - n = awk->openFile (file); - if (n >= 0) epa->handle = (void*)file.getHandle(); - return n; - + return awk->openFile (file); case ASE_AWK_IO_CLOSE: - file.setHandle (epa->handle); return awk->closeFile (file); case ASE_AWK_IO_READ: - file.setHandle (epa->handle); return awk->readFile (file, data, count); case ASE_AWK_IO_WRITE: - file.setHandle (epa->handle); return awk->writeFile (file, data, count); case ASE_AWK_IO_FLUSH: - file.setHandle (epa->handle); return awk->flushFile (file); case ASE_AWK_IO_NEXT: - file.setHandle (epa->handle); return awk->nextFile (file); } @@ -629,32 +690,23 @@ namespace ASE ASE_ASSERT ((epa->type & 0xFF) == ASE_AWK_EXTIO_CONSOLE); - Console console (epa->name, (Console::Mode)epa->mode); - ssize_t n; + Console console (epa); switch (cmd) { case ASE_AWK_IO_OPEN: - n = awk->openConsole (console); - if (n >= 0) epa->handle = (void*)console.getHandle(); - return n; - + return awk->openConsole (console); case ASE_AWK_IO_CLOSE: - console.setHandle (epa->handle); return awk->closeConsole (console); case ASE_AWK_IO_READ: - console.setHandle (epa->handle); return awk->readConsole (console, data, count); case ASE_AWK_IO_WRITE: - console.setHandle (epa->handle); return awk->writeConsole (console, data, count); case ASE_AWK_IO_FLUSH: - console.setHandle (epa->handle); return awk->flushConsole (console); case ASE_AWK_IO_NEXT: - console.setHandle (epa->handle); return awk->nextConsole (console); } diff --git a/ase/awk/Awk.hpp b/ase/awk/Awk.hpp index 1ec7e41f..8c66d690 100644 --- a/ase/awk/Awk.hpp +++ b/ase/awk/Awk.hpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.hpp,v 1.22 2007/05/12 03:53:32 bacon Exp $ + * $Id: Awk.hpp,v 1.25 2007/05/13 14:43:58 bacon Exp $ */ #ifndef _ASE_AWK_AWK_HPP_ @@ -46,15 +46,17 @@ namespace ASE class Extio { public: - Extio (const char_t* name); + Extio (ase_awk_extio_t* extio); const char_t* getName() const; const void* getHandle () const; void setHandle (void* handle); - private: - const char_t* name; - void* handle; + ase_awk_run_t* getRun () const; + ase_awk_t* getAwk () const; + + protected: + ase_awk_extio_t* extio; }; class Pipe: public Extio @@ -66,12 +68,8 @@ namespace ASE WRITE = ASE_AWK_EXTIO_PIPE_WRITE }; - Pipe (char_t* name, Mode mode); - + Pipe (ase_awk_extio_t* extio); Mode getMode () const; - - private: - Mode mode; }; class File: public Extio @@ -84,12 +82,8 @@ namespace ASE APPEND = ASE_AWK_EXTIO_FILE_APPEND }; - File (char_t* name, Mode mode); - + File (ase_awk_extio_t* extio); Mode getMode () const; - - private: - Mode mode; }; class Console: public Extio @@ -101,12 +95,14 @@ namespace ASE WRITE = ASE_AWK_EXTIO_CONSOLE_WRITE }; - Console (char_t* name, Mode mode); + Console (ase_awk_extio_t* extio); + ~Console (); Mode getMode () const; + int setFileName (const char_t* name); private: - Mode mode; + char_t* filename; }; class Argument @@ -190,7 +186,7 @@ namespace ASE virtual int parse (); virtual int run (const char_t* main = ASE_NULL, - const char_t** args = ASE_NULL); + const char_t** args = ASE_NULL, size_t nargs = 0); typedef int (Awk::*FunctionHandler) ( Return* ret, const Argument* args, size_t nargs); diff --git a/ase/awk/StdAwk.cpp b/ase/awk/StdAwk.cpp index e6bbcb1e..0c905b90 100644 --- a/ase/awk/StdAwk.cpp +++ b/ase/awk/StdAwk.cpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.cpp,v 1.11 2007/05/11 17:21:01 bacon Exp $ + * $Id: StdAwk.cpp,v 1.12 2007/05/13 10:49:32 bacon Exp $ */ #include @@ -39,8 +39,8 @@ namespace ASE ASE_AWK_BLOCKLESS | ASE_AWK_STRBASEONE | ASE_AWK_STRIPSPACES | - ASE_AWK_NEXTOFILE /*| - ASE_AWK_ARGSTOMAIN*/; + ASE_AWK_NEXTOFILE | + ASE_AWK_ARGSTOMAIN; ase_awk_setoption (awk, opt); diff --git a/ase/awk/aseawk++.dsp b/ase/awk/aseawk++.dsp index a0f6dfeb..8b7cd8ae 100644 --- a/ase/awk/aseawk++.dsp +++ b/ase/awk/aseawk++.dsp @@ -38,7 +38,7 @@ RSC=rc.exe # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "../release/lib" -# PROP Intermediate_Dir "release" +# PROP Intermediate_Dir "release/cpp" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" MTL=midl.exe @@ -66,7 +66,7 @@ LIB32=link.exe -lib # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "../debug/lib" -# PROP Intermediate_Dir "debug" +# PROP Intermediate_Dir "debug/cpp" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" MTL=midl.exe diff --git a/ase/awk/parse.c b/ase/awk/parse.c index 88d1b2cf..9c1fff8f 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.4 2007/05/05 16:32:46 bacon Exp $ + * $Id: parse.c,v 1.5 2007/05/13 14:43:58 bacon Exp $ * * {License} */ @@ -3650,12 +3650,12 @@ static ase_awk_nde_t* parse_nextfile (ase_awk_t* awk, ase_size_t line, int out) { ase_awk_nde_nextfile_t* nde; - if (awk->parse.id.block == PARSE_BEGIN_BLOCK) + if (!out && awk->parse.id.block == PARSE_BEGIN_BLOCK) { SETERRLIN (awk, ASE_AWK_ENEXTFBEG, line); return ASE_NULL; } - if (awk->parse.id.block == PARSE_END_BLOCK) + if (!out && awk->parse.id.block == PARSE_END_BLOCK) { SETERRLIN (awk, ASE_AWK_ENEXTFEND, line); return ASE_NULL; diff --git a/ase/awk/run.c b/ase/awk/run.c index 877c1bcf..4979121b 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.4 2007/05/05 16:32:46 bacon Exp $ + * $Id: run.c,v 1.5 2007/05/13 14:43:58 bacon Exp $ * * {License} */ @@ -2235,6 +2235,8 @@ static int __run_nextoutfile (ase_awk_run_t* run, ase_awk_nde_nextfile_t* nde) { int n; + /* nextofile can be called from BEGIN and END block unlike nextfile */ + n = ase_awk_nextextio_write (run, ASE_AWK_OUT_CONSOLE, ASE_T("")); if (n == -1) { @@ -2245,8 +2247,9 @@ static int __run_nextoutfile (ase_awk_run_t* run, ase_awk_nde_nextfile_t* nde) if (n == 0) { - /* TODO: should it terminate the program - * when there is no more output console? */ + /* should it terminate the program there is no more + * output console? no. there will just be no more console + * output */ /*run->exit_level = EXIT_GLOBAL;*/ return 0; } diff --git a/ase/awk/tree.c b/ase/awk/tree.c index 5f56b3ef..4e68ee6d 100644 --- a/ase/awk/tree.c +++ b/ase/awk/tree.c @@ -1,5 +1,5 @@ /* - * $Id: tree.c,v 1.3 2007/04/30 05:47:33 bacon Exp $ + * $Id: tree.c,v 1.4 2007/05/13 14:43:58 bacon Exp $ * * {License} */ @@ -817,7 +817,10 @@ static int print_statements (ase_awk_t* awk, ase_awk_nde_t* tree, int depth) case ASE_AWK_NDE_NEXTFILE: { PRINT_TABS (awk, depth); - PUT_SRCSTR (awk, ASE_T("nextfile;")); + if (((ase_awk_nde_nextfile_t*)p)->out) + PUT_SRCSTR (awk, ASE_T("nextofile;")); + else + PUT_SRCSTR (awk, ASE_T("nextfile;")); PUT_NEWLINE (awk); break; } diff --git a/ase/change.log b/ase/change.log new file mode 100644 index 00000000..e6ee034b --- /dev/null +++ b/ase/change.log @@ -0,0 +1,13 @@ +[0.2.0] + +* fixed bug (nextofile shown as nextfile in source output) +* fixed bug (nextofile not allowed in the BEGIN and END block) +* fixed bug (ASE_MALLOC/ASE_FREE defined wrongly causing test programs + to crash in the debug mode when compiled with MSVC/C++. + +* added awk c++ classes (awk/Awk.hpp awk/Awk.cpp awk/StdAwk.hpp awk/StdAwk.cpp) +* added c++ test program (test/awk/Awk.cpp) + +[0.1.0] + +* initial release diff --git a/ase/lsp/lsp_i.h b/ase/lsp/lsp_i.h index 031fdfb2..79ebc476 100644 --- a/ase/lsp/lsp_i.h +++ b/ase/lsp/lsp_i.h @@ -1,5 +1,5 @@ /* - * $Id: lsp_i.h,v 1.3 2007/04/30 06:09:46 bacon Exp $ + * $Id: lsp_i.h,v 1.4 2007/05/13 15:45:14 bacon Exp $ * * {License} */ @@ -22,18 +22,9 @@ #pragma warning (disable: 4996) #endif -#if defined(_WIN32) && defined(_MSC_VER) && defined(_DEBUG) - #define _CRTDBG_MAP_ALLOC - #include - - #define ASE_LSP_MALLOC(lsp,size) malloc (size) - #define ASE_LSP_REALLOC(lsp,ptr,size) realloc (ptr, size) - #define ASE_LSP_FREE(lsp,ptr) free (ptr) -#else - #define ASE_LSP_MALLOC(lsp,size) ASE_MALLOC(&(lsp)->prmfns.mmgr,size) - #define ASE_LSP_REALLOC(lsp,ptr,size) ASE_REALLOC(&(lsp)->prmfns.mmgr,ptr,size) - #define ASE_LSP_FREE(lsp,ptr) ASE_FREE(&(lsp)->prmfns.mmgr,ptr) -#endif +#define ASE_LSP_MALLOC(lsp,size) ASE_MALLOC(&(lsp)->prmfns.mmgr,size) +#define ASE_LSP_REALLOC(lsp,ptr,size) ASE_REALLOC(&(lsp)->prmfns.mmgr,ptr,size) +#define ASE_LSP_FREE(lsp,ptr) ASE_FREE(&(lsp)->prmfns.mmgr,ptr) #define ASE_LSP_ISUPPER(lsp,c) ASE_ISUPPER(&(lsp)->prmfns.ccls,c) #define ASE_LSP_ISLOWER(lsp,c) ASE_ISLOWER(&(lsp)->prmfns.ccls,c) diff --git a/ase/test/awk/Awk.cpp b/ase/test/awk/Awk.cpp index a1348ca7..af3f6d27 100644 --- a/ase/test/awk/Awk.cpp +++ b/ase/test/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp,v 1.9 2007/05/13 07:05:46 bacon Exp $ + * $Id: Awk.cpp,v 1.11 2007/05/13 14:43:58 bacon Exp $ */ #include @@ -19,58 +19,92 @@ class TestAwk: public ASE::StdAwk { public: + TestAwk (): srcInName(ASE_NULL), srcOutName(ASE_NULL), + numConInFiles(0), numConOutFiles(0) + { + } + ~TestAwk () { close (); } - int parse (const char_t* name) + int addConsoleInput (const char_t* file) { - ase_strxcpy (sourceInName, ASE_COUNTOF(sourceInName), name); - return StdAwk::parse (); - } - -protected: - int openSource (Source& io) - { - Source::Mode mode = io.getMode(); - - if (mode == Source::READ) - { - FILE* fp = ase_fopen (sourceInName, ASE_T("r")); - if (fp == ASE_NULL) return -1; - io.setHandle (fp); - return 1; - } - else if (mode == Source::WRITE) + if (numConInFiles < ASE_COUNTOF(conInFile)) { + conInFile[numConInFiles++] = file; return 0; } return -1; } + int addConsoleOutput (const char_t* file) + { + if (numConOutFiles < ASE_COUNTOF(conOutFile)) + { + conOutFile[numConOutFiles++] = file; + return 0; + } + + return -1; + } + + int parse (const char_t* in, const char_t* out) + { + srcInName = in; + srcOutName = out; + return StdAwk::parse (); + } + +protected: + + int openSource (Source& io) + { + Source::Mode mode = io.getMode(); + FILE* fp = ASE_NULL; + + if (mode == Source::READ) + { + if (srcInName == ASE_NULL) + { + io.setHandle (stdin); + return 0; + } + + if (srcInName[0] == ASE_T('\0')) fp = stdin; + else fp = ase_fopen (srcInName, ASE_T("r")); + } + else if (mode == Source::WRITE) + { + if (srcOutName == ASE_NULL) + { + io.setHandle (stdout); + return 0; + } + + if (srcOutName[0] == ASE_T('\0')) fp = stdout; + else fp = ase_fopen (srcOutName, ASE_T("w")); + } + + if (fp == ASE_NULL) return -1; + io.setHandle (fp); + return 1; + } + int closeSource (Source& io) { Source::Mode mode = io.getMode(); - - if (mode == Source::READ) - { - fclose ((FILE*)io.getHandle()); - io.setHandle (ASE_NULL); - return 0; - } - else if (mode == Source::WRITE) - { - return 0; - } - - return -1; + FILE* fp = (FILE*)io.getHandle(); + if (fp != stdin && fp != stdout && fp != stderr) fclose (fp); + io.setHandle (ASE_NULL); + return 0; } - ssize_t readSource (Source& io, char_t* buf, size_t count) + ssize_t readSource (Source& io, char_t* buf, size_t len) { - if (count <= 0) return -1; + if (len <= 0) return -1; // TOOD: read more characters... cint_t c = ase_fgetc ((FILE*)io.getHandle()); @@ -79,14 +113,31 @@ protected: return 1; } - ssize_t writeSource (Source& io, char_t* buf, size_t count) + ssize_t writeSource (Source& io, char_t* buf, size_t len) { - return 0; + FILE* fp = (FILE*)io.getHandle(); + size_t left = len; + + while (left > 0) + { + if (*buf == ASE_T('\0')) + { + if (ase_fputc (*buf, fp) == ASE_CHAR_EOF) return -1; + left -= 1; buf += 1; + } + else + { + int n = ase_fprintf (fp, ASE_T("%.*s"), left, buf); + if (n < 0) return -1; + left -= n; buf += n; + } + } + + return len; } - // pipe io handlers - int openPipe (Pipe& io) + int openPipe (Pipe& io) { Awk::Pipe::Mode mode = io.getMode(); FILE* fp = NULL; @@ -134,7 +185,14 @@ protected: { if (*buf == ASE_T('\0')) { - if (ase_fputc (*buf, fp) == ASE_CHAR_EOF) return -1; + #if defined(ASE_CHAR_IS_WCHAR) && defined(__linux) + if (fputc ('\0', fp) == EOF) + #else + if (ase_fputc (*buf, fp) == ASE_CHAR_EOF) + #endif + { + return -1; + } left -= 1; buf += 1; } else @@ -144,14 +202,21 @@ protected: * pointer opened by popen, as of this writing. * anyway, hopefully the following replacement * will work all the way. */ - int n = fprintf ( - (FILE*)epa->handle, "%.*ls", left, buf); + int n = fprintf (fp, "%.*ls", left, buf); + if (n >= 0) + { + size_t x; + for (x = 0; x < left; x++) + { + if (buf[x] == ASE_T('\0')) break; + } + n = x; + } #else - int n = ase_fprintf ( - (FILE*)epa->handle, ASE_T("%.*s"), left, buf); + int n = ase_fprintf (fp, ASE_T("%.*s"), left, buf); #endif - if (n < 0) return -1; + if (n < 0 || n > left) return -1; left -= n; buf += n; } } @@ -220,7 +285,7 @@ protected: else { int n = ase_fprintf (fp, ASE_T("%.*s"), left, buf); - if (n < 0) return -1; + if (n < 0 || n > left) return -1; left -= n; buf += n; } } @@ -232,12 +297,75 @@ protected: int nextFile (File& io) { return -1; } // console io handlers - int openConsole (Console& io) { return 1; } - int closeConsole (Console& io) { return 0; } + int openConsole (Console& io) + { + Awk::Console::Mode mode = io.getMode(); + FILE* fp = ASE_NULL; + const char_t* fn = ASE_NULL; - ssize_t readConsole (Console& io, char_t* buf, size_t len) + switch (mode) + { + case Awk::Console::READ: + if (numConInFiles == 0) fp = stdin; + else + { + fn = conInFile[0]; + fp = ase_fopen (fn, ASE_T("r")); + } + break; + + case Awk::Console::WRITE: + if (numConOutFiles == 0) fp = stdout; + else + { + fn = conOutFile[0]; + fp = ase_fopen (fn, ASE_T("w")); + } + break; + } + + if (fp == NULL) return -1; + + ConTrack* t = (ConTrack*) ase_awk_malloc (awk, ASE_SIZEOF(ConTrack)); + if (t == ASE_NULL) + { + if (fp != stdin && fp != stdout) fclose (fp); + return -1; + } + + t->handle = fp; + t->nextConIdx = 1; + + if (fn != ASE_NULL) + { + if (io.setFileName (fn) == -1) + { + if (fp != stdin && fp != stdout) fclose (fp); + ase_awk_free (awk, t); + return -1; + } + } + + io.setHandle (t); + return 1; + } + + int closeConsole (Console& io) + { + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + + if (fp != stdin && fp != stdout && fp != stderr) fclose (fp); + + ase_awk_free (awk, t); + return 0; + } + + ssize_t readConsole (Console& io, char_t* buf, size_t len) { - FILE* fp = stdin; + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + if (ase_fgets (buf, len, fp) == ASE_NULL) { if (ferror(fp)) return -1; @@ -249,7 +377,8 @@ protected: ssize_t writeConsole (Console& io, char_t* buf, size_t len) { - FILE* fp = stdout; + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; size_t left = len; while (left > 0) @@ -270,11 +399,58 @@ protected: return len; } - int flushConsole (Console& io) { return ::fflush (stdout); } - int nextConsole (Console& io) { return 0; } + int flushConsole (Console& io) + { + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + return ::fflush (fp); + } + + int nextConsole (Console& io) + { + Awk::Console::Mode mode = io.getMode(); + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* ofp = t->handle; + FILE* nfp = ASE_NULL; + const char_t* fn = ASE_NULL; + + switch (mode) + { + case Awk::Console::READ: + if (t->nextConIdx >= numConInFiles) return 0; + fn = conInFile[t->nextConIdx]; + nfp = ase_fopen (fn, ASE_T("r")); + break; + + case Awk::Console::WRITE: + if (t->nextConIdx >= numConOutFiles) return 0; + fn = conOutFile[t->nextConIdx]; + nfp = ase_fopen (fn, ASE_T("w")); + break; + } + + if (nfp == ASE_NULL) return -1; + + if (fn != ASE_NULL) + { + if (io.setFileName (fn) == -1) + { + fclose (nfp); + return -1; + } + } + + fclose (ofp); + + t->nextConIdx++; + t->handle = nfp; + + return 1; + } + // primitive operations - void* allocMem (size_t n) { return ::malloc (n); } + void* allocMem (size_t n) { return ::malloc (n); } void* reallocMem (void* ptr, size_t n) { return ::realloc (ptr, n); } void freeMem (void* ptr) { ::free (ptr); } @@ -308,7 +484,20 @@ protected: } private: - char_t sourceInName[1024+1]; + const char_t* srcInName; + const char_t* srcOutName; + + struct ConTrack + { + FILE* handle; + size_t nextConIdx; + }; + + size_t numConInFiles; + const char_t* conInFile[128]; + + size_t numConOutFiles; + const char_t* conOutFile[128]; }; #ifndef NDEBUG @@ -344,9 +533,126 @@ void ase_assert_printf (const ase_char_t* fmt, ...) } #endif +static void print_error (const ase_char_t* msg) +{ + ase_printf (ASE_T("Error: %s\n"), msg); +} + +static void print_usage (const ase_char_t* argv0) +{ + ase_printf (ASE_T("Usage: %s [-m main-function] [-si source-in-file] [-so source-out-file] [-ci console-in-file]* [-co console-out-file]* [-a argument]*\n"), argv0); +} + int awk_main (int argc, ase_char_t* argv[]) { TestAwk awk; + int mode = 0; + const ase_char_t* mainfn = NULL; + const ase_char_t* srcin = ASE_T(""); + const ase_char_t* srcout = NULL; + const ase_char_t* args[256]; + ase_size_t nargs = 0; + ase_size_t nsrcins = 0; + ase_size_t nsrcouts = 0; + + for (int i = 1; i < argc; i++) + { + if (mode == 0) + { + if (ase_strcmp(argv[i], ASE_T("-si")) == 0) mode = 1; + else if (ase_strcmp(argv[i], ASE_T("-so")) == 0) mode = 2; + else if (ase_strcmp(argv[i], ASE_T("-ci")) == 0) mode = 3; + else if (ase_strcmp(argv[i], ASE_T("-co")) == 0) mode = 4; + else if (ase_strcmp(argv[i], ASE_T("-a")) == 0) mode = 5; + else if (ase_strcmp(argv[i], ASE_T("-m")) == 0) mode = 6; + else + { + print_usage (argv[0]); + return -1; + } + } + else + { + if (argv[i][0] == ASE_T('-')) + { + print_usage (argv[0]); + return -1; + } + + if (mode == 1) // source input + { + if (nsrcins != 0) + { + print_usage (argv[0]); + return -1; + } + + srcin = argv[i]; + nsrcins++; + mode = 0; + } + else if (mode == 2) // source output + { + if (nsrcouts != 0) + { + print_usage (argv[0]); + return -1; + } + + srcout = argv[i]; + nsrcouts++; + mode = 0; + } + else if (mode == 3) // console input + { + if (awk.addConsoleInput (argv[i]) == -1) + { + print_error (ASE_T("too many console inputs")); + return -1; + } + + mode = 0; + } + else if (mode == 4) // console output + { + if (awk.addConsoleOutput (argv[i]) == -1) + { + print_error (ASE_T("too many console outputs")); + return -1; + } + + mode = 0; + } + else if (mode == 5) // argument mode + { + if (nargs >= ASE_COUNTOF(args)) + { + print_usage (argv[0]); + return -1; + } + + args[nargs++] = argv[i]; + mode = 0; + } + else if (mode == 6) + { + if (mainfn != NULL) + { + print_usage (argv[0]); + return -1; + } + + mainfn = argv[i]; + mode = 0; + } + } + } + + if (mode != 0) + { + print_usage (argv[0]); + return -1; + } if (awk.open() == -1) { @@ -354,13 +660,13 @@ int awk_main (int argc, ase_char_t* argv[]) return -1; } - if (awk.parse(ASE_T("t.awk")) == -1) + if (awk.parse (srcin, srcout) == -1) { ase_fprintf (stderr, ASE_T("cannot parse\n")); return -1; } - if (awk.run () == -1) + if (awk.run (mainfn, args, nargs) == -1) { ase_fprintf (stderr, ASE_T("cannot run\n")); return -1; diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index 91ea070b..12cc0d78 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.4 2007/05/12 17:05:07 bacon Exp $ + * $Id: awk.c,v 1.6 2007/05/13 14:57:43 bacon Exp $ */ #include @@ -323,18 +323,48 @@ static ase_ssize_t awk_extio_pipe ( case ASE_AWK_IO_WRITE: { - #if defined(ASE_CHAR_IS_WCHAR) && defined(__linux) - /* fwprintf seems to return an error with the file - * pointer opened by popen, as of this writing. - * anyway, hopefully the following replacement - * will work all the way. */ - int n = fprintf ( - (FILE*)epa->handle, "%.*ls", size, data); - #else - int n = ase_fprintf ( - (FILE*)epa->handle, ASE_T("%.*s"), size, data); - #endif - if (n < 0) return -1; + FILE* fp = (FILE*)epa->handle; + size_t left = size; + + while (left > 0) + { + if (*data == ASE_T('\0')) + { + #if defined(ASE_CHAR_IS_WCHAR) && defined(__linux) + if (fputc ('\0', fp) == EOF) + #else + if (ase_fputc (*data, fp) == ASE_CHAR_EOF) + #endif + { + return -1; + } + left -= 1; data += 1; + } + else + { + #if defined(ASE_CHAR_IS_WCHAR) && defined(__linux) + /* fwprintf seems to return an error with the file + * pointer opened by popen, as of this writing. + * anyway, hopefully the following replacement + * will work all the way. */ + int n = fprintf (fp, "%.*ls", left, data); + if (n >= 0) + { + size_t x; + for (x = 0; x < left; x++) + { + if (data[x] == ASE_T('\0')) break; + } + n = x; + } + #else + int n = ase_fprintf (fp, ASE_T("%.*s"), left, data); + #endif + + if (n < 0 || n > left) return -1; + left -= n; data += n; + } + } return size; } @@ -342,7 +372,7 @@ static ase_ssize_t awk_extio_pipe ( case ASE_AWK_IO_FLUSH: { if (epa->mode == ASE_AWK_EXTIO_PIPE_READ) return -1; - else return 0; + return fflush ((FILE*)epa->handle); } case ASE_AWK_IO_NEXT: @@ -413,7 +443,7 @@ static ase_ssize_t awk_extio_file ( case ASE_AWK_IO_WRITE: { FILE* fp = (FILE*)epa->handle; - ssize_t left = size; + ase_ssize_t left = size; while (left > 0) {