diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 2dd46b0c..63eca514 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c 217 2009-06-28 13:41:47Z hyunghwan.chung $ + * $Id: awk.c 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -754,7 +754,7 @@ static int awk_main (int argc, qse_char_t* argv[]) rcb.on_loop_enter = on_loop_enter; rcb.on_loop_exit = on_loop_exit; rcb.on_statement = on_statement; - rcb.data = &arg; + rcb.udd = &arg; rtx = qse_awk_rtx_openstd (awk, 0, QSE_T("qseawk"), arg.icf, QSE_NULL); if (rtx == QSE_NULL) diff --git a/qse/doc/Doxyfile.in b/qse/doc/Doxyfile.in index 7b90f817..caf94329 100644 --- a/qse/doc/Doxyfile.in +++ b/qse/doc/Doxyfile.in @@ -621,7 +621,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = ../test +EXAMPLE_PATH = ../samples ../cmd # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/qse/include/qse/awk/Awk.hpp b/qse/include/qse/awk/Awk.hpp index c6d2b663..63ea4db7 100644 --- a/qse/include/qse/awk/Awk.hpp +++ b/qse/include/qse/awk/Awk.hpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.hpp 213 2009-06-26 13:05:19Z hyunghwan.chung $ + * $Id: Awk.hpp 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -405,17 +405,9 @@ public: ERR_NOMEM = QSE_AWK_ENOMEM, ERR_NOSUP = QSE_AWK_ENOSUP, ERR_NOPER = QSE_AWK_ENOPER, - ERR_NODEV = QSE_AWK_ENODEV, - ERR_NOSPC = QSE_AWK_ENOSPC, - ERR_MFILE = QSE_AWK_EMFILE, - ERR_MLINK = QSE_AWK_EMLINK, - ERR_AGAIN = QSE_AWK_EAGAIN, ERR_NOENT = QSE_AWK_ENOENT, ERR_EXIST = QSE_AWK_EEXIST, - ERR_FTBIG = QSE_AWK_EFTBIG, - ERR_TBUSY = QSE_AWK_ETBUSY, - ERR_ISDIR = QSE_AWK_EISDIR, - ERR_IOERR = QSE_AWK_RIOERR, + ERR_IOERR = QSE_AWK_EIOERR, ERR_OPEN = QSE_AWK_EOPEN, ERR_READ = QSE_AWK_EREAD, ERR_WRITE = QSE_AWK_EWRITE, @@ -487,7 +479,7 @@ public: ERR_POSIDX = QSE_AWK_EPOSIDX, ERR_ARGTF = QSE_AWK_EARGTF, ERR_ARGTM = QSE_AWK_EARGTM, - ERR_FUNNONE = QSE_AWK_EFUNNONE, + ERR_FUNNF = QSE_AWK_EFUNNF, ERR_NOTIDX = QSE_AWK_ENOTIDX, ERR_NOTDEL = QSE_AWK_ENOTDEL, ERR_NOTMAP = QSE_AWK_ENOTMAP, @@ -835,39 +827,38 @@ public: * override Awk::openSource, Awk::closeSource, Awk::readSource, * Awk::writeSource to implement the source code stream. * - * @return - * On success, 0 is returned. On failure, -1 is returned and - * extended error information is set. Call Awk::getErrorNumber - * to get it. + * @return 0 on success, -1 on failure */ virtual int parse (); /** - * Executes the parse tree. - * - * This method executes the parse tree formed by Awk::parse. - * - * @param args Pointer to an array of character strings. - * If it is specified, the charater strings are passed to - * an AWK program. The values can be accesed with ARGC & ARGV - * inside the AWK program. - * @param nargs Number of character strings in the array - * - * @return - * On success, 0 is returned. On failure, -1 is returned if - * the run-time callback is not enabled. If the run-time callback - * is enabled, 0 is returned and the error is indicated through - * Awk::onRunEnd. The run-time callback is enabled and disbaled - * with Awk::enableRunCallback and Awk::disableRunCallback. - * Call Awk::getErrorNumber to get extended error information. + * Executes the BEGIN block, pattern-action blocks, and the END block. + * @return 0 on succes, -1 on failure */ - virtual int run (const char_t** args = QSE_NULL, size_t nargs = 0); + virtual int loop (); /** - * Requests aborting execution of the parse tree + * Makes request to abort execution */ virtual void stop (); + /** + * Adds a string for ARGV. loop() and call() makes a string added + * available to a script through ARGV. Note this is not related to + * the Awk::Argument class. + */ + virtual int addArgument ( + const char_t* arg, + size_t len + ); + + virtual int addArgument (const char_t* arg); + + /** + * Deletes all ARGV strings. + */ + virtual void clearArguments (); + /** * Adds a intrinsic global variable. */ @@ -1018,9 +1009,9 @@ protected: /*@}*/ // run-time callbacks - virtual bool onRunEnter (Run& run); - virtual void onRunExit (Run& run, const Argument& ret); - virtual void onRunStatement (Run& run, size_t line); + virtual bool onLoopEnter (Run& run); + virtual void onLoopExit (Run& run, const Argument& ret); + virtual void onStatement (Run& run, size_t line); // primitive handlers virtual real_t pow (real_t x, real_t y) = 0; @@ -1047,9 +1038,9 @@ protected: rtx_t* rtx, const char_t* name, size_t len); static void freeFunctionMapValue (map_t* map, void* dptr, size_t dlen); - static int onRunEnter (rtx_t* run, void* data); - static void onRunExit (rtx_t* run, val_t* ret, void* data); - static void onRunStatement (rtx_t* run, size_t line, void* data); + static int onLoopEnter (rtx_t* run, void* data); + static void onLoopExit (rtx_t* run, val_t* ret, void* data); + static void onStatement (rtx_t* run, size_t line, void* data); static real_t pow (awk_t* data, real_t x, real_t y); static int sprintf (awk_t* data, char_t* buf, size_t size, @@ -1069,6 +1060,13 @@ protected: bool runCallback; + struct + { + qse_xstr_t* ptr; + size_t len; + size_t capa; + } runarg; + private: static const char_t* xerrstr (awk_t* a, errnum_t num) throw (); diff --git a/qse/include/qse/awk/StdAwk.hpp b/qse/include/qse/awk/StdAwk.hpp index de505bed..76b0f71a 100644 --- a/qse/include/qse/awk/StdAwk.hpp +++ b/qse/include/qse/awk/StdAwk.hpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.hpp 211 2009-06-24 09:50:10Z hyunghwan.chung $ + * $Id: StdAwk.hpp 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -39,7 +39,6 @@ class StdAwk: public Awk { public: int open (); - int run (const char_t** args, size_t nargs); protected: @@ -83,6 +82,16 @@ protected: ssize_t writeFile (File& io, const char_t* buf, size_t len); int flushFile (File& io); +#if 0 + // console io handlers + int openConsole (Console& io); + int closeConsole (Console& io); + ssize_t readConsole (Console& io, char_t* buf, size_t len); + ssize_t writeConsole (Console& io, const char_t* buf, size_t len); + int flushConsole (Console& io); + int nextConsole (Console& io); +#endif + // primitive handlers void* allocMem (size_t n) throw (); void* reallocMem (void* ptr, size_t n) throw (); @@ -94,6 +103,7 @@ protected: protected: unsigned int seed; + size_t runarg_index; }; ///////////////////////////////// diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 902dfbda..e84ca40c 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h 217 2009-06-28 13:41:47Z hyunghwan.chung $ + * $Id: awk.h 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -25,7 +25,7 @@ #include /** @file - * An embeddable AWK interpreter is defined in this header files. + * An embeddable AWK interpreter is defined in this header file. * * @example awk.c * This program demonstrates how to build a complete awk interpreter. @@ -51,10 +51,13 @@ * @code * qse_awk_t* awk; * qse_awk_rtx_t* rtx; + * qse_awk_sio_t sio; // need to initialize it with callback functions + * qse_awk_rio_t rio; // need to initialize it with callback functions + * qse_cstr_t args[5]; // need to initialize it with strings * * awk = qse_awk_open (mmgr, 0, prm); // create an interpreter - * qse_awk_parse (awk, sio); // parse a script - * rtx = qse_awk_rtx_open (awk, 0, rio, args); // create a runtime context + * qse_awk_parse (awk, &sio); // parse a script + * rtx = qse_awk_rtx_open (awk, 0, &rio, args); // create a runtime context * qse_awk_rtx_loop (rtx); // run a standard AWK loop * qse_awk_rtx_close (rtx); // destroy the runtime context * qse_awk_close (awk); // destroy the interpreter @@ -78,14 +81,30 @@ typedef struct qse_awk_t qse_awk_t; * qse_awk_rtx_open(). * * I/O handlers are categoriezed into three kinds: console, file, pipe. - * The #qse_awk_rio_t type defines a set of I/O handlers as a callback. + * The #qse_awk_rio_t type defines as a callback a set of I/O handlers + * to handle runtime I/O: + * - getline piped in from a command reads from a pipe. + * ("ls -l" | getline line) + * - print and printf piped out to a command writes to a pipe. + * (print 2 | "sort") + * - getline redirected in reads from a file. + * (getline line < "file") + * - print and printf redirected out writes to a file. + * (print num > "file") + * - The pattern-action loop and getline with no redirected input + * reads from a console. (/susie/ { ... }) + * - print and printf writes to a console. (print "hello, world") * * @sa qse_awk_t qse_awk_rtx_open qse_awk_rio_t */ typedef struct qse_awk_rtx_t qse_awk_rtx_t; /** - * The QSE_AWK_VAL_HDR defines the common header of a value type. + * The QSE_AWK_VAL_HDR defines the common header for a value. + * Three common fields are: + * - type - type of a value from #qse_awk_val_type_t + * - ref - reference count + * - nstr - numeric string marker */ #if QSE_SIZEOF_INT == 2 # define QSE_AWK_VAL_HDR \ @@ -99,8 +118,6 @@ typedef struct qse_awk_rtx_t qse_awk_rtx_t; unsigned int nstr: 2 #endif -#define QSE_AWK_VAL_TYPE(x) ((x)->type) - /** * The qse_awk_val_t type is an abstract value type. A value commonly contains: * - type of a value @@ -196,7 +213,21 @@ struct qse_awk_val_ref_t { QSE_AWK_VAL_HDR; - int id; + enum + { + /* keep these items in the same order as corresponding items + * in tree.h */ + QSE_AWK_VAL_REF_NAMED, /**< plain named variable */ + QSE_AWK_VAL_REF_GBL, /**< plain global variable */ + QSE_AWK_VAL_REF_LCL, /**< plain local variable */ + QSE_AWK_VAL_REF_ARG, /**< plain function argument */ + QSE_AWK_VAL_REF_NAMEDIDX, /**< member of named map variable */ + QSE_AWK_VAL_REF_GBLIDX, /**< member of global map variable */ + QSE_AWK_VAL_REF_LCLIDX, /**< member of local map variable */ + QSE_AWK_VAL_REF_ARGIDX, /**< member of map argument */ + QSE_AWK_VAL_REF_POS /**< positional variable */ + } id; + /* if id is QSE_AWK_VAL_REF_POS, adr holds an index of the * positional variable. Otherwise, adr points to the value * directly. */ @@ -250,36 +281,46 @@ typedef qse_ssize_t (*qse_awk_sio_fun_t) ( ); /** - * The qse_awk_rio_cmd_t type defines runtime IO commands. + * The qse_awk_rio_cmd_t type defines runtime I/O request types. */ enum qse_awk_rio_cmd_t { - QSE_AWK_RIO_OPEN = 0, - QSE_AWK_RIO_CLOSE = 1, - QSE_AWK_RIO_READ = 2, - QSE_AWK_RIO_WRITE = 3, - QSE_AWK_RIO_FLUSH = 4, - QSE_AWK_RIO_NEXT = 5 + QSE_AWK_RIO_OPEN = 0, /**< open a stream */ + QSE_AWK_RIO_CLOSE = 1, /**< close a stream */ + QSE_AWK_RIO_READ = 2, /**< read a stream */ + QSE_AWK_RIO_WRITE = 3, /**< write a stream */ + QSE_AWK_RIO_FLUSH = 4, /**< write buffered data to a stream */ + QSE_AWK_RIO_NEXT = 5 /**< close the current stream and + open the next stream. only for console */ }; typedef enum qse_awk_rio_cmd_t qse_awk_rio_cmd_t; +/** + * The qse_awk_rio_mode_t type defines the I/O modes used by I/O handlers. + * Each I/O handler should inspect the requested mode and open an I/O + * stream accordingly for subsequent operations. + */ enum qse_awk_rio_mode_t { - QSE_AWK_RIO_PIPE_READ = 0, - QSE_AWK_RIO_PIPE_WRITE = 1, - QSE_AWK_RIO_PIPE_RW = 2, + QSE_AWK_RIO_PIPE_READ = 0, /**< open a pipe for read */ + QSE_AWK_RIO_PIPE_WRITE = 1, /**< open a pipe for write */ + QSE_AWK_RIO_PIPE_RW = 2, /**< open a pipe for read and write */ - QSE_AWK_RIO_FILE_READ = 0, - QSE_AWK_RIO_FILE_WRITE = 1, - QSE_AWK_RIO_FILE_APPEND = 2, + QSE_AWK_RIO_FILE_READ = 0, /**< open a file for read */ + QSE_AWK_RIO_FILE_WRITE = 1, /**< open a file for write */ + QSE_AWK_RIO_FILE_APPEND = 2, /**< open a file for append */ - QSE_AWK_RIO_CONSOLE_READ = 0, - QSE_AWK_RIO_CONSOLE_WRITE = 1 + QSE_AWK_RIO_CONSOLE_READ = 0, /**< open a console for read */ + QSE_AWK_RIO_CONSOLE_WRITE = 1 /**< open a console for write */ }; typedef enum qse_awk_rio_mode_t qse_awk_rio_mode_t; /** - * The qse_awk_rio_arg_t defines the data passed to a rio function + * The qse_awk_rio_arg_t defines the data structure passed to a runtime + * I/O handler. An I/O handler should inspect the @a mode field and the + * @a name field and store an open handle to the @handle field when + * #QSE_AWK_RIO_OPEN is requested. For other request type, it can refer + * to the handle field set previously. */ struct qse_awk_rio_arg_t { @@ -288,7 +329,6 @@ struct qse_awk_rio_arg_t void* handle; /**< [OUT] I/O handle set by a handler */ /*-- from here down, internal use only --*/ - int type; struct @@ -411,30 +451,47 @@ typedef struct qse_awk_sio_t qse_awk_sio_t; /** * The qse_awk_rio_t type defines a runtime I/O handler set. + * @sa qse_awk_rtx_t */ struct qse_awk_rio_t { - qse_awk_rio_fun_t pipe; - qse_awk_rio_fun_t file; - qse_awk_rio_fun_t console; + qse_awk_rio_fun_t pipe; /**< pipe handler */ + qse_awk_rio_fun_t file; /**< file handler */ + qse_awk_rio_fun_t console; /**< console handler */ }; typedef struct qse_awk_rio_t qse_awk_rio_t; /** - * The qse_awk_rcb_t type defines runtime callbacks + * The qse_awk_rcb_t type defines runtime callbacks. You may set callbacks + * with qse_awk_rtx_setrcb() to be informed of important events during runtime. */ struct qse_awk_rcb_t { + /** + * called by qse_awk_rtx_loop() before entering pattern-action loop. + * A @b BEGIN block is executed after this callback. + */ int (*on_loop_enter) ( - qse_awk_rtx_t* rtx, void* data); + qse_awk_rtx_t* rtx, void* udd); + /** + * called by qse_awk_rtx_loop() when exiting pattern-action loop. + * An @b END block is executed before this callback. + */ void (*on_loop_exit) ( - qse_awk_rtx_t* rtx, qse_awk_val_t* ret, void* data); + qse_awk_rtx_t* rtx, qse_awk_val_t* ret, void* udd); + /** + * called by qse_awk_rtx_loop() and qse_awk_rtx_call() for + * each statement executed. + */ void (*on_statement) ( - qse_awk_rtx_t* rtx, qse_size_t line, void* data); + qse_awk_rtx_t* rtx, qse_size_t line, void* udd); - void* data; + /** + * A caller may store a custom data pointer into this field. + */ + void* udd; }; typedef struct qse_awk_rcb_t qse_awk_rcb_t; @@ -467,7 +524,7 @@ enum qse_awk_option_t /** supports @b getline and @b print */ QSE_AWK_RIO = (1 << 7), - /** supports dual direction pipe if QSE_AWK_RIO is on */ + /** supports dual direction pipe if #QSE_AWK_RIO is on */ QSE_AWK_RWPIPE = (1 << 8), /** a new line can terminate a statement */ @@ -518,7 +575,7 @@ enum qse_awk_option_t QSE_AWK_NCMPONSTR = (1 << 17), /** - * strict naming rule + * enables the strict naming rule. * - a parameter can not be the same as the owning function name. * - a local variable can not be the same as the owning function name. */ @@ -538,154 +595,145 @@ enum qse_awk_option_t */ enum qse_awk_errnum_t { - QSE_AWK_ENOERR, /* no error */ - QSE_AWK_EUNKNOWN, /* unknown error */ + QSE_AWK_ENOERR, /**< no error */ + QSE_AWK_EUNKNOWN,/**< unknown error */ /* common errors */ - QSE_AWK_EINVAL, /* invalid parameter or data */ - QSE_AWK_ENOMEM, /* out of memory */ - QSE_AWK_ENOSUP, /* not supported */ - QSE_AWK_ENOPER, /* operation not allowed */ - QSE_AWK_ENODEV, /* no such device */ - QSE_AWK_ENOSPC, /* no space left on device */ - QSE_AWK_EMFILE, /* too many open files */ - QSE_AWK_EMLINK, /* too many links */ - QSE_AWK_EAGAIN, /* resource temporarily unavailable */ - QSE_AWK_ENOENT, /* '${1}' not existing */ - QSE_AWK_EEXIST, /* file or data exists */ - QSE_AWK_EFTBIG, /* file or data too big */ - QSE_AWK_ETBUSY, /* system too busy */ - QSE_AWK_EISDIR, /* is a directory */ - QSE_AWK_RIOERR, /* i/o error */ + QSE_AWK_EINVAL, /**< invalid parameter or data */ + QSE_AWK_ENOMEM, /**< insufficient memory */ + QSE_AWK_ENOSUP, /**< not supported */ + QSE_AWK_ENOPER, /**< operation not allowed */ + QSE_AWK_ENOENT, /**< '${0}' not found */ + QSE_AWK_EEXIST, /**< '${0}' already exists */ + QSE_AWK_EIOERR, /**< I/O error */ /* mostly parse errors */ - QSE_AWK_EOPEN, /* cannot open */ - QSE_AWK_EREAD, /* cannot read */ - QSE_AWK_EWRITE, /* cannot write */ - QSE_AWK_ECLOSE, /* cannot close */ + QSE_AWK_EOPEN, /**< cannot open '${0}' */ + QSE_AWK_EREAD, /**< cannot read '${0}' */ + QSE_AWK_EWRITE, /**< cannot write '${0}' */ + QSE_AWK_ECLOSE, /**< cannot close '${0}' */ - QSE_AWK_EINTERN, /* internal error */ - QSE_AWK_ERUNTIME, /* run-time error */ - QSE_AWK_EBLKNST, /* blocke nested too deeply */ - QSE_AWK_EEXPRNST, /* expression nested too deeply */ + QSE_AWK_EINTERN, /**< internal error */ + QSE_AWK_ERUNTIME,/**< general run-time error */ + QSE_AWK_EBLKNST, /**< block nested too deeply */ + QSE_AWK_EEXPRNST,/**< expression nested too deeply */ - QSE_AWK_ESINOP, /* failed to open source input */ - QSE_AWK_ESINCL, /* failed to close source output */ - QSE_AWK_ESINRD, /* failed to read source input */ + QSE_AWK_ESINOP, /**< failed to open source input */ + QSE_AWK_ESINCL, /**< failed to close source output */ + QSE_AWK_ESINRD, /**< failed to read source input */ - QSE_AWK_ESOUTOP, /* failed to open source output */ - QSE_AWK_ESOUTCL, /* failed to close source output */ - QSE_AWK_ESOUTWR, /* failed to write source output */ + QSE_AWK_ESOUTOP, /**< failed to open source output */ + QSE_AWK_ESOUTCL, /**< failed to close source output */ + QSE_AWK_ESOUTWR, /**< failed to write source output */ - QSE_AWK_ELXCHR, /* lexer came accross an wrong character */ - QSE_AWK_ELXDIG, /* invalid digit */ - QSE_AWK_ELXUNG, /* lexer failed to unget a character */ + QSE_AWK_ELXCHR, /**< invalid character '${0}' */ + QSE_AWK_ELXDIG, /**< invalid digit '${0}' */ + QSE_AWK_ELXUNG, /**< failed to unget character */ - QSE_AWK_EENDSRC, /* unexpected end of source */ - QSE_AWK_EENDCMT, /* a comment not closed properly */ - QSE_AWK_EENDSTR, /* a string not closed with a quote */ - QSE_AWK_EENDREX, /* unexpected end of a regular expression */ - QSE_AWK_ELBRACE, /* left brace expected */ - QSE_AWK_ELPAREN, /* left parenthesis expected */ - QSE_AWK_ERPAREN, /* right parenthesis expected */ - QSE_AWK_ERBRACK, /* right bracket expected */ - QSE_AWK_ECOMMA, /* comma expected */ - QSE_AWK_ESCOLON, /* semicolon expected */ - QSE_AWK_ECOLON, /* colon expected */ - QSE_AWK_ESTMEND, /* statement not ending with a semicolon */ - QSE_AWK_EIN, /* keyword 'in' is expected */ - QSE_AWK_ENOTVAR, /* not a variable name after 'in' */ - QSE_AWK_EEXPRES, /* expression expected */ + QSE_AWK_EENDSRC, /**< unexpected end of source */ + QSE_AWK_EENDCMT, /**< comment not closed properly */ + QSE_AWK_EENDSTR, /**< string or regular expression not closed */ + QSE_AWK_EENDREX, /**< unexpected end of regular expression */ + QSE_AWK_ELBRACE, /**< left brace expected in place of '${0}' */ + QSE_AWK_ELPAREN, /**< left parenthesis expected in place of '${0}' */ + QSE_AWK_ERPAREN, /**< right parenthesis expected in place of '${0}' */ + QSE_AWK_ERBRACK, /**< right bracket expected in place of '${0}' */ + QSE_AWK_ECOMMA, /**< comma expected in place of '${0}' */ + QSE_AWK_ESCOLON, /**< semicolon expected in place of '${0}' */ + QSE_AWK_ECOLON, /**< colon expected in place of '${0}' */ + QSE_AWK_ESTMEND, /**< statement not ending with a semicolon */ + QSE_AWK_EIN, /**< 'in' expected in place of '${0}' */ + QSE_AWK_ENOTVAR, /**< right-hand side of 'in' not a variable */ + QSE_AWK_EEXPRES, /**< invalid expression */ - QSE_AWK_EFUNCTION, /* keyword 'function' is expected */ - QSE_AWK_EWHILE, /* keyword 'while' is expected */ - QSE_AWK_EASSIGN, /* assignment statement expected */ - QSE_AWK_EIDENT, /* identifier expected */ - QSE_AWK_EFUNNAME, /* not a valid function name */ - QSE_AWK_EBLKBEG, /* BEGIN requires an action block */ - QSE_AWK_EBLKEND, /* END requires an action block */ - QSE_AWK_EDUPBEG, /* duplicate BEGIN */ - QSE_AWK_EDUPEND, /* duplicate END */ - QSE_AWK_EKWRED, /* keyword redefined */ - QSE_AWK_EFNCRED, /* intrinsic function redefined */ - QSE_AWK_EFUNRED, /* function redefined */ - QSE_AWK_EGBLRED, /* global variable redefined */ - QSE_AWK_EPARRED, /* parameter redefined */ - QSE_AWK_EVARRED, /* named variable redefined */ - QSE_AWK_EDUPPAR, /* duplicate parameter name */ - QSE_AWK_EDUPGBL, /* duplicate global variable name */ - QSE_AWK_EDUPLCL, /* duplicate local variable name */ - QSE_AWK_EBADPAR, /* not a valid parameter name */ - QSE_AWK_EBADVAR, /* not a valid variable name */ - QSE_AWK_EVARMS, /* variable name missing */ - QSE_AWK_EUNDEF, /* undefined identifier */ - QSE_AWK_ELVALUE, /* l-value required */ - QSE_AWK_EGBLTM, /* too many global variables */ - QSE_AWK_ELCLTM, /* too many local variables */ - QSE_AWK_EPARTM, /* too many parameters */ - QSE_AWK_EDELETE, /* delete not followed by a variable */ - QSE_AWK_ERESET, /* reset not followed by a variable */ - QSE_AWK_EBREAK, /* break outside a loop */ - QSE_AWK_ECONTINUE, /* continue outside a loop */ - QSE_AWK_ENEXTBEG, /* next illegal in BEGIN block */ - QSE_AWK_ENEXTEND, /* next illegal in END block */ - QSE_AWK_ENEXTFBEG, /* nextfile illegal in BEGIN block */ - QSE_AWK_ENEXTFEND, /* nextfile illegal in END block */ - QSE_AWK_EPRINTFARG, /* printf not followed by any arguments */ - QSE_AWK_EPREPST, /* both prefix and postfix increment/decrement - operator present */ + QSE_AWK_EFUNCTION, /**< 'function' is expected in place of '${0}' */ + QSE_AWK_EWHILE, /**< 'while' is expected in place of '${0}' */ + QSE_AWK_EASSIGN, /**< assignment statement expected */ + QSE_AWK_EIDENT, /**< identifier expected in place of '${0}' */ + QSE_AWK_EFUNNAME, /**< '${0}' not a valid function name */ + QSE_AWK_EBLKBEG, /**< BEGIN not followed by left bracket on the same line */ + QSE_AWK_EBLKEND, /**< END not followed by left bracket on the same line */ + QSE_AWK_EDUPBEG, /**< duplicate BEGIN */ + QSE_AWK_EDUPEND, /**< duplicate END */ + QSE_AWK_EKWRED, /**< keyword '${0}' redefined */ + QSE_AWK_EFNCRED, /**< intrinsic function '${0}' redefined */ + QSE_AWK_EFUNRED, /**< function '${0}' redefined */ + QSE_AWK_EGBLRED, /**< global variable '${0}' redefined */ + QSE_AWK_EPARRED, /**< parameter '${0}' redefined */ + QSE_AWK_EVARRED, /**< variable '${0}' redefined */ + QSE_AWK_EDUPPAR, /**< duplicate parameter name '${0}' */ + QSE_AWK_EDUPGBL, /**< duplicate global variable name '${0}' */ + QSE_AWK_EDUPLCL, /**< duplicate local variable name '${0}' */ + QSE_AWK_EBADPAR, /**< '${0}' not a valid parameter name */ + QSE_AWK_EBADVAR, /**< '${0}' not a valid variable name */ + QSE_AWK_EVARMS, /**< variable name missing */ + QSE_AWK_EUNDEF, /**< undefined identifier '${0}' */ + QSE_AWK_ELVALUE, /**< l-value required */ + QSE_AWK_EGBLTM, /**< too many global variables */ + QSE_AWK_ELCLTM, /**< too many local variables */ + QSE_AWK_EPARTM, /**< too many parameters */ + QSE_AWK_EDELETE, /**< 'delete' not followed by variable */ + QSE_AWK_ERESET, /**< 'reset' not followed by variable */ + QSE_AWK_EBREAK, /**< 'break' outside a loop */ + QSE_AWK_ECONTINUE, /**< 'continue' outside a loop */ + QSE_AWK_ENEXTBEG, /**< 'next' illegal in BEGIN block */ + QSE_AWK_ENEXTEND, /**< 'next' illegal in END block */ + QSE_AWK_ENEXTFBEG, /**< 'nextfile' illegal in BEGIN block */ + QSE_AWK_ENEXTFEND, /**< 'nextfile' illegal in END block */ + QSE_AWK_EPRINTFARG,/**< 'printf' not followed by argument */ + QSE_AWK_EPREPST, /**< both prefix and postfix incr/decr operator present */ /* run time error */ - QSE_AWK_EDIVBY0, /* divide by zero */ - QSE_AWK_EOPERAND, /* invalid operand */ - QSE_AWK_EPOSIDX, /* wrong position index */ - QSE_AWK_EARGTF, /* too few arguments */ - QSE_AWK_EARGTM, /* too many arguments */ - QSE_AWK_EFUNNONE, /* function '${1}' not found */ - QSE_AWK_ENOTIDX, /* variable not indexable */ - QSE_AWK_ENOTDEL, /* variable not deletable */ - QSE_AWK_ENOTMAP, /* value not a map */ - QSE_AWK_ENOTMAPIN, /* right-hand side of 'in' not a map */ - QSE_AWK_ENOTMAPNILIN, /* right-hand side of 'in' not a map nor nil */ - QSE_AWK_ENOTREF, /* value not referenceable */ - QSE_AWK_ENOTASS, /* value not assignable */ - QSE_AWK_EIDXVALASSMAP, /* indexed value cannot be assigned a map */ - QSE_AWK_EPOSVALASSMAP, /* a positional cannot be assigned a map */ - QSE_AWK_EMAPTOSCALAR, /* cannot change a map to a scalar value */ - QSE_AWK_ESCALARTOMAP, /* cannot change a scalar value to a map */ - QSE_AWK_EMAPNOTALLOWED, /* a map is not allowed */ - QSE_AWK_EVALTYPE, /* invalid value type */ - QSE_AWK_ERDELETE, /* delete called with a wrong target */ - QSE_AWK_ERRESET, /* reset called with a wrong target */ - QSE_AWK_ERNEXTBEG, /* next called from BEGIN */ - QSE_AWK_ERNEXTEND, /* next called from END */ - QSE_AWK_ERNEXTFBEG, /* nextfile called from BEGIN */ - QSE_AWK_ERNEXTFEND, /* nextfile called from END */ - QSE_AWK_EFNCUSER, /* wrong intrinsic function implementation */ - QSE_AWK_EFNCIMPL, /* intrinsic function handler failed */ - QSE_AWK_EIOUSER, /* wrong user io handler implementation */ - QSE_AWK_EIOIMPL, /* i/o callback returned an error */ - QSE_AWK_EIONMNF, /* no such io name found */ - QSE_AWK_EIONMEM, /* i/o name empty */ - QSE_AWK_EIONMNL, /* i/o name contains '\0' */ - QSE_AWK_EFMTARG, /* arguments to format string not sufficient */ - QSE_AWK_EFMTCNV, /* recursion detected in format conversion */ - QSE_AWK_ECONVFMTCHR, /* an invalid character found in CONVFMT */ - QSE_AWK_EOFMTCHR, /* an invalid character found in OFMT */ + QSE_AWK_EDIVBY0, /**< divide by zero */ + QSE_AWK_EOPERAND, /**< invalid operand */ + QSE_AWK_EPOSIDX, /**< wrong position index */ + QSE_AWK_EARGTF, /**< too few arguments */ + QSE_AWK_EARGTM, /**< too many arguments */ + QSE_AWK_EFUNNF, /**< function '${0}' not found */ + QSE_AWK_ENOTIDX, /**< variable not indexable */ + QSE_AWK_ENOTDEL, /**< variable '${0}' not deletable */ + QSE_AWK_ENOTMAP, /**< value not a map */ + QSE_AWK_ENOTMAPIN, /**< right-hand side of 'in' not a map */ + QSE_AWK_ENOTMAPNILIN, /**< right-hand side of 'in' not a map nor nil */ + QSE_AWK_ENOTREF, /**< value not referenceable */ + QSE_AWK_ENOTASS, /**< value not assignable */ + QSE_AWK_EIDXVALASSMAP, /**< an indexed value cannot be assigned a map */ + QSE_AWK_EPOSVALASSMAP, /**< a positional cannot be assigned a map */ + QSE_AWK_EMAPTOSCALAR, /**< map '${0}' not assignable with a scalar */ + QSE_AWK_ESCALARTOMAP, /**< cannot change a scalar value to a map */ + QSE_AWK_EMAPNOTALLOWED,/**< map not allowed */ + QSE_AWK_EVALTYPE, /**< invalid value type */ + QSE_AWK_ERDELETE, /**< 'delete' called with wrong target */ + QSE_AWK_ERRESET, /**< 'reset' called with wrong target */ + QSE_AWK_ERNEXTBEG, /**< 'next' called from BEGIN block */ + QSE_AWK_ERNEXTEND, /**< 'next' called from END block */ + QSE_AWK_ERNEXTFBEG, /**< 'nextfile' called from BEGIN block */ + QSE_AWK_ERNEXTFEND, /**< 'nextfile' called from END block */ + QSE_AWK_EFNCUSER, /**< wrong intrinsic function implementation */ + QSE_AWK_EFNCIMPL, /**< intrinsic function handler failed */ + QSE_AWK_EIOUSER, /**< wrong user io handler implementation */ + QSE_AWK_EIOIMPL, /**< I/O callback returned an error */ + QSE_AWK_EIONMNF, /**< no such I/O name found */ + QSE_AWK_EIONMEM, /**< I/O name empty */ + QSE_AWK_EIONMNL, /**< I/O name '${0}' containing '\\0' */ + QSE_AWK_EFMTARG, /**< not sufficient arguments to formatting sequence */ + QSE_AWK_EFMTCNV, /**< recursion detected in format conversion */ + QSE_AWK_ECONVFMTCHR, /**< invalid character in CONVFMT */ + QSE_AWK_EOFMTCHR, /**< invalid character in OFMT */ /* regular expression error */ - QSE_AWK_EREXRECUR, /* recursion too deep */ - QSE_AWK_EREXRPAREN, /* a right parenthesis is expected */ - QSE_AWK_EREXRBRACKET, /* a right bracket is expected */ - QSE_AWK_EREXRBRACE, /* a right brace is expected */ - QSE_AWK_EREXUNBALPAREN, /* unbalanced parenthesis */ - QSE_AWK_EREXINVALBRACE, /* invalid brace */ - QSE_AWK_EREXCOLON, /* a colon is expected */ - QSE_AWK_EREXCRANGE, /* invalid character range */ - QSE_AWK_EREXCCLASS, /* invalid character class */ - QSE_AWK_EREXBRANGE, /* invalid boundary range */ - QSE_AWK_EREXEND, /* unexpected end of the pattern */ - QSE_AWK_EREXGARBAGE, /* garbage after the pattern */ + QSE_AWK_EREXRECUR, /**< recursion too deep */ + QSE_AWK_EREXRPAREN, /**< a right parenthesis is expected */ + QSE_AWK_EREXRBRACKET, /**< a right bracket is expected */ + QSE_AWK_EREXRBRACE, /**< a right brace is expected */ + QSE_AWK_EREXUNBALPAREN,/**< unbalanced parenthesis */ + QSE_AWK_EREXINVALBRACE,/**< invalid brace */ + QSE_AWK_EREXCOLON, /**< a colon is expected */ + QSE_AWK_EREXCRANGE, /**< invalid character range */ + QSE_AWK_EREXCCLASS, /**< invalid character class */ + QSE_AWK_EREXBRANGE, /**< invalid boundary range */ + QSE_AWK_EREXEND, /**< unexpected end of the pattern */ + QSE_AWK_EREXGARBAGE, /**< garbage after the pattern */ /* the number of error numbers, internal use only */ QSE_AWK_NUMERRNUM @@ -705,7 +753,7 @@ struct qse_awk_errinf_t typedef struct qse_awk_errinf_t qse_awk_errinf_t; /** - * The qse_awk_errstr_t type defines a error string getter. It should return + * The qse_awk_errstr_t type defines an error string getter. It should return * an error formatting string for an error number requested. A new string * should contain the same number of positional parameters (${X}) as in the * default error formatting string. You can set a new getter into an awk @@ -761,34 +809,24 @@ enum qse_awk_gbl_id_t QSE_AWK_MAX_GBL_ID = QSE_AWK_GBL_SUBSEP }; +/** + * The qse_awk_val_type_t type defines types of AWK values. Each value + * allocated is tagged with a value type in the @a type field. + * @sa qse_awk_val_t QSE_AWK_VAL_HDR + */ enum qse_awk_val_type_t { /* the values between QSE_AWK_VAL_NIL and QSE_AWK_VAL_STR inclusive * must be synchronized with an internal table of the __cmp_val * function in run.c */ - QSE_AWK_VAL_NIL = 0, - QSE_AWK_VAL_INT = 1, - QSE_AWK_VAL_REAL = 2, - QSE_AWK_VAL_STR = 3, + QSE_AWK_VAL_NIL = 0, /**< nil */ + QSE_AWK_VAL_INT = 1, /**< integer */ + QSE_AWK_VAL_REAL = 2, /**< floating-pointer number */ + QSE_AWK_VAL_STR = 3, /**< string */ - QSE_AWK_VAL_REX = 4, - QSE_AWK_VAL_MAP = 5, - QSE_AWK_VAL_REF = 6 -}; - -enum qse_awk_val_ref_id_t -{ - /* keep these items in the same order as corresponding items - * in tree.h */ - QSE_AWK_VAL_REF_NAMED, - QSE_AWK_VAL_REF_GBL, - QSE_AWK_VAL_REF_LCL, - QSE_AWK_VAL_REF_ARG, - QSE_AWK_VAL_REF_NAMEDIDX, - QSE_AWK_VAL_REF_GBLIDX, - QSE_AWK_VAL_REF_LCLIDX, - QSE_AWK_VAL_REF_ARGIDX, - QSE_AWK_VAL_REF_POS + QSE_AWK_VAL_REX = 4, /**< regular expression */ + QSE_AWK_VAL_MAP = 5, /**< map */ + QSE_AWK_VAL_REF = 6 /**< reference to other types */ }; /** @@ -1166,19 +1204,30 @@ int qse_awk_parse ( /** * The qse_awk_alloc() function allocates dynamic memory. - * @return a pointer to memory space allocated on success, #QSE_NULL on failure + * @return a pointer to a memory block on success, #QSE_NULL on failure */ void* qse_awk_alloc ( qse_awk_t* awk, /**< awk object */ qse_size_t size /**< size of memory to allocate in bytes */ ); +/** + * The qse_awk_realloc() function resizes a dynamic memory block. + * @return a pointer to a memory block on success, #QSE_NULL on failure + */ +void* qse_awk_realloc ( + qse_awk_t* awk, /**< awk object */ + void* ptr, /**< memory block */ + qse_size_t size /**< new block size in bytes */ +); + + /** * The qse_awk_free() function frees dynamic memory allocated. */ void qse_awk_free ( qse_awk_t* awk, /**< awk object */ - void* ptr /**< memory space to free */ + void* ptr /**< memory block to free */ ); /** @@ -1245,8 +1294,7 @@ qse_awk_rtx_t* qse_awk_rtx_open ( ); /** - * The qse_awk_rtx_close() function destroys a runtime context - * SYNOPSIS + * The qse_awk_rtx_close() function destroys a runtime context. */ void qse_awk_rtx_close ( qse_awk_rtx_t* rtx /**< runtime context */ @@ -1325,18 +1373,22 @@ void qse_awk_rtx_stop ( ); /** - * The qse_awk_rtx_setrcb() function gets runtime callback. + * The qse_awk_rtx_setrcb() function gets runtime callbacks. + * @return #QSE_NULL if no callback is set. Otherwise, the pointer to a + * callback set. + * @sa qse_awk_rtx_setrcb */ qse_awk_rcb_t* qse_awk_rtx_getrcb ( - qse_awk_rtx_t* rtx + qse_awk_rtx_t* rtx /**< runtime context */ ); /** - * The qse_awk_rtx_setrcb() function sets runtime callback. + * The qse_awk_rtx_setrcb() function sets runtime callbacks. + * @sa qse_awk_rtx_getrcb */ void qse_awk_rtx_setrcb ( - qse_awk_rtx_t* rtx, - qse_awk_rcb_t* rcb + qse_awk_rtx_t* rtx, /**< runtime context */ + qse_awk_rcb_t* rcb /**< callback set */ ); /** diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index 08f9d414..94cbed6e 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -1,5 +1,5 @@ /* - * $Id: types.h 204 2009-06-18 12:08:06Z hyunghwan.chung $ + * $Id: types.h 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -371,11 +371,12 @@ typedef int qse_mcint_t; /** * The qse_xstr_t type defines a structure combining a pointer to a character - * string and the number of characters. + * string and the number of characters. It is designed to be interchangeable + * with the #qse_cstr_t type except the constness on the @a ptr field. */ struct qse_xstr_t { - qse_char_t* ptr; /**< a pointer to a character string */ + qse_char_t* ptr; /**< pointer to a character string */ qse_size_t len; /**< the number of characters */ }; typedef struct qse_xstr_t qse_xstr_t; @@ -383,10 +384,12 @@ typedef struct qse_xstr_t qse_xstr_t; /** * The qse_cstr_t type defines a structure combining a pointer to * a constant character string and the number of characters. + * It is designed to be interchangeable with the #qse_xstr_t type + * except the constness on the @a ptr field. */ struct qse_cstr_t { - const qse_char_t* ptr; /**< a pointer to a const character string */ + const qse_char_t* ptr; /**< pointer to a const character string */ qse_size_t len; /**< the number of characters */ }; typedef struct qse_cstr_t qse_cstr_t; diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index 2bfa1299..5ed8637c 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp 212 2009-06-25 07:39:27Z hyunghwan.chung $ + * $Id: Awk.cpp 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -226,7 +226,7 @@ void Awk::Argument::clear () this->str.ptr = QSE_NULL; this->str.len = 0; } - else if (QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP) + else if (this->val->type == QSE_AWK_VAL_MAP) { QSE_ASSERT (this->run != QSE_NULL); @@ -241,7 +241,7 @@ void Awk::Argument::clear () if (this->str.ptr != QSE_NULL) { - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_STR) + if (this->val->type != QSE_AWK_VAL_STR) { awk_t* awk = this->run->awk->awk; qse_awk_free (awk, this->str.ptr); @@ -315,7 +315,7 @@ int Awk::Argument::init (val_t* v) qse_awk_rtx_refupval (this->run->run, v); this->val = v; - if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_STR) + if (v->type == QSE_AWK_VAL_STR) { int n = qse_awk_rtx_valtonum ( this->run->run, v, &this->inum, &this->rnum); @@ -334,7 +334,7 @@ int Awk::Argument::init (val_t* v) return 0; } } - else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_INT) + else if (v->type == QSE_AWK_VAL_INT) { this->inum = ((qse_awk_val_int_t*)v)->val; this->rnum = (qse_real_t)((qse_awk_val_int_t*)v)->val; @@ -343,7 +343,7 @@ int Awk::Argument::init (val_t* v) this->run->run, v, &this->str.len); if (this->str.ptr != QSE_NULL) return 0; } - else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_REAL) + else if (v->type == QSE_AWK_VAL_REAL) { this->inum = (qse_long_t)((qse_awk_val_real_t*)v)->val; this->rnum = ((qse_awk_val_real_t*)v)->val; @@ -352,7 +352,7 @@ int Awk::Argument::init (val_t* v) this->run->run, v, &this->str.len); if (this->str.ptr != QSE_NULL) return 0; } - else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_NIL) + else if (v->type == QSE_AWK_VAL_NIL) { this->inum = 0; this->rnum = 0.0; @@ -361,7 +361,7 @@ int Awk::Argument::init (val_t* v) this->run->run, v, &this->str.len); if (this->str.ptr != QSE_NULL) return 0; } - else if (QSE_AWK_VAL_TYPE(v) == QSE_AWK_VAL_MAP) + else if (v->type == QSE_AWK_VAL_MAP) { this->inum = 0; this->rnum = 0.0; @@ -412,7 +412,7 @@ const Awk::char_t* Awk::Argument::toStr (size_t* len) const { if (this->val != QSE_NULL && - QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP) + this->val->type == QSE_AWK_VAL_MAP) { *len = 0; return QSE_T(""); @@ -432,7 +432,7 @@ const Awk::char_t* Awk::Argument::toStr (size_t* len) const bool Awk::Argument::isIndexed () const { if (this->val == QSE_NULL) return false; - return QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP; + return this->val->type == QSE_AWK_VAL_MAP; } int Awk::Argument::getIndexed (const char_t* idxptr, Awk::Argument& val) const @@ -448,7 +448,7 @@ int Awk::Argument::getIndexed ( // not initialized yet. val is just nil. not an error if (this->val == QSE_NULL) return 0; // not a map. val is just nil. not an error - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) return 0; + if (this->val->type != QSE_AWK_VAL_MAP) return 0; // get the value from the map. qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val; @@ -469,7 +469,7 @@ int Awk::Argument::getIndexed (long_t idx, Argument& val) const if (this->val == QSE_NULL) return 0; // not a map. val is just nil. not an error - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) return 0; + if (this->val->type != QSE_AWK_VAL_MAP) return 0; char_t ri[128]; @@ -510,7 +510,7 @@ int Awk::Argument::getFirstIndex (Awk::Argument& val) const val.clear (); if (this->val == QSE_NULL) return -1; - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) return -1; + if (this->val->type != QSE_AWK_VAL_MAP) return -1; qse_size_t buckno; qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val; @@ -533,7 +533,7 @@ int Awk::Argument::getNextIndex (Awk::Argument& val) const val.clear (); if (this->val == QSE_NULL) return -1; - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) return -1; + if (this->val->type != QSE_AWK_VAL_MAP) return -1; qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val; @@ -624,7 +624,7 @@ int Awk::Return::set (const char_t* ptr, size_t len) bool Awk::Return::isIndexed () const { if (this->val == QSE_NULL) return false; - return QSE_AWK_VAL_TYPE(this->val) == QSE_AWK_VAL_MAP; + return this->val->type == QSE_AWK_VAL_MAP; } int Awk::Return::setIndexed (const char_t* idx, size_t iln, long_t v) @@ -639,7 +639,7 @@ int Awk::Return::setIndexed (const char_t* idx, size_t iln, long_t v) return -1; } - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) + if (this->val->type != QSE_AWK_VAL_MAP) { qse_awk_val_t* x = qse_awk_rtx_makemapval (this->run->run); if (x == QSE_NULL) return -1; @@ -702,7 +702,7 @@ int Awk::Return::setIndexed (const char_t* idx, size_t iln, real_t v) return -1; } - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) + if (this->val->type != QSE_AWK_VAL_MAP) { qse_awk_val_t* x = qse_awk_rtx_makemapval (this->run->run); if (x == QSE_NULL) return -1; @@ -765,7 +765,7 @@ int Awk::Return::setIndexed (const char_t* idx, size_t iln, const char_t* str, s return -1; } - if (QSE_AWK_VAL_TYPE(this->val) != QSE_AWK_VAL_MAP) + if (this->val->type != QSE_AWK_VAL_MAP) { qse_awk_val_t* x = qse_awk_rtx_makemapval (this->run->run); if (x == QSE_NULL) return -1; @@ -1078,6 +1078,10 @@ Awk::Awk () throw (): awk (QSE_NULL), functionMap (QSE_NULL), { this->errmsg[0] = QSE_T('\0'); + + this->runarg.ptr = QSE_NULL; + this->runarg.len = 0; + this->runarg.capa = 0; } Awk::operator Awk::awk_t* () const @@ -1234,6 +1238,8 @@ int Awk::open () void Awk::close () { + clearArguments (); + if (functionMap != QSE_NULL) { qse_map_close (functionMap); @@ -1345,14 +1351,12 @@ int Awk::parse () return n; } -int Awk::run (const char_t** args, size_t nargs) +int Awk::loop () { QSE_ASSERT (awk != QSE_NULL); - size_t i; qse_awk_rio_t rio; qse_awk_rcb_t rcb; - qse_xstr_t* runarg = QSE_NULL; // note that the run field is set below after qse_awk_rtx_open() is // executed. @@ -1365,44 +1369,15 @@ int Awk::run (const char_t** args, size_t nargs) if (runCallback) { QSE_MEMSET (&rcb, 0, QSE_SIZEOF(rcb)); - // TODO: deprecate onRunStart and onRunEnd - rcb.on_loop_enter = onRunEnter; - rcb.on_loop_exit = onRunExit; - rcb.on_statement = onRunStatement; - rcb.data = &runctx; - } - - if (nargs > 0) - { - runarg = (qse_xstr_t*) qse_awk_alloc ( - awk, QSE_SIZEOF(qse_xstr_t)*(nargs+1)); - - if (runarg == QSE_NULL) - { - setError (ERR_NOMEM); - return -1; - } - - for (i = 0; i < nargs; i++) - { - runarg[i].len = qse_strlen (args[i]); - runarg[i].ptr = qse_awk_strxdup (awk, args[i], runarg[i].len); - if (runarg[i].ptr == QSE_NULL) - { - while (i > 0) qse_awk_free (awk, runarg[--i].ptr); - qse_awk_free (awk, runarg); - setError (ERR_NOMEM); - return -1; - } - } - - runarg[i].ptr = QSE_NULL; - runarg[i].len = 0; + rcb.on_loop_enter = onLoopEnter; + rcb.on_loop_exit = onLoopExit; + 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); + awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg.ptr); if (rtx == QSE_NULL) { retrieveError(); @@ -1421,13 +1396,6 @@ int Awk::run (const char_t** args, size_t nargs) qse_awk_rtx_close (rtx); } - if (nargs > 0) - { - QSE_ASSERT (runarg != QSE_NULL); - while (i > 0) qse_awk_free (awk, runarg[--i].ptr); - qse_awk_free (awk, runarg); - } - return n; } @@ -1447,7 +1415,7 @@ int Awk::dispatchFunction (Run* run, const char_t* name, size_t len) pair = qse_map_search (functionMap, name, len); if (pair == QSE_NULL) { - run->setError (ERR_FUNNONE, 0, name, len); + run->setError (ERR_FUNNF, 0, name, len); return -1; } @@ -1496,6 +1464,60 @@ int Awk::dispatchFunction (Run* run, const char_t* name, size_t len) return 0; } +int Awk::addArgument (const char_t* arg, size_t len) +{ + QSE_ASSERT (awk != QSE_NULL); + + if (runarg.len >= runarg.capa) + { + qse_xstr_t* ptr; + size_t capa = runarg.capa; + + capa += 64; + ptr = (qse_xstr_t*) qse_awk_realloc ( + awk, runarg.ptr, QSE_SIZEOF(qse_xstr_t)*(capa+1)); + if (ptr == QSE_NULL) + { + setError (ERR_NOMEM); + return -1; + } + + runarg.ptr = ptr; + runarg.capa = capa; + } + + runarg.ptr[runarg.len].len = len; + runarg.ptr[runarg.len].ptr = qse_awk_strxdup (awk, arg, len); + if (runarg.ptr[runarg.len].ptr == QSE_NULL) + { + setError (ERR_NOMEM); + return -1; + } + + runarg.len++; + runarg.ptr[runarg.len].len = 0; + runarg.ptr[runarg.len].ptr = QSE_NULL; + + return 0; +} + +int Awk::addArgument (const char_t* arg) +{ + return addArgument (arg, qse_strlen(arg)); +} + +void Awk::clearArguments () +{ + if (runarg.ptr != QSE_NULL) + { + QSE_ASSERT (awk != QSE_NULL); + qse_awk_free (awk, runarg.ptr); + runarg.ptr = QSE_NULL; + runarg.len = 0; + runarg.capa = 0; + } +} + int Awk::addGlobal (const char_t* name) { QSE_ASSERT (awk != QSE_NULL); @@ -1579,16 +1601,16 @@ void Awk::disableRunCallback () runCallback = false; } -bool Awk::onRunEnter (Run& run) +bool Awk::onLoopEnter (Run& run) { return true; } -void Awk::onRunExit (Run& run, const Argument& ret) +void Awk::onLoopExit (Run& run, const Argument& ret) { } -void Awk::onRunStatement (Run& run, size_t line) +void Awk::onStatement (Run& run, size_t line) { } @@ -1742,26 +1764,26 @@ void Awk::freeFunctionMapValue (map_t* map, void* dptr, size_t dlen) qse_awk_free (awk->awk, dptr); } -int Awk::onRunEnter (rtx_t* run, void* data) +int Awk::onLoopEnter (rtx_t* run, void* data) { Run* r = (Run*)data; - return r->awk->onRunEnter(*r)? 0: -1; + return r->awk->onLoopEnter(*r)? 0: -1; } -void Awk::onRunExit (rtx_t* run, val_t* ret, void* data) +void Awk::onLoopExit (rtx_t* run, val_t* ret, void* data) { Run* r = (Run*)data; Argument x (r); if (x.init (ret) == -1) qse_awk_rtx_seterrnum (r->run, (errnum_t)ERR_NOMEM); - else r->awk->onRunExit (*r, x); + else r->awk->onLoopExit (*r, x); } -void Awk::onRunStatement (rtx_t* run, size_t line, void* data) +void Awk::onStatement (rtx_t* run, size_t line, void* data) { Run* r = (Run*)data; - r->awk->onRunStatement (*r, line); + r->awk->onStatement (*r, line); } Awk::real_t Awk::pow (awk_t* awk, real_t x, real_t y) diff --git a/qse/lib/awk/StdAwk.cpp b/qse/lib/awk/StdAwk.cpp index 21720d53..4d1618fe 100644 --- a/qse/lib/awk/StdAwk.cpp +++ b/qse/lib/awk/StdAwk.cpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.cpp 195 2009-06-10 13:18:25Z hyunghwan.chung $ + * $Id: StdAwk.cpp 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -65,19 +65,13 @@ int StdAwk::open () ADDFNC (QSE_T("srand"), 0, 1, &StdAwk::srand); ADDFNC (QSE_T("system"), 1, 1, &StdAwk::system); - return 0; -} - -int StdAwk::run (const char_t** args, size_t nargs) -{ qse_ntime_t now; if (qse_gettime(&now) == -1) this->seed = 0; else this->seed = (unsigned int)now; ::srand (this->seed); - - return Awk::run (args, nargs); + return 0; } int StdAwk::sin (Run& run, Return& ret, const Argument* args, size_t nargs, @@ -391,6 +385,346 @@ int StdAwk::flushFile (File& io) return qse_fio_flush ((qse_fio_t*)io.getHandle()); } +#if 0 +// console io handlers +int StdAwk::openConsole (Console& io) +{ + qse_sio_t* fp; + Console::Mode mode = io.getMode(); + + switch (mode) + { + case Console::READ: + { + if (runarg.ptr == QSE_NULL) + { + io.setHandle (qse_sio_in); + return 1; + } + else + { + qse_sio_t* sio; + const qse_char_t* file; + qse_awk_val_t* argv; + qse_map_t* map; + qse_map_pair_t* pair; + qse_char_t ibuf[128]; + qse_size_t ibuflen; + qse_awk_val_t* v; + qse_awk_rtx_valtostr_out_t out; + + nextfile: + file = runarg.ptr[runarg_index]; + + if (file == QSE_NULL) + { + /* no more input file */ + + if (runarg_count == 0) + { + /* all ARGVs are empty strings. + * so no console files were opened. + * open the standard input here. + * + * 'BEGIN { ARGV[1]=""; ARGV[2]=""; } + * { print $0; }' file1 file2 + */ + io.setHandle (qse_sio_in); + runarg_count++; + return 1; + } + + return 0; + } + + /* handle special case when ARGV[x] has been altered. + * so from here down, the file name gotten from + * rxtn->c.in.files is not important and is overridden + * from ARGV. + * 'BEGIN { ARGV[1]="file3"; } + * { print $0; }' file1 file2 + */ + argv = qse_awk_rtx_getgbl (rtx, QSE_AWK_GBL_ARGV); + QSE_ASSERT (argv != QSE_NULL); + QSE_ASSERT (argv->type == QSE_AWK_VAL_MAP); + + map = ((qse_awk_val_map_t*)argv)->map; + QSE_ASSERT (map != QSE_NULL); + + ibuflen = qse_awk_longtostr ( + rtx->awk, rxtn->c.in.index + 1, 10, QSE_NULL, + ibuf, QSE_COUNTOF(ibuf)); + + pair = qse_map_search (map, ibuf, ibuflen); + QSE_ASSERT (pair != QSE_NULL); + + v = QSE_MAP_VPTR(pair); + QSE_ASSERT (v != QSE_NULL); + + out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; + if (qse_awk_rtx_valtostr (rtx, v, &out) == QSE_NULL) return -1; + + if (out.u.cpldup.len == 0) + { + /* the name is empty */ + qse_awk_rtx_free (rtx, out.u.cpldup.ptr); + rxtn->c.in.index++; + goto nextfile; + } + + if (qse_strlen(out.u.cpldup.ptr) < out.u.cpldup.len) + { + /* the name contains one or more '\0' */ + qse_cstr_t errarg; + + errarg.ptr = out.u.cpldup.ptr; + /* use this length not to contains '\0' + * in an error message */ + errarg.len = qse_strlen(out.u.cpldup.ptr); + + qse_awk_rtx_seterror ( + rtx, QSE_AWK_EIONMNL, 0, &errarg); + + qse_awk_rtx_free (rtx, out.u.cpldup.ptr); + return -1; + } + + file = out.u.cpldup.ptr; + + if (file[0] == QSE_T('-') && file[1] == QSE_T('\0')) + { + /* special file name '-' */ + sio = qse_sio_in; + } + else + { + sio = qse_sio_open ( + rtx->awk->mmgr, 0, file, QSE_SIO_READ); + if (sio == QSE_NULL) + { + qse_cstr_t errarg; + + errarg.ptr = file; + errarg.len = qse_strlen(file); + + qse_awk_rtx_seterror ( + rtx, QSE_AWK_EOPEN, 0, &errarg); + + qse_awk_rtx_free (rtx, out.u.cpldup.ptr); + return -1; + } + } + + if (qse_awk_rtx_setfilename ( + rtx, file, qse_strlen(file)) == -1) + { + if (sio != qse_sio_in) qse_sio_close (sio); + qse_awk_rtx_free (rtx, out.u.cpldup.ptr); + return -1; + } + + qse_awk_rtx_free (rtx, out.u.cpldup.ptr); + riod->handle = sio; + + /* increment the counter of files successfully opened */ + rxtn->c.in.count++; + } + + rxtn->c.in.index++; + } + + break; + } + + case Console::WRITE: + break; + } + +#if 0 + FILE* fp = QSE_NULL; + const char_t* fn = QSE_NULL; + + switch (mode) + { + case StdAwk::Console::READ: + + if (numConInFiles == 0) fp = stdin; + else + { + fn = conInFile[0]; + fp = qse_fopen (fn, QSE_T("r")); + } + break; + + case StdAwk::Console::WRITE: + + if (numConOutFiles == 0) fp = stdout; + else + { + fn = conOutFile[0]; + fp = qse_fopen (fn, QSE_T("w")); + } + break; + } + + if (fp == NULL) return -1; + + ConTrack* t = (ConTrack*) + qse_awk_alloc (awk, QSE_SIZEOF(ConTrack)); + if (t == QSE_NULL) + { + if (fp != stdin && fp != stdout) fclose (fp); + return -1; + } + + t->handle = fp; + t->nextConIdx = 1; + + if (fn != QSE_NULL) + { + if (io.setFileName(fn) == -1) + { + if (fp != stdin && fp != stdout) fclose (fp); + qse_awk_free (awk, t); + return -1; + } + } + + io.setHandle (t); + return 1; +#endif +} + +int StdAwk::closeConsole (Console& io) +{ + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + + if (fp == stdout || fp == stderr) fflush (fp); + if (fp != stdin && fp != stdout && fp != stderr) fclose (fp); + + qse_awk_free (awk, t); + return 0; +} + +ssize_t StdAwk::readConsole (Console& io, char_t* buf, size_t len) +{ + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + ssize_t n = 0; + + while (n < (ssize_t)len) + { + qse_cint_t c = qse_fgetc (fp); + if (c == QSE_CHAR_EOF) + { + if (qse_ferror(fp)) return -1; + if (t->nextConIdx >= numConInFiles) break; + + const char_t* fn = conInFile[t->nextConIdx]; + FILE* nfp = qse_fopen (fn, QSE_T("r")); + if (nfp == QSE_NULL) return -1; + + if (io.setFileName(fn) == -1 || io.setFNR(0) == -1) + { + fclose (nfp); + return -1; + } + + fclose (fp); + fp = nfp; + t->nextConIdx++; + t->handle = fp; + + if (n == 0) continue; + else break; + } + + buf[n++] = c; + if (c == QSE_T('\n')) break; + } + + return n; +} + +ssize_t StdAwk::writeConsole (Console& io, const char_t* buf, size_t len) +{ + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + size_t left = len; + + while (left > 0) + { + if (*buf == QSE_T('\0')) + { + if (qse_fputc(*buf,fp) == QSE_CHAR_EOF) return -1; + left -= 1; buf += 1; + } + else + { + int chunk = (left > QSE_TYPE_MAX(int))? QSE_TYPE_MAX(int): (int)left; + int n = qse_fprintf (fp, QSE_T("%.*s"), chunk, buf); + if (n < 0 || n > chunk) return -1; + left -= n; buf += n; + } + } + + return len; +} + +int StdAwk::flushConsole (Console& io) +{ + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* fp = t->handle; + return ::fflush (fp); +} + +int StdAwk::nextConsole (Console& io) +{ + StdAwk::Console::Mode mode = io.getMode(); + + ConTrack* t = (ConTrack*)io.getHandle(); + FILE* ofp = t->handle; + FILE* nfp = QSE_NULL; + const char_t* fn = QSE_NULL; + + switch (mode) + { + case StdAwk::Console::READ: + + if (t->nextConIdx >= numConInFiles) return 0; + fn = conInFile[t->nextConIdx]; + nfp = qse_fopen (fn, QSE_T("r")); + break; + + case StdAwk::Console::WRITE: + + if (t->nextConIdx >= numConOutFiles) return 0; + fn = conOutFile[t->nextConIdx]; + nfp = qse_fopen (fn, QSE_T("w")); + break; + } + + if (nfp == QSE_NULL) return -1; + + if (fn != QSE_NULL) + { + if (io.setFileName (fn) == -1) + { + fclose (nfp); + return -1; + } + } + + fclose (ofp); + + t->nextConIdx++; + t->handle = nfp; + + return 1; +} +#endif + // memory allocation primitives void* StdAwk::allocMem (size_t n) throw () { diff --git a/qse/lib/awk/err.c b/qse/lib/awk/err.c index ac8db27b..652f909f 100644 --- a/qse/lib/awk/err.c +++ b/qse/lib/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c 214 2009-06-27 02:50:54Z hyunghwan.chung $ + * $Id: err.c 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -29,17 +29,9 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum) QSE_T("insufficient memory"), QSE_T("not supported"), QSE_T("operation not allowed"), - QSE_T("no such device"), - QSE_T("no space left on device"), - QSE_T("too many open files"), - QSE_T("too many links"), - QSE_T("resource temporarily unavailable"), - QSE_T("'${0}' not existing"), + QSE_T("'${0}' not found"), QSE_T("'${0}' already exists"), - QSE_T("file or data too big"), - QSE_T("system too busy"), - QSE_T("is a directory"), - QSE_T("IO error"), + QSE_T("I/O error"), QSE_T("cannot open '${0}'"), QSE_T("cannot read '${0}'"), @@ -49,43 +41,43 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum) QSE_T("internal error that should never have happened"), QSE_T("general runtime error"), QSE_T("block nested too deeply"), - QSE_T("expressio nested too deeply"), + QSE_T("expression nested too deeply"), - QSE_T("cannot open source input"), - QSE_T("cannot close source input"), - QSE_T("cannot read source input"), + QSE_T("failed to open source input"), + QSE_T("failed to close source input"), + QSE_T("failed to read source input"), - QSE_T("cannot open source output"), - QSE_T("cannot close source output"), - QSE_T("cannot write source output"), + QSE_T("failed to open source output"), + QSE_T("failed to close source output"), + QSE_T("failed to write source output"), QSE_T("invalid character '${0}'"), QSE_T("invalid digit '${0}'"), - QSE_T("cannot unget character"), + QSE_T("failed to unget character"), QSE_T("unexpected end of source"), - QSE_T("a comment not closed properly"), - QSE_T("a string or a regular expression not closed"), - QSE_T("unexpected end of a regular expression"), - QSE_T("a left brace expected in place of '${0}'"), - QSE_T("a left parenthesis expected in place of '${0}'"), - QSE_T("a right parenthesis expected in place of '${0}'"), - QSE_T("a right bracket expected in place of '${0}'"), - QSE_T("a comma expected in place of '${0}'"), - QSE_T("a semicolon expected in place of '${0}'"), - QSE_T("a colon expected in place of '${0}'"), + QSE_T("comment not closed properly"), + QSE_T("string or regular expression not closed"), + QSE_T("unexpected end of regular expression"), + QSE_T("left brace expected in place of '${0}'"), + QSE_T("left parenthesis expected in place of '${0}'"), + QSE_T("right parenthesis expected in place of '${0}'"), + QSE_T("right bracket expected in place of '${0}'"), + QSE_T("comma expected in place of '${0}'"), + QSE_T("semicolon expected in place of '${0}'"), + QSE_T("colon expected in place of '${0}'"), QSE_T("statement not ending with a semicolon"), QSE_T("'in' expected in place of '${0}'"), - QSE_T("right-hand side of the 'in' operator not a variable"), + QSE_T("right-hand side of 'in' not a variable"), QSE_T("invalid expression"), - QSE_T("keyword 'function' expected in place of '${0}'"), - QSE_T("keyword 'while' expected in place of '${0}'"), + QSE_T("'function' expected in place of '${0}'"), + QSE_T("'while' expected in place of '${0}'"), QSE_T("invalid assignment statement"), - QSE_T("an identifier expected in place of '${0}'"), + QSE_T("identifier expected in place of '${0}'"), QSE_T("'${0}' not a valid function name"), - QSE_T("BEGIN not followed by a left bracket on the same line"), - QSE_T("END not followed by a left bracket on the same line"), + QSE_T("BEGIN not followed by left bracket on the same line"), + QSE_T("END not followed by left bracket on the same line"), QSE_T("duplicate BEGIN"), QSE_T("duplicate END"), QSE_T("keyword '${0}' redefined"), @@ -105,15 +97,15 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum) QSE_T("too many global variables"), QSE_T("too many local variables"), QSE_T("too many parameters"), - QSE_T("delete statement not followed by a normal variable"), - QSE_T("reset statement not followed by a normal variable"), - QSE_T("break statement outside a loop"), - QSE_T("continue statement outside a loop"), - QSE_T("next statement illegal in the BEGIN block"), - QSE_T("next statement illegal in the END block"), - QSE_T("nextfile statement illegal in the BEGIN block"), - QSE_T("nextfile statement illegal in the END block"), - QSE_T("printf not followed by any arguments"), + QSE_T("'delete' not followed by variable"), + QSE_T("'reset' not followed by variable"), + QSE_T("'break' outside a loop"), + QSE_T("'continue' outside a loop"), + QSE_T("'next' illegal in the BEGIN block"), + QSE_T("'next' illegal in the END block"), + QSE_T("'nextfile' illegal in the BEGIN block"), + QSE_T("'nextfile' illegal in the END block"), + QSE_T("'printf' not followed by argument"), QSE_T("both prefix and postfix increment/decrement operator present"), QSE_T("divide by zero"), @@ -133,21 +125,21 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum) QSE_T("a positional value cannot be assigned a map"), QSE_T("map '${0}' not assignable with a scalar"), QSE_T("cannot change a scalar value to a map"), - QSE_T("a map is not allowed"), + QSE_T("map not allowed"), QSE_T("invalid value type"), - QSE_T("delete statement called with a wrong target"), - QSE_T("reset statement called with a wrong target"), - QSE_T("next statement called from the BEGIN block"), - QSE_T("next statement called from the END block"), - QSE_T("nextfile statement called from the BEGIN block"), - QSE_T("nextfile statement called from the END block"), + QSE_T("'delete' called with wrong target"), + QSE_T("'reset' called with wrong target"), + QSE_T("'next' called from BEGIN block"), + QSE_T("'next' called from END block"), + QSE_T("'nextfile' called from BEGIN block"), + QSE_T("'nextfile' called from END block"), QSE_T("wrong implementation of intrinsic function handler"), QSE_T("intrinsic function handler returned an error"), QSE_T("wrong implementation of user-defined io handler"), - QSE_T("IO handler returned an error"), - QSE_T("no such IO name found"), - QSE_T("IO name empty"), - QSE_T("IO name '${0}' containing a null character"), + QSE_T("I/O handler returned an error"), + QSE_T("no such I/O name found"), + QSE_T("I/O name empty"), + QSE_T("I/O name '${0}' containing '\\0'"), QSE_T("not sufficient arguments to formatting sequence"), QSE_T("recursion detected in format conversion"), QSE_T("invalid character in CONVFMT"), diff --git a/qse/lib/awk/misc.c b/qse/lib/awk/misc.c index 9c030b12..8c7c0dae 100644 --- a/qse/lib/awk/misc.c +++ b/qse/lib/awk/misc.c @@ -1,5 +1,5 @@ /* - * $Id: misc.c 219 2009-06-30 13:14:39Z hyunghwan.chung $ + * $Id: misc.c 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -23,6 +23,11 @@ void* qse_awk_alloc (qse_awk_t* awk, qse_size_t size) return QSE_AWK_ALLOC (awk, size); } +void* qse_awk_realloc (qse_awk_t* awk, void* ptr, qse_size_t size) +{ + return QSE_AWK_REALLOC (awk, ptr, size); +} + void qse_awk_free (qse_awk_t* awk, void* ptr) { QSE_AWK_FREE (awk, ptr); diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index 8d8036f7..666bc34f 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c 218 2009-06-29 10:17:39Z hyunghwan.chung $ + * $Id: parse.c 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -553,7 +553,7 @@ static int parse (qse_awk_t* awk) QSE_MAP_KPTR(p), QSE_MAP_KLEN(p)) == QSE_NULL) { /* TODO: set better error no & line */ - SETERRARG (awk, QSE_AWK_EFUNNONE, + SETERRARG (awk, QSE_AWK_EFUNNF, *(qse_size_t*)QSE_MAP_VPTR(p), QSE_MAP_KPTR(p), QSE_MAP_KLEN(p)); diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 2c0b761f..1650dae9 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c 213 2009-06-26 13:05:19Z hyunghwan.chung $ + * $Id: run.c 220 2009-07-01 13:14:39Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -1322,7 +1322,7 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) if (rtx->rcb.on_loop_enter != QSE_NULL) { qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOERR); - ret = rtx->rcb.on_loop_enter (rtx, rtx->rcb.data); + ret = rtx->rcb.on_loop_enter (rtx, rtx->rcb.udd); if (ret <= -1) { if (rtx->errinf.num == QSE_AWK_ENOMEM) @@ -1426,7 +1426,7 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) /* we call the on_exit handler regardless of ret. * the return value passed is the global return value * in the stack. */ - rtx->rcb.on_loop_exit (rtx, v, rtx->rcb.data); + rtx->rcb.on_loop_exit (rtx, v, rtx->rcb.udd); } /* end the life of the global return value */ @@ -1498,7 +1498,7 @@ qse_awk_val_t* qse_awk_rtx_call ( errarg.ptr = call.what.fun.name.ptr; errarg.len = call.what.fun.name.len; - qse_awk_rtx_seterror (rtx, QSE_AWK_EFUNNONE, 0, &errarg); + qse_awk_rtx_seterror (rtx, QSE_AWK_EFUNNF, 0, &errarg); return QSE_NULL; } @@ -1542,17 +1542,6 @@ qse_awk_val_t* qse_awk_rtx_call ( qse_awk_rtx_refupval (rtx, v); } -#if 0 - if (rtx->rcb.on_loop_exit != QSE_NULL) - { - rtx->rcb.on_loop_exit ( - rtx, - ((v == QSE_NULL)? qse_awk_val_nil: v), - rtx->rcb.data - ); - } -#endif - /* return the return value with its reference count at least 1. * the caller of this function should count down its reference. */ return v; @@ -1844,7 +1833,7 @@ static int run_block0 (qse_awk_rtx_t* run, qse_awk_nde_blk_t* nde) if ((rtx)->rcb.on_statement != QSE_NULL) \ { \ (rtx)->rcb.on_statement ( \ - rtx, (nde)->line, (rtx)->rcb.data); \ + rtx, (nde)->line, (rtx)->rcb.udd); \ } static int run_statement (qse_awk_rtx_t* run, qse_awk_nde_t* nde) @@ -5520,7 +5509,7 @@ static qse_awk_val_t* eval_fun_ex ( errarg.len = call->what.fun.name.len, qse_awk_rtx_seterror (run, - QSE_AWK_EFUNNONE, nde->line, &errarg); + QSE_AWK_EFUNNF, nde->line, &errarg); return QSE_NULL; } diff --git a/qse/regress/awk/regress.out b/qse/regress/awk/regress.out index e8853ac2..cd7f4a0b 100644 --- a/qse/regress/awk/regress.out +++ b/qse/regress/awk/regress.out @@ -937,7 +937,7 @@ my hello my hello my hello my hello -ERROR: CODE [23] LINE [6] block nested too deeply +ERROR: CODE [15] LINE [6] block nested too deeply -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-003.awk &1 -------------------------------------------------------------------------------- @@ -956,7 +956,7 @@ BEGIN { -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-004.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [60] LINE [3] function 'a' redefined +ERROR: CODE [52] LINE [3] function 'a' redefined -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --implicit=off --explicit=on --newline=on -o- -f lang-005.awk &1 -------------------------------------------------------------------------------- @@ -984,7 +984,7 @@ BEGIN { -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --implicit=off --explicit=on --newline=on -o- -f lang-006.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [61] LINE [5] global variable 'a' redefined +ERROR: CODE [53] LINE [5] global variable 'a' redefined -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --implicit=on --explicit=on --newline=on -o- -f lang-007.awk &1 -------------------------------------------------------------------------------- @@ -1352,7 +1352,7 @@ BEGIN { printf ("%s\n",10.34); } -ERROR: CODE [118] LINE [3] recursion detected in format conversion +ERROR: CODE [110] LINE [3] recursion detected in format conversion -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-014.awk &1 -------------------------------------------------------------------------------- @@ -1367,7 +1367,7 @@ BEGIN { -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-015.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [23] LINE [3] block nested too deeply +ERROR: CODE [15] LINE [3] block nested too deeply -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-016.awk &1 -------------------------------------------------------------------------------- @@ -1481,27 +1481,27 @@ END { -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-018.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [65] LINE [1] duplicate global variable 'ARGV' +ERROR: CODE [57] LINE [1] duplicate global variable 'ARGV' -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-019.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [67] LINE [1] '+' not a valid parameter name +ERROR: CODE [59] LINE [1] '+' not a valid parameter name -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-020.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [68] LINE [1] '+' not a valid variable name +ERROR: CODE [60] LINE [1] '+' not a valid variable name -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-021.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [68] LINE [3] '+' not a valid variable name +ERROR: CODE [60] LINE [3] '+' not a valid variable name -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-022.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [39] LINE [2] a left parenthesis expected in place of '=' +ERROR: CODE [31] LINE [2] left parenthesis expected in place of '=' -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-023.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [44] LINE [5] a colon expected in place of ';' +ERROR: CODE [36] LINE [5] colon expected in place of ';' -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-024.awk &1 -------------------------------------------------------------------------------- @@ -1520,7 +1520,7 @@ BEGIN { delete iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix; } -ERROR: CODE [92] LINE [3] variable 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix' not deletable +ERROR: CODE [84] LINE [3] variable 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix' not deletable -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-026.awk &1 -------------------------------------------------------------------------------- @@ -1532,19 +1532,19 @@ BEGIN { } abc -ERROR: CODE [100] LINE [4] map 'abc' not assignable with a scalar +ERROR: CODE [92] LINE [4] map 'abc' not assignable with a scalar -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-027.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [31] LINE [2] invalid character '' +ERROR: CODE [23] LINE [2] invalid character '' -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-028.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [59] LINE [2] intrinsic function 'substr' redefined +ERROR: CODE [51] LINE [2] intrinsic function 'substr' redefined -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-029.awk &1 -------------------------------------------------------------------------------- -ERROR: CODE [60] LINE [9] function 'abc' redefined +ERROR: CODE [52] LINE [9] function 'abc' redefined -------------------------------------------------------------------------------- ../../cmd/awk/qseawk --newline=on -o- -f lang-030.awk &1 -------------------------------------------------------------------------------- diff --git a/qse/regress/awk/regress.sh b/qse/regress/awk/regress.sh index d36d7e1d..155b2075 100755 --- a/qse/regress/awk/regress.sh +++ b/qse/regress/awk/regress.sh @@ -183,6 +183,7 @@ run_scripts() case $1 in init) run_scripts > "${OUTFILE}" + echo_so "INIT OK" ;; test) run_scripts > "${OUTFILE}.temp" @@ -192,6 +193,7 @@ test) exit 1 } rm -f "${OUTFILE}.temp" + echo_so "TEST OK" ;; *) echo_so "USAGE: $0 init" diff --git a/qse/samples/awk/awk05.cpp b/qse/samples/awk/awk05.cpp index 76e9625f..97bb3799 100644 --- a/qse/samples/awk/awk05.cpp +++ b/qse/samples/awk/awk05.cpp @@ -70,7 +70,7 @@ public: #endif int n = StdAwk::open (); - if (n == -1) + if (n <= -1) { #ifdef _WIN32 HeapDestroy (heap); @@ -80,16 +80,16 @@ public: } idLastSleep = addGlobal (QSE_T("LAST_SLEEP")); - if (idLastSleep == -1) goto failure; + if (idLastSleep <= -1) goto failure; if (addFunction (QSE_T("sleep"), 1, 1, - (FunctionHandler)&TestAwk::sleep) == -1) goto failure; + (FunctionHandler)&TestAwk::sleep) <= -1) goto failure; if (addFunction (QSE_T("sumintarray"), 1, 1, - (FunctionHandler)&TestAwk::sumintarray) == -1) goto failure; + (FunctionHandler)&TestAwk::sumintarray) <= -1) goto failure; if (addFunction (QSE_T("arrayindices"), 1, 1, - (FunctionHandler)&TestAwk::arrayindices) == -1) goto failure; + (FunctionHandler)&TestAwk::arrayindices) <= -1) goto failure; return 0; failure: @@ -135,7 +135,7 @@ public: else { qse_printf (QSE_T("BAD:\n")); } */ - if (run.setGlobal (idLastSleep, x) == -1) return -1; + if (run.setGlobal (idLastSleep, x) <= -1) return -1; #ifdef _WIN32 ::Sleep ((DWORD)(x * 1000)); @@ -160,7 +160,7 @@ public: size_t len; const char_t* ptr = idx.toStr(&len); - if (args[0].getIndexed(ptr, len, val) == -1) return -1; + if (args[0].getIndexed(ptr, len, val) <= -1) return -1; x += val.toInt (); n = args[0].getNextIndex (idx); @@ -186,7 +186,7 @@ public: size_t len; const char_t* ptr = idx.toStr(&len); n = args[0].getNextIndex (idx); - if (ret.setIndexed (i, ptr, len) == -1) return -1; + if (ret.setIndexed (i, ptr, len) <= -1) return -1; } if (n != 0) return -1; @@ -377,7 +377,7 @@ protected: if (fn != QSE_NULL) { - if (io.setFileName(fn) == -1) + if (io.setFileName(fn) <= -1) { if (fp != stdin && fp != stdout) fclose (fp); qse_awk_free (awk, t); @@ -419,7 +419,7 @@ protected: FILE* nfp = qse_fopen (fn, QSE_T("r")); if (nfp == QSE_NULL) return -1; - if (io.setFileName(fn) == -1 || io.setFNR(0) == -1) + if (io.setFileName(fn) <= -1 || io.setFNR(0) <= -1) { fclose (nfp); return -1; @@ -503,7 +503,7 @@ protected: if (fn != QSE_NULL) { - if (io.setFileName (fn) == -1) + if (io.setFileName (fn) <= -1) { fclose (nfp); return -1; @@ -705,7 +705,7 @@ static int awk_main (int argc, qse_char_t* argv[]) qse_size_t nsrcins = 0; qse_size_t nsrcouts = 0; - if (awk.open() == -1) + if (awk.open() <= -1) { qse_fprintf (stderr, QSE_T("cannot open awk\n")); return -1; @@ -796,7 +796,7 @@ static int awk_main (int argc, qse_char_t* argv[]) } else if (mode == 3) // console input { - if (awk.addConsoleInput (argv[i]) == -1) + if (awk.addConsoleInput (argv[i]) <= -1) { print_error (QSE_T("too many console inputs")); return -1; @@ -806,7 +806,7 @@ static int awk_main (int argc, qse_char_t* argv[]) } else if (mode == 4) // console output { - if (awk.addConsoleOutput (argv[i]) == -1) + if (awk.addConsoleOutput (argv[i]) <= -1) { print_error (QSE_T("too many console outputs")); return -1; @@ -855,7 +855,7 @@ static int awk_main (int argc, qse_char_t* argv[]) return -1; } - if (awk.parse (srcin, srcout) == -1) + if (awk.parse (srcin, srcout) <= -1) { qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"), awk.getErrorLine(), awk.getErrorMessage()); @@ -866,7 +866,20 @@ static int awk_main (int argc, qse_char_t* argv[]) awk.enableRunCallback (); app_awk = &awk; - if (awk.run (args, nargs) == -1) + for (qse_size_t i = 0; i < nargs; i++) + { + if (awk.addArgument (args[i]) <= -1) + { + qse_fprintf (stderr, + QSE_T("ERROR: %s\n"), + awk.getErrorMessage() + ); + awk.close (); + return -1; + } + } + + if (awk.loop () <= -1) { qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"), awk.getErrorLine(), awk.getErrorMessage());