diff --git a/qse/include/qse/awk/Awk.hpp b/qse/include/qse/awk/Awk.hpp index 8655b39e..d5e57bd7 100644 --- a/qse/include/qse/awk/Awk.hpp +++ b/qse/include/qse/awk/Awk.hpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.hpp 249 2009-08-07 13:35:24Z hyunghwan.chung $ + * $Id: Awk.hpp 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -275,17 +275,15 @@ public: * The Awk::Source::Data class is used to deliver information * needed for source script I/O. */ - class Data: protected qse_awk_sio_arg_t + class Data: protected sio_arg_t { public: friend class Awk; protected: - Data (Awk* awk, Mode mode): - awk (awk), mode (mode) + Data (Awk* awk, Mode mode, sio_arg_t* arg): + awk (awk), mode (mode), arg (arg) { - this->name = QSE_NULL; - this->handle = QSE_NULL; } public: @@ -296,17 +294,17 @@ public: const char_t* getName() const { - return this->name; + return arg->name; } const void* getHandle () const { - return this->handle; + return arg->handle; } void setHandle (void* handle) { - this->handle = handle; + arg->handle = handle; } operator Awk* () const @@ -322,6 +320,7 @@ public: protected: Awk* awk; Mode mode; + sio_arg_t* arg; }; Source () {} @@ -1090,9 +1089,6 @@ protected: map_t* functionMap; - Source::Data sourceIn; - Source::Data sourceOut; - Source* sourceReader; Source* sourceWriter; diff --git a/qse/include/qse/awk/StdAwk.hpp b/qse/include/qse/awk/StdAwk.hpp index 3fa921dc..7d5d8137 100644 --- a/qse/include/qse/awk/StdAwk.hpp +++ b/qse/include/qse/awk/StdAwk.hpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.hpp 235 2009-07-15 10:43:31Z hyunghwan.chung $ + * $Id: StdAwk.hpp 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -45,7 +45,10 @@ public: class SourceFile: public Source { public: - SourceFile (const char_t* name): name (name) {} + SourceFile (const char_t* name): name (name) + { + dir.ptr = QSE_NULL; dir.len = 0; + } int open (Data& io); int close (Data& io); @@ -54,6 +57,7 @@ public: protected: const char_t* name; + qse_cstr_t dir; }; class SourceString: public Source diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 11b93190..b64b2859 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h 249 2009-08-07 13:35:24Z hyunghwan.chung $ + * $Id: awk.h 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -271,12 +271,21 @@ enum qse_awk_sio_cmd_t }; typedef enum qse_awk_sio_cmd_t qse_awk_sio_cmd_t; +typedef struct qse_awk_sio_lxc_t qse_awk_sio_lxc_t; +struct qse_awk_sio_lxc_t +{ + qse_cint_t c; + qse_size_t lin; + qse_size_t col; + const qse_char_t* file; +}; + struct qse_awk_sio_arg_t { const qse_char_t* name; /**< [IN] name of I/O object */ void* handle; /**< [OUT] I/O handle set by a handler */ - /*-- from here down, internal use only --*/ + /*-- from here down, internal use only --*/ struct { qse_char_t buf[1024]; @@ -287,6 +296,7 @@ struct qse_awk_sio_arg_t qse_size_t lin; qse_size_t col; + qse_awk_sio_lxc_t last; struct qse_awk_sio_arg_t* next; }; typedef struct qse_awk_sio_arg_t qse_awk_sio_arg_t; diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index 42482042..aa1d0d63 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp 249 2009-08-07 13:35:24Z hyunghwan.chung $ + * $Id: Awk.cpp 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -995,9 +995,7 @@ int Awk::Run::getGlobal (int id, Value& g) const // Awk ////////////////////////////////////////////////////////////////// -Awk::Awk () : awk (QSE_NULL), functionMap (QSE_NULL), - sourceIn (this, Source::READ), sourceOut (this, Source::WRITE), - runctx (this) +Awk::Awk () : awk (QSE_NULL), functionMap (QSE_NULL), runctx (this) { errinf.num = (errnum_t)ERR_NOERR; @@ -1608,16 +1606,16 @@ Awk::ssize_t Awk::readSource ( char_t* data, size_t count) { xtn_t* xtn = (xtn_t*) QSE_XTN (awk); + Source::Data sdat (xtn->awk, Source::READ, arg); switch (cmd) { case QSE_AWK_SIO_OPEN: - xtn->awk->sourceIn.name = arg->name; - return xtn->awk->sourceReader->open (xtn->awk->sourceIn); + return xtn->awk->sourceReader->open (sdat); case QSE_AWK_SIO_CLOSE: - return xtn->awk->sourceReader->close (xtn->awk->sourceIn); + return xtn->awk->sourceReader->close (sdat); case QSE_AWK_SIO_READ: - return xtn->awk->sourceReader->read (xtn->awk->sourceIn, data, count); + return xtn->awk->sourceReader->read (sdat, data, count); default: return -1; } @@ -1628,16 +1626,16 @@ Awk::ssize_t Awk::writeSource ( char_t* data, size_t count) { xtn_t* xtn = (xtn_t*) QSE_XTN (awk); + Source::Data sdat (xtn->awk, Source::WRITE, arg); switch (cmd) { case QSE_AWK_SIO_OPEN: - xtn->awk->sourceOut.name = arg->name; - return xtn->awk->sourceWriter->open (xtn->awk->sourceOut); + return xtn->awk->sourceWriter->open (sdat); case QSE_AWK_SIO_CLOSE: - return xtn->awk->sourceWriter->close (xtn->awk->sourceOut); + return xtn->awk->sourceWriter->close (sdat); case QSE_AWK_SIO_WRITE: - return xtn->awk->sourceWriter->write (xtn->awk->sourceOut, data, count); + return xtn->awk->sourceWriter->write (sdat, data, count); default: return -1; } diff --git a/qse/lib/awk/StdAwk.cpp b/qse/lib/awk/StdAwk.cpp index e6690b06..965d9a9d 100644 --- a/qse/lib/awk/StdAwk.cpp +++ b/qse/lib/awk/StdAwk.cpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.cpp 241 2009-07-22 12:47:13Z hyunghwan.chung $ + * $Id: StdAwk.cpp 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -778,22 +778,78 @@ int StdAwk::vsprintf ( int StdAwk::SourceFile::open (Data& io) { qse_sio_t* sio; + const qse_char_t* ioname = io.getName(); - if (name[0] == QSE_T('-') && - name[1] == QSE_T('\0')) + if (ioname == QSE_NULL) { - sio = (io.getMode() == READ)? qse_sio_in: qse_sio_out; + if (name[0] == QSE_T('-') && name[1] == QSE_T('\0')) + { + sio = (io.getMode() == READ)? qse_sio_in: qse_sio_out; + } + else + { + const qse_char_t* base; + + sio = qse_sio_open ( + ((awk_t*)io)->mmgr, + 0, + name, + (io.getMode() == READ? + QSE_SIO_READ: + (QSE_SIO_WRITE|QSE_SIO_CREATE|QSE_SIO_TRUNCATE)) + ); + if (sio == QSE_NULL) return -1; + + base = qse_awk_basename ((awk_t*)io, name); + if (base != name) + { + dir.ptr = name; + dir.len = base - name; + } + } } else { + const char_t* file = name; + char_t fbuf[64]; + char_t* dbuf = QSE_NULL; + + if (dir.len > 0) + { + size_t tmplen, totlen; + + totlen = qse_strlen(ioname) + dir.len; + if (totlen >= QSE_COUNTOF(fbuf)) + { + dbuf = (qse_char_t*) QSE_MMGR_ALLOC ( + ((awk_t*)io)->mmgr, + QSE_SIZEOF(qse_char_t) * (totlen + 1) + ); + if (dbuf == QSE_NULL) + { + ((Awk*)io)->setError (ERR_NOMEM); + return -1; + } + + file = dbuf; + } + else file = fbuf; + + tmplen = qse_strncpy ( + (char_t*)file, dir.ptr, dir.len); + qse_strcpy ((char_t*)file + tmplen, ioname); + } + sio = qse_sio_open ( ((awk_t*)io)->mmgr, 0, - name, + file, (io.getMode() == READ? QSE_SIO_READ: (QSE_SIO_WRITE|QSE_SIO_CREATE|QSE_SIO_TRUNCATE)) ); + + if (dbuf != QSE_NULL) QSE_MMGR_FREE (((awk_t*)io)->mmgr, dbuf); if (sio == QSE_NULL) return -1; } @@ -827,27 +883,67 @@ StdAwk::ssize_t StdAwk::SourceFile::write (Data& io, char_t* buf, size_t len) int StdAwk::SourceString::open (Data& io) { - /* SourceString does not support writing */ - if (io.getMode() == WRITE) return -1; - ptr = str; + qse_sio_t* sio; + const char_t* ioname = io.getName(); + + if (ioname == QSE_NULL) + { + /* SourceString does not support writing */ + if (io.getMode() == WRITE) return -1; + ptr = str; + } + else + { + /* open an included file */ + sio = qse_sio_open ( + ((awk_t*)io)->mmgr, + 0, + ioname, + (io.getMode() == READ? + QSE_SIO_READ: + (QSE_SIO_WRITE|QSE_SIO_CREATE|QSE_SIO_TRUNCATE)) + ); + if (sio == QSE_NULL) return -1; + io.setHandle (sio); + } + return 1; } int StdAwk::SourceString::close (Data& io) { + if (io.getName() != QSE_NULL) + qse_sio_close ((qse_sio_t*)io.getHandle()); + return 0; } StdAwk::ssize_t StdAwk::SourceString::read (Data& io, char_t* buf, size_t len) { - qse_size_t n = 0; - while (*ptr != QSE_T('\0') && n < len) buf[n++] = *ptr++; - return n; + if (io.getName() == QSE_NULL) + { + qse_size_t n = 0; + while (*ptr != QSE_T('\0') && n < len) buf[n++] = *ptr++; + return n; + } + else + { + return qse_sio_getsn ((qse_sio_t*)io.getHandle(), buf, len); + } } StdAwk::ssize_t StdAwk::SourceString::write (Data& io, char_t* buf, size_t len) { - return -1; + if (io.getName() == QSE_NULL) + { + return -1; + } + else + { + // in fact, this block will never be reached as + // there is no included file concept for deparsing + return qse_sio_putsn ((qse_sio_t*)io.getHandle(), buf, len); + } } ///////////////////////////////// diff --git a/qse/lib/awk/awk.h b/qse/lib/awk/awk.h index a9d989ed..e392fd92 100644 --- a/qse/lib/awk/awk.h +++ b/qse/lib/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h 248 2009-08-06 08:27:14Z hyunghwan.chung $ + * $Id: awk.h 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -106,15 +106,6 @@ struct qse_awk_token_t qse_size_t col; }; -typedef struct qse_awk_lxc_t qse_awk_lxc_t; -struct qse_awk_lxc_t -{ - qse_cint_t c; - qse_size_t lin; - qse_size_t col; - const qse_char_t* file; -}; - struct qse_awk_t { QSE_DEFINE_COMMON_FIELDS (sed) @@ -186,10 +177,10 @@ struct qse_awk_t qse_awk_sio_fun_t inf; qse_awk_sio_fun_t outf; - qse_awk_lxc_t last; + qse_awk_sio_lxc_t last; qse_size_t nungots; - qse_awk_lxc_t ungot[5]; + qse_awk_sio_lxc_t ungot[5]; qse_awk_sio_arg_t arg; /* for the top level source */ qse_awk_sio_arg_t* inp; /* current input */ diff --git a/qse/lib/awk/misc.c b/qse/lib/awk/misc.c index 44e00ab8..2d4379d1 100644 --- a/qse/lib/awk/misc.c +++ b/qse/lib/awk/misc.c @@ -1,5 +1,5 @@ /* - * $Id: misc.c 237 2009-07-16 12:43:47Z hyunghwan.chung $ + * $Id: misc.c 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -999,3 +999,17 @@ void qse_awk_rtx_free (qse_awk_rtx_t* rtx, void* ptr) qse_awk_free (rtx->awk, ptr); } +const qse_char_t* qse_awk_basename (qse_awk_t* awk, const qse_char_t* path) +{ + const qse_char_t* p, * last = QSE_NULL; + + for (p = path; *p != QSE_T('\0'); p++) + { + if (*p == QSE_T('/')) last = p; +#ifdef _WIN32 + else if (*p == QSE_T('\\')) last = p; +#endif + } + + return (last == QSE_NULL)? path: (last + 1); +} diff --git a/qse/lib/awk/misc.h b/qse/lib/awk/misc.h index 314351c8..960a2035 100644 --- a/qse/lib/awk/misc.h +++ b/qse/lib/awk/misc.h @@ -1,5 +1,5 @@ /* - * $Id: misc.h 171 2009-06-01 09:34:34Z hyunghwan.chung $ + * $Id: misc.h 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -67,6 +67,11 @@ int qse_awk_matchrex ( qse_cstr_t* match, qse_awk_errnum_t* errnum ); +const qse_char_t* qse_awk_basename ( + qse_awk_t* awk, + const qse_char_t* path +); + #ifdef __cplusplus } #endif diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index 127778cb..ba5df580 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c 248 2009-08-06 08:27:14Z hyunghwan.chung $ + * $Id: parse.c 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -398,11 +398,7 @@ static int get_char (qse_awk_t* awk) if (awk->sio.nungots > 0) { /* there are something in the unget buffer */ - QSE_MEMCPY ( - &awk->sio.last, - &awk->sio.ungot[--awk->sio.nungots], - QSE_SIZEOF(awk->sio.last) - ); + awk->sio.last = awk->sio.ungot[--awk->sio.nungots]; return 0; } @@ -433,31 +429,28 @@ static int get_char (qse_awk_t* awk) awk->sio.inp->b.len = n; } - awk->sio.last.c = awk->sio.inp->b.buf[awk->sio.inp->b.pos++]; - awk->sio.last.lin = awk->sio.inp->lin; - awk->sio.last.col = awk->sio.inp->col; - awk->sio.last.file = awk->sio.inp->name; + awk->sio.inp->last.c = awk->sio.inp->b.buf[awk->sio.inp->b.pos++]; + awk->sio.inp->last.lin = awk->sio.inp->lin; + awk->sio.inp->last.col = awk->sio.inp->col; + awk->sio.inp->last.file = awk->sio.inp->name; - if (awk->sio.last.c == QSE_T('\n')) + if (awk->sio.inp->last.c == QSE_T('\n')) { awk->sio.inp->lin++; awk->sio.inp->col = 1; } else awk->sio.inp->col++; + awk->sio.last = awk->sio.inp->last; return 0; } -static void unget_char (qse_awk_t* awk, const qse_awk_lxc_t* c) +static void unget_char (qse_awk_t* awk, const qse_awk_sio_lxc_t* c) { /* Make sure that the unget buffer is large enough */ QSE_ASSERTX (awk->sio.nungots < QSE_COUNTOF(awk->sio.ungot), "Make sure that you have increased the size of sio.ungot large enough"); - - QSE_MEMCPY ( - &awk->sio.ungot[awk->sio.nungots++], - c, QSE_SIZEOF(*c) - ); + awk->sio.ungot[awk->sio.nungots++] = *c; } const qse_char_t* qse_awk_getgblname ( @@ -762,8 +755,8 @@ static int end_include (qse_awk_t* awk) static qse_awk_t* parse_progunit (qse_awk_t* awk) { /* + @include "xxxx" global xxx, xxxx; - include "xxxx"; BEGIN { action } END { action } pattern { action } @@ -5132,16 +5125,16 @@ static int skip_spaces (qse_awk_t* awk) if (c == QSE_T('\\')) { - qse_awk_lxc_t bs; - qse_awk_lxc_t cr; + qse_awk_sio_lxc_t bs; + qse_awk_sio_lxc_t cr; int hascr = 0; - QSE_MEMCPY (&bs, &awk->sio.last, QSE_SIZEOF(bs)); + bs = awk->sio.last; GET_CHAR_TO (awk, c); if (c == QSE_T('\r')) { hascr = 1; - QSE_MEMCPY (&cr, &awk->sio.last, QSE_SIZEOF(cr)); + cr = awk->sio.last; GET_CHAR_TO (awk, c); } @@ -5157,7 +5150,7 @@ static int skip_spaces (qse_awk_t* awk) /* push CR if any */ if (hascr) unget_char (awk, &cr); /* restore the orginal backslash */ - QSE_MEMCPY (&awk->sio.last, &bs, QSE_SIZEOF(bs)); + awk->sio.last = bs; } } @@ -5176,7 +5169,7 @@ static int skip_spaces (qse_awk_t* awk) static int skip_comment (qse_awk_t* awk) { qse_cint_t c = awk->sio.last.c; - qse_awk_lxc_t lc; + qse_awk_sio_lxc_t lc; if (c == QSE_T('#')) { @@ -5192,7 +5185,7 @@ static int skip_comment (qse_awk_t* awk) if (c != QSE_T('/')) return 0; /* not a comment */ /* save the last character */ - QSE_MEMCPY (&lc, &awk->sio.last, QSE_SIZEOF(lc)); + lc = awk->sio.last; /* read a new character */ GET_CHAR_TO (awk, c); @@ -5232,7 +5225,7 @@ static int skip_comment (qse_awk_t* awk) /* unget '*' */ unget_char (awk, &awk->sio.last); /* restore the previous state */ - QSE_MEMCPY (&awk->sio.last, &lc, QSE_SIZEOF(lc)); + awk->sio.last = lc; return 0; } @@ -5359,7 +5352,11 @@ retry: { n = end_include (awk); if (n <= -1) return -1; - if (n >= 1) goto retry; + if (n >= 1) + { + awk->sio.last = awk->sio.inp->last; + goto retry; + } ADD_TOKEN_STR (awk, token, QSE_T(""), 5); SET_TOKEN_TYPE (awk, token, TOKEN_EOF); @@ -5377,9 +5374,9 @@ retry: } else if (c == QSE_T('.')) { - qse_awk_lxc_t lc; + qse_awk_sio_lxc_t lc; - QSE_MEMCPY (&lc, &awk->sio.last, QSE_SIZEOF(lc)); + lc = awk->sio.last; GET_CHAR_TO (awk, c); if (!(awk->option & QSE_AWK_EXPLICIT) && @@ -5387,7 +5384,7 @@ retry: { /* for a token such as .123 */ unget_char (awk, &awk->sio.last); - QSE_MEMCPY (&awk->sio.last, &lc, QSE_SIZEOF(lc)); + awk->sio.last = lc; if (get_number (awk, token) <= -1) return -1; } diff --git a/qse/lib/awk/std.c b/qse/lib/awk/std.c index d96863e0..19d7424f 100644 --- a/qse/lib/awk/std.c +++ b/qse/lib/awk/std.c @@ -1,5 +1,5 @@ /* - * $Id: std.c 247 2009-07-31 13:01:04Z hyunghwan.chung $ + * $Id: std.c 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -45,6 +45,7 @@ typedef struct xtn_t const qse_char_t* end; } cpl; } u; + qse_cstr_t dir; qse_sio_t* handle; /* the handle to an open file */ } in; @@ -173,6 +174,8 @@ static qse_ssize_t sf_in_open ( } else { + const qse_char_t* base; + xtn->s.in.handle = qse_sio_open ( awk->mmgr, 0, @@ -190,6 +193,13 @@ static qse_ssize_t sf_in_open ( ); return -1; } + + base = qse_awk_basename (awk, xtn->s.in.u.file); + if (base != xtn->s.in.u.file) + { + xtn->s.in.dir.ptr = xtn->s.in.u.file; + xtn->s.in.dir.len = base - xtn->s.in.u.file; + } } return 1; @@ -208,11 +218,45 @@ static qse_ssize_t sf_in_open ( } else { -/* TODO: standard include path */ + const qse_char_t* file = arg->name; + qse_char_t fbuf[64]; + qse_char_t* dbuf = QSE_NULL; + + if (xtn->s.in.dir.len > 0) + { + qse_size_t tmplen, totlen; + + totlen = qse_strlen(arg->name) + xtn->s.in.dir.len; + if (totlen >= QSE_COUNTOF(fbuf)) + { + dbuf = QSE_MMGR_ALLOC ( + awk->mmgr, + QSE_SIZEOF(qse_char_t) * (totlen + 1) + ); + if (dbuf == QSE_NULL) + { + qse_awk_seterrnum (awk, QSE_AWK_ENOMEM); + return -1; + } + + file = dbuf; + } + else file = fbuf; + + tmplen = qse_strncpy ( + (qse_char_t*)file, + xtn->s.in.dir.ptr, + xtn->s.in.dir.len + ); + qse_strcpy ((qse_char_t*)file + tmplen, arg->name); + } + arg->handle = qse_sio_open ( - awk->mmgr, 0, arg->name, QSE_SIO_READ + awk->mmgr, 0, file, QSE_SIO_READ ); - if (arg->handle == QSE_NULL) + + if (dbuf != QSE_NULL) QSE_MMGR_FREE (awk->mmgr, dbuf); + if (arg->handle == QSE_NULL) { qse_cstr_t ea; ea.ptr = arg->name; diff --git a/qse/samples/awk/awk04.c b/qse/samples/awk/awk04.c index 8c4c0d9a..600b4a8d 100644 --- a/qse/samples/awk/awk04.c +++ b/qse/samples/awk/awk04.c @@ -1,5 +1,5 @@ /* - * $Id: awk04.c 211 2009-06-24 09:50:10Z hyunghwan.chung $ + * $Id: awk04.c 250 2009-08-10 03:29:59Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -33,7 +33,7 @@ int main () qse_size_t len; qse_awk_val_t* v; qse_awk_val_t* arg[2] = { QSE_NULL, QSE_NULL }; - int ret, i; + int ret, i, opt; /* create a main processor */ awk = qse_awk_openstd (0); @@ -43,8 +43,14 @@ int main () ret = -1; goto oops; } + opt = qse_awk_getoption(awk); + /* don't allow BEGIN, END, pattern-action blocks */ - qse_awk_setoption (awk, qse_awk_getoption(awk) & ~QSE_AWK_PABLOCK); + opt &= ~QSE_AWK_PABLOCK; + /* enable ** */ + opt |= QSE_AWK_EXTRAOPS; + + qse_awk_setoption (awk, opt); psin.type = QSE_AWK_PARSESTD_CP; psin.u.cp = src;