changed Source IO model in Awk
This commit is contained in:
parent
1d88a17c7c
commit
852a51ae75
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: Awk.hpp 225 2009-07-08 13:01:45Z hyunghwan.chung $
|
* $Id: Awk.hpp 226 2009-07-09 12:46:14Z hyunghwan.chung $
|
||||||
*
|
*
|
||||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
@ -55,137 +55,67 @@ public:
|
|||||||
|
|
||||||
typedef qse_awk_rio_cmd_t rio_cmd_t;
|
typedef qse_awk_rio_cmd_t rio_cmd_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the source code I/O context for Awk::parse.
|
|
||||||
* An instance of Awk::Source is passed to Awk::openSource,
|
|
||||||
* Awk::readSource, Awk::writeSource, Awk::closeSource
|
|
||||||
* when Awk::parse calls them to read the source code and write the
|
|
||||||
* internal parse tree. It indicates the mode of the context and
|
|
||||||
* provides space for data that may be needed for the I/O operation.
|
|
||||||
*/
|
|
||||||
class Source
|
class Source
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class Awk;
|
|
||||||
|
|
||||||
/** Mode of source code I/O. */
|
|
||||||
enum Mode
|
enum Mode
|
||||||
{
|
{
|
||||||
READ, /**< source code read. */
|
READ, /**< source code read. */
|
||||||
WRITE /**< source code write. */
|
WRITE /**< source code write. */
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
class Data
|
||||||
Source (Mode mode);
|
{
|
||||||
|
public:
|
||||||
|
friend class Awk;
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
/**
|
Data (Awk* awk, Mode mode):
|
||||||
* Returns the mode of the source code I/O.
|
awk (awk), mode (mode), handle (QSE_NULL) {}
|
||||||
* You may call this method in Awk::openSource and
|
|
||||||
* Awk::closeSource to determine the mode as shown in
|
|
||||||
* the example below. This method always returns Source::READ
|
|
||||||
* and Source::WRITE respectively when called from
|
|
||||||
* Awk::readSource and Awk::writeSource.
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* int openSource (Source& io)
|
|
||||||
* {
|
|
||||||
* if (io.getMode() == Source::READ)
|
|
||||||
* {
|
|
||||||
* // open for reading
|
|
||||||
* return 1;
|
|
||||||
* }
|
|
||||||
* else (io.getMode() == Source::WRITE)
|
|
||||||
* {
|
|
||||||
* // open for writing
|
|
||||||
* return 1;
|
|
||||||
* }
|
|
||||||
* return -1;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* int closeSource (Source& io)
|
|
||||||
* {
|
|
||||||
* if (io.getMode() == Source::READ)
|
|
||||||
* {
|
|
||||||
* // close for reading
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* else (io.getMode() == Source::WRITE)
|
|
||||||
* {
|
|
||||||
* // close for writing
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* return -1;
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @return Awk::Source::READ or Awk::Source::WRITE
|
|
||||||
*/
|
|
||||||
Mode getMode() const;
|
|
||||||
|
|
||||||
/**
|
public:
|
||||||
* Returns the value set with Source::setHandle.
|
Mode getMode() const
|
||||||
* QSE_NULL is returned if it has not been set with
|
{
|
||||||
* Source::setHandle. You usually call this method
|
return mode;
|
||||||
* from Awk::readSource, Awk::writeSource, and
|
}
|
||||||
* Awk::closeSource to get the value set in Awk::openSource
|
|
||||||
* as shown in the example below.
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* int closeSource (Source& io)
|
|
||||||
* {
|
|
||||||
* if (io.getMode() == Source::READ)
|
|
||||||
* {
|
|
||||||
* fclose ((FILE*)io.getHandle());
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* else (io.getMode() == Source::WRITE)
|
|
||||||
* {
|
|
||||||
* fclose ((FILE*)io.getHandle());
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* return -1;
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @return an arbitrary value of type void* set with
|
|
||||||
* Source::setHandle() or QSE_NULL
|
|
||||||
*/
|
|
||||||
const void* getHandle () const;
|
|
||||||
|
|
||||||
/**
|
const void* getHandle () const
|
||||||
* Sets the handle value. Source::getHandle can retrieve
|
{
|
||||||
* the value set with Source::setHandle. You usually call
|
return handle;
|
||||||
* this from Awk::openSource as shown in the example below.
|
}
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* int openSource (Source& io)
|
|
||||||
* {
|
|
||||||
* if (io.getMode() == Source::READ)
|
|
||||||
* {
|
|
||||||
* FILE* fp = fopen ("t.awk", "r");
|
|
||||||
* if (fp == NULL) return -1;
|
|
||||||
* io.setHandle (fp);
|
|
||||||
* return 1;
|
|
||||||
* }
|
|
||||||
* else (io.getMode() == Source::WRITE)
|
|
||||||
* {
|
|
||||||
* FILE* fp = fopen ("t.out", "w");
|
|
||||||
* if (fp == NULL) return -1;
|
|
||||||
* io.setHandle (fp);
|
|
||||||
* return 1;
|
|
||||||
* }
|
|
||||||
* return -1;
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param handle an arbitrary value of the type void*
|
|
||||||
*/
|
|
||||||
void setHandle (void* handle);
|
|
||||||
|
|
||||||
protected:
|
void setHandle (void* handle)
|
||||||
Mode mode;
|
{
|
||||||
void* handle;
|
this->handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Awk* () const
|
||||||
|
{
|
||||||
|
return awk;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator awk_t* () const
|
||||||
|
{
|
||||||
|
return awk->awk;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Awk* awk;
|
||||||
|
Mode mode;
|
||||||
|
void* handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
Source () {}
|
||||||
|
virtual ~Source () {}
|
||||||
|
|
||||||
|
virtual int open (Data& io) = 0;
|
||||||
|
virtual int close (Data& io) = 0;
|
||||||
|
virtual ssize_t read (Data& io, char_t* buf, size_t len) = 0;
|
||||||
|
virtual ssize_t write (Data& io, char_t* buf, size_t len) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Source (const Source&);
|
||||||
|
Source& operator= (const Source&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Run;
|
class Run;
|
||||||
@ -212,6 +142,10 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
Run* run;
|
Run* run;
|
||||||
rio_arg_t* riod;
|
rio_arg_t* riod;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RIOBase (const RIOBase&);
|
||||||
|
RIOBase& operator= (const RIOBase&);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -819,7 +753,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return a Run object on success, QSE_NULL on failure
|
* @return a Run object on success, QSE_NULL on failure
|
||||||
*/
|
*/
|
||||||
virtual Awk::Run* parse ();
|
virtual Awk::Run* parse (Source* in, Source* out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the BEGIN block, pattern-action blocks, and the END block.
|
* Executes the BEGIN block, pattern-action blocks, and the END block.
|
||||||
@ -900,77 +834,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual int dispatchFunction (Run* run, const char_t* name, size_t len);
|
virtual int dispatchFunction (Run* run, const char_t* name, size_t len);
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Source code I/O handlers
|
|
||||||
* A subclass should override the following methods to support the
|
|
||||||
* source code input and output. The awk interpreter calls the
|
|
||||||
* following methods when the parse method is invoked.
|
|
||||||
*
|
|
||||||
* To read the source code, Awk::parse calls Awk::openSource,
|
|
||||||
* Awk::readSource, and Awk::closeSource as shown in the diagram below.
|
|
||||||
* Any failures wll cause Awk::parse to return an error.
|
|
||||||
*
|
|
||||||
* \image html awk-srcio-read.png
|
|
||||||
*
|
|
||||||
* Awk::parse is able to write back the internal parse tree by
|
|
||||||
* calling Awk::openSource, Awk::writeSource, and Awk::closeSource
|
|
||||||
* as shown in the diagram below. Any failures will cause Awk::parse
|
|
||||||
* to return an error.
|
|
||||||
*
|
|
||||||
* \image html awk-srcio-write.png
|
|
||||||
*
|
|
||||||
* Awk::parse passes an instance of Awk::Source when invoking these
|
|
||||||
* methods. You can determine the context of the method by calling
|
|
||||||
* Awk::Source::getMode and inspecting its return value. You may use
|
|
||||||
* Awk::Source::getHandle and Awk::Source::setHandle to store and
|
|
||||||
* retrieve the data information needed to complete the operation.
|
|
||||||
*/
|
|
||||||
/*@{*/
|
|
||||||
/**
|
|
||||||
* Opens the source code stream.
|
|
||||||
* A subclass should override this method. It should return 1 on
|
|
||||||
* success, -1 on failure, and 0 if the opening operation
|
|
||||||
* is successful but has reached the end of the stream.
|
|
||||||
* @param io I/O context passed from Awk::parse
|
|
||||||
* @see Awk::Source::getMode, Awk::Source::setHandle
|
|
||||||
*/
|
|
||||||
virtual int openSource (Source& io) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the source code stream.
|
|
||||||
* A subclass should override this method. It should return 0 on
|
|
||||||
* success and -1 on failure.
|
|
||||||
* @param io I/O context passed from Awk::parse
|
|
||||||
* @see Awk::Source::getMode, Awk::Source::getHandle
|
|
||||||
*/
|
|
||||||
virtual int closeSource (Source& io) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads from the source code input stream.
|
|
||||||
* A subclass should override this method. It should return 0 when
|
|
||||||
* it has reached the end of the stream and -1 on falure.
|
|
||||||
* When it has data to return, it should read characters not longer
|
|
||||||
* than len characters, fill the buffer pointed at by buf with them,
|
|
||||||
* and return the number of the charaters read.
|
|
||||||
* @param io I/O context passed from Awk::parse
|
|
||||||
* @param buf pointer to a character buffer
|
|
||||||
* @param len number of characters in the buffer
|
|
||||||
*/
|
|
||||||
virtual ssize_t readSource (Source& io, char_t* buf, size_t len) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to the source code output stream.
|
|
||||||
* A subclass should override this method. It should return 0 when
|
|
||||||
* it has reachedthe end of the stream and -1 on failure.
|
|
||||||
* It should write up to len characters from the buffer pointed at
|
|
||||||
* by buf and return the number of characters written.
|
|
||||||
* @param io I/O context passed from Awk::parse
|
|
||||||
* @param buf pointer to a character buffer
|
|
||||||
* @param len size of the buffer in characters
|
|
||||||
*/
|
|
||||||
virtual ssize_t writeSource (Source& io, char_t* buf, size_t len) = 0;
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Pipe I/O handlers
|
* @name Pipe I/O handlers
|
||||||
* Pipe operations are achieved through the following methods.
|
* Pipe operations are achieved through the following methods.
|
||||||
@ -1018,9 +881,9 @@ protected:
|
|||||||
const char_t* fmt, va_list arg) = 0;
|
const char_t* fmt, va_list arg) = 0;
|
||||||
|
|
||||||
// static glue members for various handlers
|
// static glue members for various handlers
|
||||||
static ssize_t sourceReader (
|
static ssize_t readSource (
|
||||||
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count);
|
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count);
|
||||||
static ssize_t sourceWriter (
|
static ssize_t writeSource (
|
||||||
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count);
|
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count);
|
||||||
|
|
||||||
static ssize_t pipeHandler (
|
static ssize_t pipeHandler (
|
||||||
@ -1050,8 +913,11 @@ protected:
|
|||||||
errstr_t dflerrstr;
|
errstr_t dflerrstr;
|
||||||
map_t* functionMap;
|
map_t* functionMap;
|
||||||
|
|
||||||
Source sourceIn;
|
Source::Data sourceIn;
|
||||||
Source sourceOut;
|
Source::Data sourceOut;
|
||||||
|
|
||||||
|
Source* sourceReader;
|
||||||
|
Source* sourceWriter;
|
||||||
|
|
||||||
ErrorNumber errnum;
|
ErrorNumber errnum;
|
||||||
size_t errlin;
|
size_t errlin;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: StdAwk.hpp 224 2009-07-07 13:05:10Z hyunghwan.chung $
|
* $Id: StdAwk.hpp 226 2009-07-09 12:46:14Z hyunghwan.chung $
|
||||||
*
|
*
|
||||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
@ -24,6 +24,8 @@
|
|||||||
/**
|
/**
|
||||||
* @example awk05.cpp
|
* @example awk05.cpp
|
||||||
* This program demonstrates how to embed QSE::StdAwk in C++.
|
* This program demonstrates how to embed QSE::StdAwk in C++.
|
||||||
|
* @example awk06.cpp
|
||||||
|
* This program demonstrates how to embed QSE::StdAwk in C++.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
@ -38,6 +40,35 @@ QSE_BEGIN_NAMESPACE(QSE)
|
|||||||
class StdAwk: public Awk
|
class StdAwk: public Awk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class SourceFile: public Source
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SourceFile (const char_t* name): name (name) {}
|
||||||
|
|
||||||
|
int open (Data& io);
|
||||||
|
int close (Data& io);
|
||||||
|
ssize_t read (Data& io, char_t* buf, size_t len);
|
||||||
|
ssize_t write (Data& io, char_t* buf, size_t len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char_t* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SourceString: public Source
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SourceString (const char_t* str): str (str) {}
|
||||||
|
|
||||||
|
int open (Data& io);
|
||||||
|
int close (Data& io);
|
||||||
|
ssize_t read (Data& io, char_t* buf, size_t len);
|
||||||
|
ssize_t write (Data& io, char_t* buf, size_t len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char_t* str;
|
||||||
|
const char_t* ptr;
|
||||||
|
};
|
||||||
|
|
||||||
int open ();
|
int open ();
|
||||||
void close ();
|
void close ();
|
||||||
|
|
||||||
@ -46,7 +77,6 @@ public:
|
|||||||
virtual void clearConsoleOutputs ();
|
virtual void clearConsoleOutputs ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// intrinsic functions
|
// intrinsic functions
|
||||||
int sin (Run& run, Return& ret, const Argument* args, size_t nargs,
|
int sin (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||||
const char_t* name, size_t len);
|
const char_t* name, size_t len);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: Awk.cpp 225 2009-07-08 13:01:45Z hyunghwan.chung $
|
* $Id: Awk.cpp 226 2009-07-09 12:46:14Z hyunghwan.chung $
|
||||||
*
|
*
|
||||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
@ -39,25 +39,6 @@ struct rxtn_t
|
|||||||
Awk::Run* run;
|
Awk::Run* run;
|
||||||
};
|
};
|
||||||
|
|
||||||
Awk::Source::Source (Mode mode): mode (mode), handle (QSE_NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Awk::Source::Mode Awk::Source::getMode () const
|
|
||||||
{
|
|
||||||
return this->mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* Awk::Source::getHandle () const
|
|
||||||
{
|
|
||||||
return this->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Awk::Source::setHandle (void* handle)
|
|
||||||
{
|
|
||||||
this->handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
// Awk::RIO
|
// Awk::RIO
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
@ -1067,7 +1048,7 @@ int Awk::Run::getGlobal (int id, Argument& gbl) const
|
|||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Awk::Awk () throw (): awk (QSE_NULL), functionMap (QSE_NULL),
|
Awk::Awk () throw (): awk (QSE_NULL), functionMap (QSE_NULL),
|
||||||
sourceIn (Source::READ), sourceOut (Source::WRITE),
|
sourceIn (this, Source::READ), sourceOut (this, Source::WRITE),
|
||||||
errnum (ERR_NOERR), errlin (0), runCallback (false),
|
errnum (ERR_NOERR), errlin (0), runCallback (false),
|
||||||
runctx (this)
|
runctx (this)
|
||||||
|
|
||||||
@ -1329,15 +1310,18 @@ int Awk::unsetAllWords ()
|
|||||||
return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0);
|
return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Awk::Run* Awk::parse ()
|
Awk::Run* Awk::parse (Source* in, Source* out)
|
||||||
{
|
{
|
||||||
QSE_ASSERT (awk != QSE_NULL);
|
QSE_ASSERT (awk != QSE_NULL);
|
||||||
|
|
||||||
fini_runctx ();
|
fini_runctx ();
|
||||||
|
|
||||||
|
sourceReader = in;
|
||||||
|
sourceWriter = out;
|
||||||
|
|
||||||
qse_awk_sio_t sio;
|
qse_awk_sio_t sio;
|
||||||
sio.in = sourceReader;
|
sio.in = readSource;
|
||||||
sio.out = sourceWriter;
|
sio.out = (sourceWriter == QSE_NULL)? QSE_NULL: writeSource;
|
||||||
|
|
||||||
int n = qse_awk_parse (awk, &sio);
|
int n = qse_awk_parse (awk, &sio);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
@ -1657,7 +1641,7 @@ void Awk::onStatement (Run& run, size_t line)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Awk::ssize_t Awk::sourceReader (
|
Awk::ssize_t Awk::readSource (
|
||||||
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count)
|
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count)
|
||||||
{
|
{
|
||||||
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
|
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
|
||||||
@ -1665,19 +1649,17 @@ Awk::ssize_t Awk::sourceReader (
|
|||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case QSE_AWK_SIO_OPEN:
|
case QSE_AWK_SIO_OPEN:
|
||||||
return xtn->awk->openSource (xtn->awk->sourceIn);
|
return xtn->awk->sourceReader->open (xtn->awk->sourceIn);
|
||||||
case QSE_AWK_SIO_CLOSE:
|
case QSE_AWK_SIO_CLOSE:
|
||||||
return xtn->awk->closeSource (xtn->awk->sourceIn);
|
return xtn->awk->sourceReader->close (xtn->awk->sourceIn);
|
||||||
case QSE_AWK_SIO_READ:
|
case QSE_AWK_SIO_READ:
|
||||||
return xtn->awk->readSource (xtn->awk->sourceIn, data, count);
|
return xtn->awk->sourceReader->read (xtn->awk->sourceIn, data, count);
|
||||||
case QSE_AWK_SIO_WRITE:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Awk::ssize_t Awk::sourceWriter (
|
Awk::ssize_t Awk::writeSource (
|
||||||
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count)
|
awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count)
|
||||||
{
|
{
|
||||||
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
|
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
|
||||||
@ -1685,16 +1667,14 @@ Awk::ssize_t Awk::sourceWriter (
|
|||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case QSE_AWK_SIO_OPEN:
|
case QSE_AWK_SIO_OPEN:
|
||||||
return xtn->awk->openSource (xtn->awk->sourceOut);
|
return xtn->awk->sourceWriter->open (xtn->awk->sourceOut);
|
||||||
case QSE_AWK_SIO_CLOSE:
|
case QSE_AWK_SIO_CLOSE:
|
||||||
return xtn->awk->closeSource (xtn->awk->sourceOut);
|
return xtn->awk->sourceWriter->close (xtn->awk->sourceOut);
|
||||||
case QSE_AWK_SIO_WRITE:
|
case QSE_AWK_SIO_WRITE:
|
||||||
return xtn->awk->writeSource (xtn->awk->sourceOut, data, count);
|
return xtn->awk->sourceWriter->write (xtn->awk->sourceOut, data, count);
|
||||||
case QSE_AWK_SIO_READ:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Awk::ssize_t Awk::pipeHandler (
|
Awk::ssize_t Awk::pipeHandler (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: StdAwk.cpp 225 2009-07-08 13:01:45Z hyunghwan.chung $
|
* $Id: StdAwk.cpp 226 2009-07-09 12:46:14Z hyunghwan.chung $
|
||||||
*
|
*
|
||||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
@ -81,24 +81,6 @@ void StdAwk::close ()
|
|||||||
Awk::close ();
|
Awk::close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
int StdAwk::addConsoleOutput (const char_t* arg, size_t len)
|
|
||||||
{
|
|
||||||
QSE_ASSERT (awk != QSE_NULL);
|
|
||||||
int n = ofile.add (awk, arg, len);
|
|
||||||
if (n <= -1) setError (ERR_NOMEM);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int StdAwk::addConsoleOutput (const char_t* arg)
|
|
||||||
{
|
|
||||||
return addConsoleOutput (arg, qse_strlen(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StdAwk::clearConsoleOutputs ()
|
|
||||||
{
|
|
||||||
ofile.clear (awk);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StdAwk::sin (Run& run, Return& ret, const Argument* args, size_t nargs,
|
int StdAwk::sin (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||||
const char_t* name, size_t len)
|
const char_t* name, size_t len)
|
||||||
{
|
{
|
||||||
@ -300,22 +282,22 @@ int StdAwk::openPipe (Pipe& io)
|
|||||||
{
|
{
|
||||||
Awk::Pipe::Mode mode = io.getMode();
|
Awk::Pipe::Mode mode = io.getMode();
|
||||||
qse_pio_t* pio = QSE_NULL;
|
qse_pio_t* pio = QSE_NULL;
|
||||||
int flags;
|
int flags = QSE_PIO_TEXT | QSE_PIO_SHELL;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case Awk::Pipe::READ:
|
case Awk::Pipe::READ:
|
||||||
/* TODO: should we specify ERRTOOUT? */
|
/* TODO: should we specify ERRTOOUT? */
|
||||||
flags = QSE_PIO_READOUT |
|
flags |= QSE_PIO_READOUT |
|
||||||
QSE_PIO_ERRTOOUT;
|
QSE_PIO_ERRTOOUT;
|
||||||
break;
|
break;
|
||||||
case Awk::Pipe::WRITE:
|
case Awk::Pipe::WRITE:
|
||||||
flags = QSE_PIO_WRITEIN;
|
flags |= QSE_PIO_WRITEIN;
|
||||||
break;
|
break;
|
||||||
case Awk::Pipe::RW:
|
case Awk::Pipe::RW:
|
||||||
flags = QSE_PIO_READOUT |
|
flags |= QSE_PIO_READOUT |
|
||||||
QSE_PIO_ERRTOOUT |
|
QSE_PIO_ERRTOOUT |
|
||||||
QSE_PIO_WRITEIN;
|
QSE_PIO_WRITEIN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +305,7 @@ int StdAwk::openPipe (Pipe& io)
|
|||||||
((Awk*)io)->getMmgr(),
|
((Awk*)io)->getMmgr(),
|
||||||
0,
|
0,
|
||||||
io.getName(),
|
io.getName(),
|
||||||
flags|QSE_PIO_TEXT|QSE_PIO_SHELL
|
flags
|
||||||
);
|
);
|
||||||
if (pio == QSE_NULL) return -1;
|
if (pio == QSE_NULL) return -1;
|
||||||
|
|
||||||
@ -352,26 +334,25 @@ int StdAwk::flushPipe (Pipe& io)
|
|||||||
return qse_pio_flush ((qse_pio_t*)io.getHandle(), QSE_PIO_IN);
|
return qse_pio_flush ((qse_pio_t*)io.getHandle(), QSE_PIO_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// file io handlers
|
|
||||||
int StdAwk::openFile (File& io)
|
int StdAwk::openFile (File& io)
|
||||||
{
|
{
|
||||||
Awk::File::Mode mode = io.getMode();
|
Awk::File::Mode mode = io.getMode();
|
||||||
qse_fio_t* fio = QSE_NULL;
|
qse_fio_t* fio = QSE_NULL;
|
||||||
int flags;
|
int flags = QSE_FIO_TEXT;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case Awk::File::READ:
|
case Awk::File::READ:
|
||||||
flags = QSE_FIO_READ;
|
flags |= QSE_FIO_READ;
|
||||||
break;
|
break;
|
||||||
case Awk::File::WRITE:
|
case Awk::File::WRITE:
|
||||||
flags = QSE_FIO_WRITE |
|
flags |= QSE_FIO_WRITE |
|
||||||
QSE_FIO_CREATE |
|
QSE_FIO_CREATE |
|
||||||
QSE_FIO_TRUNCATE;
|
QSE_FIO_TRUNCATE;
|
||||||
break;
|
break;
|
||||||
case Awk::File::APPEND:
|
case Awk::File::APPEND:
|
||||||
flags = QSE_FIO_APPEND |
|
flags |= QSE_FIO_APPEND |
|
||||||
QSE_FIO_CREATE;
|
QSE_FIO_CREATE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +360,7 @@ int StdAwk::openFile (File& io)
|
|||||||
((Awk*)io)->getMmgr(),
|
((Awk*)io)->getMmgr(),
|
||||||
0,
|
0,
|
||||||
io.getName(),
|
io.getName(),
|
||||||
flags | QSE_FIO_TEXT,
|
flags,
|
||||||
QSE_FIO_RUSR | QSE_FIO_WUSR |
|
QSE_FIO_RUSR | QSE_FIO_WUSR |
|
||||||
QSE_FIO_RGRP | QSE_FIO_ROTH
|
QSE_FIO_RGRP | QSE_FIO_ROTH
|
||||||
);
|
);
|
||||||
@ -410,7 +391,24 @@ int StdAwk::flushFile (File& io)
|
|||||||
return qse_fio_flush ((qse_fio_t*)io.getHandle());
|
return qse_fio_flush ((qse_fio_t*)io.getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
// console io handlers
|
int StdAwk::addConsoleOutput (const char_t* arg, size_t len)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (awk != QSE_NULL);
|
||||||
|
int n = ofile.add (awk, arg, len);
|
||||||
|
if (n <= -1) setError (ERR_NOMEM);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdAwk::addConsoleOutput (const char_t* arg)
|
||||||
|
{
|
||||||
|
return addConsoleOutput (arg, qse_strlen(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdAwk::clearConsoleOutputs ()
|
||||||
|
{
|
||||||
|
ofile.clear (awk);
|
||||||
|
}
|
||||||
|
|
||||||
int StdAwk::open_console_in (Console& io)
|
int StdAwk::open_console_in (Console& io)
|
||||||
{
|
{
|
||||||
qse_awk_rtx_t* rtx = (rtx_t*)io;
|
qse_awk_rtx_t* rtx = (rtx_t*)io;
|
||||||
@ -754,6 +752,81 @@ int StdAwk::vsprintf (
|
|||||||
return qse_vsprintf (buf, size, fmt, arg);
|
return qse_vsprintf (buf, size, fmt, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int StdAwk::SourceFile::open (Data& io)
|
||||||
|
{
|
||||||
|
qse_sio_t* sio;
|
||||||
|
|
||||||
|
if (name[0] == QSE_T('-') &&
|
||||||
|
name[1] == QSE_T('\0'))
|
||||||
|
{
|
||||||
|
sio = (io.getMode() == READ)? qse_sio_in: qse_sio_out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.setHandle (sio);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdAwk::SourceFile::close (Data& io)
|
||||||
|
{
|
||||||
|
qse_sio_t* sio = (qse_sio_t*)io.getHandle();
|
||||||
|
|
||||||
|
qse_sio_flush (sio);
|
||||||
|
|
||||||
|
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
|
||||||
|
{
|
||||||
|
qse_sio_close (sio);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StdAwk::ssize_t StdAwk::SourceFile::read (Data& io, char_t* buf, size_t len)
|
||||||
|
{
|
||||||
|
return qse_sio_getsn ((qse_sio_t*)io.getHandle(), buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
StdAwk::ssize_t StdAwk::SourceFile::write (Data& io, char_t* buf, size_t len)
|
||||||
|
{
|
||||||
|
return qse_sio_putsn ((qse_sio_t*)io.getHandle(), buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdAwk::SourceString::open (Data& io)
|
||||||
|
{
|
||||||
|
/* SourceString does not support writing */
|
||||||
|
if (io.getMode() == WRITE) return -1;
|
||||||
|
ptr = str;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdAwk::SourceString::close (Data& io)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
StdAwk::ssize_t StdAwk::SourceString::write (Data& io, char_t* buf, size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_END_NAMESPACE(QSE)
|
QSE_END_NAMESPACE(QSE)
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -11,8 +11,13 @@ awk03_SOURCES = awk03.c
|
|||||||
awk04_SOURCES = awk04.c
|
awk04_SOURCES = awk04.c
|
||||||
|
|
||||||
if ENABLE_CXX
|
if ENABLE_CXX
|
||||||
bin_PROGRAMS += awk05
|
bin_PROGRAMS += awk05 awk06 awk07
|
||||||
|
|
||||||
awk05_SOURCES = awk05.cpp
|
awk05_SOURCES = awk05.cpp
|
||||||
|
awk06_SOURCES = awk06.cpp
|
||||||
|
awk07_SOURCES = awk07.cpp
|
||||||
|
|
||||||
awk05_LDADD = -lqseawk++ $(LDADD)
|
awk05_LDADD = -lqseawk++ $(LDADD)
|
||||||
|
awk06_LDADD = -lqseawk++ $(LDADD)
|
||||||
|
awk07_LDADD = -lqseawk++ $(LDADD)
|
||||||
endif
|
endif
|
||||||
|
@ -34,7 +34,7 @@ build_triplet = @build@
|
|||||||
host_triplet = @host@
|
host_triplet = @host@
|
||||||
bin_PROGRAMS = awk01$(EXEEXT) awk02$(EXEEXT) awk03$(EXEEXT) \
|
bin_PROGRAMS = awk01$(EXEEXT) awk02$(EXEEXT) awk03$(EXEEXT) \
|
||||||
awk04$(EXEEXT) $(am__EXEEXT_1)
|
awk04$(EXEEXT) $(am__EXEEXT_1)
|
||||||
@ENABLE_CXX_TRUE@am__append_1 = awk05
|
@ENABLE_CXX_TRUE@am__append_1 = awk05 awk06 awk07
|
||||||
subdir = samples/awk
|
subdir = samples/awk
|
||||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
@ -48,7 +48,8 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
|||||||
mkinstalldirs = $(install_sh) -d
|
mkinstalldirs = $(install_sh) -d
|
||||||
CONFIG_HEADER = $(top_builddir)/include/qse/config.h
|
CONFIG_HEADER = $(top_builddir)/include/qse/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
@ENABLE_CXX_TRUE@am__EXEEXT_1 = awk05$(EXEEXT)
|
@ENABLE_CXX_TRUE@am__EXEEXT_1 = awk05$(EXEEXT) awk06$(EXEEXT) \
|
||||||
|
@ENABLE_CXX_TRUE@ awk07$(EXEEXT)
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||||
PROGRAMS = $(bin_PROGRAMS)
|
PROGRAMS = $(bin_PROGRAMS)
|
||||||
@ -74,6 +75,14 @@ am__awk05_SOURCES_DIST = awk05.cpp
|
|||||||
awk05_OBJECTS = $(am_awk05_OBJECTS)
|
awk05_OBJECTS = $(am_awk05_OBJECTS)
|
||||||
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
|
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
|
||||||
@ENABLE_CXX_TRUE@awk05_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
@ENABLE_CXX_TRUE@awk05_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||||
|
am__awk06_SOURCES_DIST = awk06.cpp
|
||||||
|
@ENABLE_CXX_TRUE@am_awk06_OBJECTS = awk06.$(OBJEXT)
|
||||||
|
awk06_OBJECTS = $(am_awk06_OBJECTS)
|
||||||
|
@ENABLE_CXX_TRUE@awk06_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||||
|
am__awk07_SOURCES_DIST = awk07.cpp
|
||||||
|
@ENABLE_CXX_TRUE@am_awk07_OBJECTS = awk07.$(OBJEXT)
|
||||||
|
awk07_OBJECTS = $(am_awk07_OBJECTS)
|
||||||
|
@ENABLE_CXX_TRUE@awk07_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/qse
|
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/qse
|
||||||
depcomp = $(SHELL) $(top_srcdir)/ac/au/depcomp
|
depcomp = $(SHELL) $(top_srcdir)/ac/au/depcomp
|
||||||
am__depfiles_maybe = depfiles
|
am__depfiles_maybe = depfiles
|
||||||
@ -96,9 +105,11 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
|||||||
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
|
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
|
||||||
$(LDFLAGS) -o $@
|
$(LDFLAGS) -o $@
|
||||||
SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
||||||
$(awk04_SOURCES) $(awk05_SOURCES)
|
$(awk04_SOURCES) $(awk05_SOURCES) $(awk06_SOURCES) \
|
||||||
|
$(awk07_SOURCES)
|
||||||
DIST_SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
DIST_SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
||||||
$(awk04_SOURCES) $(am__awk05_SOURCES_DIST)
|
$(awk04_SOURCES) $(am__awk05_SOURCES_DIST) \
|
||||||
|
$(am__awk06_SOURCES_DIST) $(am__awk07_SOURCES_DIST)
|
||||||
ETAGS = etags
|
ETAGS = etags
|
||||||
CTAGS = ctags
|
CTAGS = ctags
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
@ -245,7 +256,11 @@ awk02_SOURCES = awk02.c
|
|||||||
awk03_SOURCES = awk03.c
|
awk03_SOURCES = awk03.c
|
||||||
awk04_SOURCES = awk04.c
|
awk04_SOURCES = awk04.c
|
||||||
@ENABLE_CXX_TRUE@awk05_SOURCES = awk05.cpp
|
@ENABLE_CXX_TRUE@awk05_SOURCES = awk05.cpp
|
||||||
|
@ENABLE_CXX_TRUE@awk06_SOURCES = awk06.cpp
|
||||||
|
@ENABLE_CXX_TRUE@awk07_SOURCES = awk07.cpp
|
||||||
@ENABLE_CXX_TRUE@awk05_LDADD = -lqseawk++ $(LDADD)
|
@ENABLE_CXX_TRUE@awk05_LDADD = -lqseawk++ $(LDADD)
|
||||||
|
@ENABLE_CXX_TRUE@awk06_LDADD = -lqseawk++ $(LDADD)
|
||||||
|
@ENABLE_CXX_TRUE@awk07_LDADD = -lqseawk++ $(LDADD)
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
@ -322,6 +337,12 @@ awk04$(EXEEXT): $(awk04_OBJECTS) $(awk04_DEPENDENCIES)
|
|||||||
awk05$(EXEEXT): $(awk05_OBJECTS) $(awk05_DEPENDENCIES)
|
awk05$(EXEEXT): $(awk05_OBJECTS) $(awk05_DEPENDENCIES)
|
||||||
@rm -f awk05$(EXEEXT)
|
@rm -f awk05$(EXEEXT)
|
||||||
$(CXXLINK) $(awk05_OBJECTS) $(awk05_LDADD) $(LIBS)
|
$(CXXLINK) $(awk05_OBJECTS) $(awk05_LDADD) $(LIBS)
|
||||||
|
awk06$(EXEEXT): $(awk06_OBJECTS) $(awk06_DEPENDENCIES)
|
||||||
|
@rm -f awk06$(EXEEXT)
|
||||||
|
$(CXXLINK) $(awk06_OBJECTS) $(awk06_LDADD) $(LIBS)
|
||||||
|
awk07$(EXEEXT): $(awk07_OBJECTS) $(awk07_DEPENDENCIES)
|
||||||
|
@rm -f awk07$(EXEEXT)
|
||||||
|
$(CXXLINK) $(awk07_OBJECTS) $(awk07_LDADD) $(LIBS)
|
||||||
|
|
||||||
mostlyclean-compile:
|
mostlyclean-compile:
|
||||||
-rm -f *.$(OBJEXT)
|
-rm -f *.$(OBJEXT)
|
||||||
@ -334,6 +355,8 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk03.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk03.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk04.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk04.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk05.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk05.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk06.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk07.Po@am__quote@
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
@ -17,468 +17,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <qse/awk/StdAwk.hpp>
|
#include <qse/awk/StdAwk.hpp>
|
||||||
#include <qse/cmn/str.h>
|
|
||||||
#include <qse/cmn/stdio.h>
|
#include <qse/cmn/stdio.h>
|
||||||
#include <qse/cmn/main.h>
|
#include <qse/cmn/main.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
static void print_error (unsigned long line, const qse_char_t* msg)
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <signal.h>
|
|
||||||
# include <errno.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class MyAwk;
|
|
||||||
#ifdef _WIN32
|
|
||||||
static BOOL WINAPI stop_run (DWORD ctrl_type);
|
|
||||||
#else
|
|
||||||
static void stop_run (int sig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void set_intr_run (void);
|
|
||||||
static void unset_intr_run (void);
|
|
||||||
|
|
||||||
MyAwk* app_awk = QSE_NULL;
|
|
||||||
static bool verbose = false;
|
|
||||||
|
|
||||||
class MyAwk: public QSE::StdAwk
|
|
||||||
{
|
{
|
||||||
public:
|
if (line > 0)
|
||||||
MyAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL)
|
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu\n"), msg, line);
|
||||||
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
heap = QSE_NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
~MyAwk ()
|
|
||||||
{
|
|
||||||
close ();
|
|
||||||
}
|
|
||||||
|
|
||||||
int open ()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
QSE_ASSERT (heap == QSE_NULL);
|
|
||||||
heap = ::HeapCreate (0, 1000000, 1000000);
|
|
||||||
if (heap == QSE_NULL) return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int n = StdAwk::open ();
|
|
||||||
if (n <= -1)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
HeapDestroy (heap);
|
|
||||||
heap = QSE_NULL;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
idLastSleep = addGlobal (QSE_T("LAST_SLEEP"));
|
|
||||||
if (idLastSleep <= -1) goto failure;
|
|
||||||
|
|
||||||
if (addFunction (QSE_T("sleep"), 1, 1,
|
|
||||||
(FunctionHandler)&MyAwk::sleep) <= -1) goto failure;
|
|
||||||
|
|
||||||
if (addFunction (QSE_T("sumintarray"), 1, 1,
|
|
||||||
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto failure;
|
|
||||||
|
|
||||||
if (addFunction (QSE_T("arrayindices"), 1, 1,
|
|
||||||
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto failure;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
failure:
|
|
||||||
StdAwk::close ();
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
HeapDestroy (heap);
|
|
||||||
heap = QSE_NULL;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close ()
|
|
||||||
{
|
|
||||||
StdAwk::close ();
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (heap != QSE_NULL)
|
|
||||||
{
|
|
||||||
HeapDestroy (heap);
|
|
||||||
heap = QSE_NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int sleep (Run& run, Return& ret, const Argument* args, size_t nargs,
|
|
||||||
const char_t* name, size_t len)
|
|
||||||
{
|
|
||||||
if (args[0].isIndexed())
|
|
||||||
{
|
|
||||||
run.setError (ERR_INVAL);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long_t x = args[0].toInt();
|
|
||||||
|
|
||||||
/*Argument arg;
|
|
||||||
if (run.getGlobal(idLastSleep, arg) == 0)
|
|
||||||
qse_printf (QSE_T("GOOD: [%d]\n"), (int)arg.toInt());
|
|
||||||
else { qse_printf (QSE_T("BAD:\n")); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (run.setGlobal (idLastSleep, x) <= -1) return -1;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
::Sleep ((DWORD)(x * 1000));
|
|
||||||
return ret.set ((long_t)0);
|
|
||||||
#else
|
|
||||||
return ret.set ((long_t)::sleep (x));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int sumintarray (Run& run, Return& ret, const Argument* args, size_t nargs,
|
|
||||||
const char_t* name, size_t len)
|
|
||||||
{
|
|
||||||
long_t x = 0;
|
|
||||||
|
|
||||||
if (args[0].isIndexed())
|
|
||||||
{
|
|
||||||
Argument idx(run), val(run);
|
|
||||||
|
|
||||||
int n = args[0].getFirstIndex (idx);
|
|
||||||
while (n > 0)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char_t* ptr = idx.toStr(&len);
|
|
||||||
|
|
||||||
if (args[0].getIndexed(ptr, len, val) <= -1) return -1;
|
|
||||||
x += val.toInt ();
|
|
||||||
|
|
||||||
n = args[0].getNextIndex (idx);
|
|
||||||
}
|
|
||||||
if (n != 0) return -1;
|
|
||||||
}
|
|
||||||
else x += args[0].toInt();
|
|
||||||
|
|
||||||
return ret.set (x);
|
|
||||||
}
|
|
||||||
|
|
||||||
int arrayindices (Run& run, Return& ret, const Argument* args, size_t nargs,
|
|
||||||
const char_t* name, size_t len)
|
|
||||||
{
|
|
||||||
if (!args[0].isIndexed()) return 0;
|
|
||||||
|
|
||||||
Argument idx (run);
|
|
||||||
long_t i;
|
|
||||||
|
|
||||||
int n = args[0].getFirstIndex (idx);
|
|
||||||
for (i = 0; n > 0; i++)
|
|
||||||
{
|
|
||||||
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 (n != 0) return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Run* parse (const char_t* in, const char_t* out)
|
|
||||||
{
|
|
||||||
srcInName = in;
|
|
||||||
srcOutName = out;
|
|
||||||
return StdAwk::parse ();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
bool onLoopEnter (Run& run)
|
|
||||||
{
|
|
||||||
set_intr_run ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onLoopExit (Run& run, const Argument& ret)
|
|
||||||
{
|
|
||||||
unset_intr_run ();
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char_t* ptr = ret.toStr (&len);
|
|
||||||
qse_printf (QSE_T("*** return [%.*s] ***\n"), (int)len, ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int openSource (Source& io)
|
|
||||||
{
|
|
||||||
Source::Mode mode = io.getMode();
|
|
||||||
FILE* fp = QSE_NULL;
|
|
||||||
|
|
||||||
// TODO: use sio instead of stdio
|
|
||||||
if (mode == Source::READ)
|
|
||||||
{
|
|
||||||
if (srcInName == QSE_NULL)
|
|
||||||
{
|
|
||||||
io.setHandle (stdin);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srcInName[0] == QSE_T('\0')) fp = stdin;
|
|
||||||
else fp = qse_fopen (srcInName, QSE_T("r"));
|
|
||||||
}
|
|
||||||
else if (mode == Source::WRITE)
|
|
||||||
{
|
|
||||||
if (srcOutName == QSE_NULL)
|
|
||||||
{
|
|
||||||
io.setHandle (stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srcOutName[0] == QSE_T('\0')) fp = stdout;
|
|
||||||
else fp = qse_fopen (srcOutName, QSE_T("w"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp == QSE_NULL) return -1;
|
|
||||||
io.setHandle (fp);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int closeSource (Source& io)
|
|
||||||
{
|
|
||||||
FILE* fp = (FILE*)io.getHandle();
|
|
||||||
if (fp == stdout || fp == stderr) fflush (fp);
|
|
||||||
if (fp != stdin && fp != stdout && fp != stderr) fclose (fp);
|
|
||||||
io.setHandle (QSE_NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t readSource (Source& io, char_t* buf, size_t len)
|
|
||||||
{
|
|
||||||
FILE* fp = (FILE*)io.getHandle();
|
|
||||||
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)) n = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[n++] = c;
|
|
||||||
if (c == QSE_T('\n')) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t writeSource (Source& io, char_t* buf, size_t len)
|
|
||||||
{
|
|
||||||
FILE* fp = (FILE*)io.getHandle();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* allocMem (size_t n) throw ()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
return ::HeapAlloc (heap, 0, n);
|
|
||||||
#else
|
|
||||||
return ::malloc (n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void* reallocMem (void* ptr, size_t n) throw ()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (ptr == NULL)
|
|
||||||
return ::HeapAlloc (heap, 0, n);
|
|
||||||
else
|
|
||||||
return ::HeapReAlloc (heap, 0, ptr, n);
|
|
||||||
#else
|
|
||||||
return ::realloc (ptr, n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void freeMem (void* ptr) throw ()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
::HeapFree (heap, 0, ptr);
|
|
||||||
#else
|
|
||||||
::free (ptr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char_t* srcInName;
|
|
||||||
const char_t* srcOutName;
|
|
||||||
|
|
||||||
int idLastSleep;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
void* heap;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static BOOL WINAPI stop_run (DWORD ctrl_type)
|
|
||||||
{
|
|
||||||
if (ctrl_type == CTRL_C_EVENT ||
|
|
||||||
ctrl_type == CTRL_CLOSE_EVENT)
|
|
||||||
{
|
|
||||||
if (app_awk) app_awk->stop ();
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
static int setsignal (int sig, void(*handler)(int), int restart)
|
|
||||||
{
|
|
||||||
struct sigaction sa_int;
|
|
||||||
|
|
||||||
sa_int.sa_handler = handler;
|
|
||||||
sigemptyset (&sa_int.sa_mask);
|
|
||||||
|
|
||||||
sa_int.sa_flags = 0;
|
|
||||||
|
|
||||||
if (restart)
|
|
||||||
{
|
|
||||||
#ifdef SA_RESTART
|
|
||||||
sa_int.sa_flags |= SA_RESTART;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||||
#ifdef SA_INTERRUPT
|
|
||||||
sa_int.sa_flags |= SA_INTERRUPT;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return sigaction (sig, &sa_int, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stop_run (int sig)
|
|
||||||
{
|
|
||||||
int e = errno;
|
|
||||||
if (app_awk) app_awk->stop ();
|
|
||||||
errno = e;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void set_intr_run (void)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
SetConsoleCtrlHandler (stop_run, TRUE);
|
|
||||||
#else
|
|
||||||
/*setsignal (SIGINT, stop_run, 1); TO BE MORE COMPATIBLE WITH WIN32*/
|
|
||||||
setsignal (SIGINT, stop_run, 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unset_intr_run (void)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
SetConsoleCtrlHandler (stop_run, FALSE);
|
|
||||||
#else
|
|
||||||
setsignal (SIGINT, SIG_DFL, 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_error (const qse_char_t* msg)
|
static void print_error (const qse_char_t* msg)
|
||||||
{
|
{
|
||||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
print_error (0, msg);
|
||||||
}
|
|
||||||
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
const qse_char_t* name;
|
|
||||||
MyAwk::Option opt;
|
|
||||||
} otab[] =
|
|
||||||
{
|
|
||||||
{ QSE_T("implicit"), MyAwk::OPT_IMPLICIT },
|
|
||||||
{ QSE_T("explicit"), MyAwk::OPT_EXPLICIT },
|
|
||||||
{ QSE_T("bxor"), MyAwk::OPT_BXOR },
|
|
||||||
{ QSE_T("shift"), MyAwk::OPT_SHIFT },
|
|
||||||
{ QSE_T("idiv"), MyAwk::OPT_IDIV },
|
|
||||||
{ QSE_T("rio"), MyAwk::OPT_RIO },
|
|
||||||
{ QSE_T("rwpipe"), MyAwk::OPT_RWPIPE },
|
|
||||||
{ QSE_T("newline"), MyAwk::OPT_NEWLINE },
|
|
||||||
{ QSE_T("stripspaces"), MyAwk::OPT_STRIPSPACES },
|
|
||||||
{ QSE_T("nextofile"), MyAwk::OPT_NEXTOFILE },
|
|
||||||
{ QSE_T("crlf"), MyAwk::OPT_CRLF },
|
|
||||||
{ QSE_T("reset"), MyAwk::OPT_RESET },
|
|
||||||
{ QSE_T("maptovar"), MyAwk::OPT_MAPTOVAR },
|
|
||||||
{ QSE_T("pablock"), MyAwk::OPT_PABLOCK }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void print_usage (const qse_char_t* argv0)
|
|
||||||
{
|
|
||||||
const qse_char_t* base;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
base = qse_strrchr(argv0, QSE_T('/'));
|
|
||||||
if (base == QSE_NULL) base = qse_strrchr(argv0, QSE_T('\\'));
|
|
||||||
if (base == QSE_NULL) base = argv0; else base++;
|
|
||||||
|
|
||||||
qse_printf (QSE_T("Usage: %s [-si file]? [-so file]? [-ci file]* [-co file]* [-w o:n]* \n"), base);
|
|
||||||
qse_printf (QSE_T(" -si file Specify the input source file\n"));
|
|
||||||
qse_printf (QSE_T(" The source code is read from stdin when it is not specified\n"));
|
|
||||||
qse_printf (QSE_T(" -so file Specify the output source file\n"));
|
|
||||||
qse_printf (QSE_T(" The deparsed code is not output when is it not specified\n"));
|
|
||||||
qse_printf (QSE_T(" -ci file Specify the input console file\n"));
|
|
||||||
qse_printf (QSE_T(" -co file Specify the output console file\n"));
|
|
||||||
qse_printf (QSE_T(" -w o:n Specify an old and new word pair\n"));
|
|
||||||
qse_printf (QSE_T(" o - an original word\n"));
|
|
||||||
qse_printf (QSE_T(" n - the new word to replace the original\n"));
|
|
||||||
qse_printf (QSE_T(" -v Print extra messages\n"));
|
|
||||||
|
|
||||||
|
|
||||||
qse_printf (QSE_T("\nYou may specify the following options to change the behavior of the interpreter.\n"));
|
|
||||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
|
||||||
{
|
|
||||||
qse_printf (QSE_T(" -%-20s -no%-20s\n"), otab[j].name, otab[j].name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int awk_main (int argc, qse_char_t* argv[])
|
static int awk_main (int argc, qse_char_t* argv[])
|
||||||
{
|
{
|
||||||
MyAwk awk;
|
QSE::StdAwk awk;
|
||||||
MyAwk::Run* run;
|
QSE::StdAwk::Run* run;
|
||||||
|
|
||||||
int mode = 0;
|
|
||||||
const qse_char_t* srcin = QSE_T("");
|
|
||||||
const qse_char_t* srcout = NULL;
|
|
||||||
qse_size_t nsrcins = 0;
|
|
||||||
qse_size_t nsrcouts = 0;
|
|
||||||
|
|
||||||
|
// initialize awk
|
||||||
if (awk.open() <= -1)
|
if (awk.open() <= -1)
|
||||||
{
|
{
|
||||||
print_error (awk.getErrorMessage());
|
print_error (awk.getErrorMessage());
|
||||||
@ -493,175 +54,41 @@ static int awk_main (int argc, qse_char_t* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
// ARGV[1] and/or the first console input file
|
||||||
|
if (awk.addArgument (QSE_T("awk05.cpp")) <= -1)
|
||||||
{
|
{
|
||||||
if (mode == 0)
|
print_error (awk.getErrorMessage());
|
||||||
{
|
|
||||||
if (qse_strcmp(argv[i], QSE_T("-si")) == 0) mode = 1;
|
|
||||||
else if (qse_strcmp(argv[i], QSE_T("-so")) == 0) mode = 2;
|
|
||||||
else if (qse_strcmp(argv[i], QSE_T("-ci")) == 0) mode = 3;
|
|
||||||
else if (qse_strcmp(argv[i], QSE_T("-co")) == 0) mode = 4;
|
|
||||||
else if (qse_strcmp(argv[i], QSE_T("-w")) == 0) mode = 5;
|
|
||||||
else if (qse_strcmp(argv[i], QSE_T("-v")) == 0)
|
|
||||||
{
|
|
||||||
verbose = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (argv[i][0] == QSE_T('-'))
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (argv[i][1] == QSE_T('n') && argv[i][2] == QSE_T('o'))
|
|
||||||
{
|
|
||||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
|
||||||
{
|
|
||||||
if (qse_strcmp(&argv[i][3], otab[j].name) == 0)
|
|
||||||
{
|
|
||||||
awk.setOption (awk.getOption() & ~otab[j].opt);
|
|
||||||
goto ok_valid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
|
||||||
{
|
|
||||||
if (qse_strcmp(&argv[i][1], otab[j].name) == 0)
|
|
||||||
{
|
|
||||||
awk.setOption (awk.getOption() | otab[j].opt);
|
|
||||||
goto ok_valid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_usage (argv[0]);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ok_valid:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (argv[i][0] == QSE_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.addArgument (argv[i]) <= -1)
|
|
||||||
{
|
|
||||||
print_error (QSE_T("too many console inputs"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mode = 0;
|
|
||||||
}
|
|
||||||
else if (mode == 4) // console output
|
|
||||||
{
|
|
||||||
if (awk.addConsoleOutput (argv[i]) <= -1)
|
|
||||||
{
|
|
||||||
print_error (QSE_T("too many console outputs"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mode = 0;
|
|
||||||
}
|
|
||||||
else if (mode == 5) // word replacement
|
|
||||||
{
|
|
||||||
const qse_char_t* p;
|
|
||||||
qse_size_t l;
|
|
||||||
|
|
||||||
p = qse_strchr(argv[i], QSE_T(':'));
|
|
||||||
if (p == QSE_NULL)
|
|
||||||
{
|
|
||||||
print_usage (argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
l = qse_strlen (argv[i]);
|
|
||||||
|
|
||||||
awk.setWord (
|
|
||||||
argv[i], p - argv[i],
|
|
||||||
p + 1, l - (p - argv[i] + 1));
|
|
||||||
|
|
||||||
mode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode != 0)
|
|
||||||
{
|
|
||||||
print_usage (argv[0]);
|
|
||||||
awk.close ();
|
awk.close ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
run = awk.parse (srcin, srcout);
|
const qse_char_t* script = QSE_T(
|
||||||
|
"BEGIN { print \">> PRINT ALL LINES WHOSE LENGTH IS GREATER THAN 0\"; }\n"
|
||||||
|
"length($0) > 0 { print $0; count++; }\n"
|
||||||
|
"END { print \">> TOTAL\", count, \"LINES\"; }\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
QSE::StdAwk::SourceString in (script);
|
||||||
|
QSE::StdAwk::SourceFile out (QSE_T("awk05.out"));
|
||||||
|
|
||||||
|
// parse the script string and deparse it to awk05.out.
|
||||||
|
run = awk.parse (&in, &out);
|
||||||
if (run == QSE_NULL)
|
if (run == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"),
|
print_error (awk.getErrorLine(), awk.getErrorMessage());
|
||||||
awk.getErrorLine(), awk.getErrorMessage());
|
|
||||||
awk.close ();
|
awk.close ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
awk.enableRunCallback ();
|
// execute the BEGIN, pattern-action, END blocks.
|
||||||
app_awk = &awk;
|
|
||||||
|
|
||||||
if (awk.loop () <= -1)
|
if (awk.loop () <= -1)
|
||||||
{
|
{
|
||||||
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
print_error (awk.getErrorLine(), awk.getErrorMessage());
|
||||||
awk.getErrorLine(), awk.getErrorMessage());
|
|
||||||
awk.close ();
|
awk.close ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
MyAwk::Return args[2];
|
|
||||||
|
|
||||||
args[0].setRun (run);
|
|
||||||
args[1].setRun (run);
|
|
||||||
|
|
||||||
if (awk.call (QSE_T("add"), args, 2) <= -1)
|
|
||||||
{
|
|
||||||
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
|
||||||
awk.getErrorLine(), awk.getErrorMessage());
|
|
||||||
awk.close ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
app_awk = QSE_NULL;
|
|
||||||
awk.close ();
|
awk.close ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
98
qse/samples/awk/awk06.cpp
Normal file
98
qse/samples/awk/awk06.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* $Id: Awk.cpp 341 2008-08-20 10:58:19Z baconevi $
|
||||||
|
*
|
||||||
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qse/awk/StdAwk.hpp>
|
||||||
|
#include <qse/cmn/stdio.h>
|
||||||
|
#include <qse/cmn/main.h>
|
||||||
|
|
||||||
|
static void print_error (unsigned long line, const qse_char_t* msg)
|
||||||
|
{
|
||||||
|
if (line > 0)
|
||||||
|
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu\n"), msg, line);
|
||||||
|
else
|
||||||
|
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_error (const qse_char_t* msg)
|
||||||
|
{
|
||||||
|
print_error (0, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int awk_main (int argc, qse_char_t* argv[])
|
||||||
|
{
|
||||||
|
QSE::StdAwk awk;
|
||||||
|
QSE::StdAwk::Run* run;
|
||||||
|
|
||||||
|
// initialize awk
|
||||||
|
if (awk.open() <= -1)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorMessage());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARGV[0]
|
||||||
|
if (awk.addArgument (QSE_T("awk05")) <= -1)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARGV[1] and/or the first console input file
|
||||||
|
if (awk.addArgument (QSE_T("awk05.cpp")) <= -1)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qse_char_t* script = QSE_T(
|
||||||
|
"BEGIN { print \">> PRINT ALL LINES WHOSE LENGTH IS GREATER THAN 0\"; }\n"
|
||||||
|
"length($0) > 0 { print $0; count++; }\n"
|
||||||
|
"END { print \">> TOTAL\", count, \"LINES\"; }\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
QSE::StdAwk::SourceString in (script);
|
||||||
|
QSE::StdAwk::SourceFile out (QSE_T("awk05.out"));
|
||||||
|
|
||||||
|
// parse the script string and deparse it to awk05.out.
|
||||||
|
run = awk.parse (&in, &out);
|
||||||
|
if (run == QSE_NULL)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorLine(), awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute the BEGIN, pattern-action, END blocks.
|
||||||
|
if (awk.loop () <= -1)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorLine(), awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
awk.close ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qse_main (int argc, qse_achar_t* argv[])
|
||||||
|
{
|
||||||
|
return qse_runmain (argc,argv,awk_main);
|
||||||
|
}
|
671
qse/samples/awk/awk07.cpp
Normal file
671
qse/samples/awk/awk07.cpp
Normal file
@ -0,0 +1,671 @@
|
|||||||
|
/*
|
||||||
|
* $Id: Awk.cpp 341 2008-08-20 10:58:19Z baconevi $
|
||||||
|
*
|
||||||
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qse/awk/StdAwk.hpp>
|
||||||
|
#include <qse/cmn/str.h>
|
||||||
|
#include <qse/cmn/stdio.h>
|
||||||
|
#include <qse/cmn/main.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <signal.h>
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class MyAwk;
|
||||||
|
#ifdef _WIN32
|
||||||
|
static BOOL WINAPI stop_run (DWORD ctrl_type);
|
||||||
|
#else
|
||||||
|
static void stop_run (int sig);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void set_intr_run (void);
|
||||||
|
static void unset_intr_run (void);
|
||||||
|
|
||||||
|
MyAwk* app_awk = QSE_NULL;
|
||||||
|
static bool verbose = false;
|
||||||
|
|
||||||
|
class MyAwk: public QSE::StdAwk
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL)
|
||||||
|
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
heap = QSE_NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~MyAwk ()
|
||||||
|
{
|
||||||
|
close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int open ()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
QSE_ASSERT (heap == QSE_NULL);
|
||||||
|
heap = ::HeapCreate (0, 1000000, 1000000);
|
||||||
|
if (heap == QSE_NULL) return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int n = StdAwk::open ();
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
HeapDestroy (heap);
|
||||||
|
heap = QSE_NULL;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
idLastSleep = addGlobal (QSE_T("LAST_SLEEP"));
|
||||||
|
if (idLastSleep <= -1) goto failure;
|
||||||
|
|
||||||
|
if (addFunction (QSE_T("sleep"), 1, 1,
|
||||||
|
(FunctionHandler)&MyAwk::sleep) <= -1) goto failure;
|
||||||
|
|
||||||
|
if (addFunction (QSE_T("sumintarray"), 1, 1,
|
||||||
|
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto failure;
|
||||||
|
|
||||||
|
if (addFunction (QSE_T("arrayindices"), 1, 1,
|
||||||
|
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto failure;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failure:
|
||||||
|
StdAwk::close ();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
HeapDestroy (heap);
|
||||||
|
heap = QSE_NULL;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close ()
|
||||||
|
{
|
||||||
|
StdAwk::close ();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (heap != QSE_NULL)
|
||||||
|
{
|
||||||
|
HeapDestroy (heap);
|
||||||
|
heap = QSE_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int sleep (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||||
|
const char_t* name, size_t len)
|
||||||
|
{
|
||||||
|
if (args[0].isIndexed())
|
||||||
|
{
|
||||||
|
run.setError (ERR_INVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long_t x = args[0].toInt();
|
||||||
|
|
||||||
|
/*Argument arg;
|
||||||
|
if (run.getGlobal(idLastSleep, arg) == 0)
|
||||||
|
qse_printf (QSE_T("GOOD: [%d]\n"), (int)arg.toInt());
|
||||||
|
else { qse_printf (QSE_T("BAD:\n")); }
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (run.setGlobal (idLastSleep, x) <= -1) return -1;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
::Sleep ((DWORD)(x * 1000));
|
||||||
|
return ret.set ((long_t)0);
|
||||||
|
#else
|
||||||
|
return ret.set ((long_t)::sleep (x));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int sumintarray (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||||
|
const char_t* name, size_t len)
|
||||||
|
{
|
||||||
|
long_t x = 0;
|
||||||
|
|
||||||
|
if (args[0].isIndexed())
|
||||||
|
{
|
||||||
|
Argument idx(run), val(run);
|
||||||
|
|
||||||
|
int n = args[0].getFirstIndex (idx);
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const char_t* ptr = idx.toStr(&len);
|
||||||
|
|
||||||
|
if (args[0].getIndexed(ptr, len, val) <= -1) return -1;
|
||||||
|
x += val.toInt ();
|
||||||
|
|
||||||
|
n = args[0].getNextIndex (idx);
|
||||||
|
}
|
||||||
|
if (n != 0) return -1;
|
||||||
|
}
|
||||||
|
else x += args[0].toInt();
|
||||||
|
|
||||||
|
return ret.set (x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int arrayindices (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||||
|
const char_t* name, size_t len)
|
||||||
|
{
|
||||||
|
if (!args[0].isIndexed()) return 0;
|
||||||
|
|
||||||
|
Argument idx (run);
|
||||||
|
long_t i;
|
||||||
|
|
||||||
|
int n = args[0].getFirstIndex (idx);
|
||||||
|
for (i = 0; n > 0; i++)
|
||||||
|
{
|
||||||
|
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 (n != 0) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Run* parse (const char_t* in, const char_t* out)
|
||||||
|
{
|
||||||
|
srcInName = in;
|
||||||
|
srcOutName = out;
|
||||||
|
return StdAwk::parse ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool onLoopEnter (Run& run)
|
||||||
|
{
|
||||||
|
set_intr_run ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onLoopExit (Run& run, const Argument& ret)
|
||||||
|
{
|
||||||
|
unset_intr_run ();
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const char_t* ptr = ret.toStr (&len);
|
||||||
|
qse_printf (QSE_T("*** return [%.*s] ***\n"), (int)len, ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int openSource (Source& io)
|
||||||
|
{
|
||||||
|
Source::Mode mode = io.getMode();
|
||||||
|
FILE* fp = QSE_NULL;
|
||||||
|
|
||||||
|
// TODO: use sio instead of stdio
|
||||||
|
if (mode == Source::READ)
|
||||||
|
{
|
||||||
|
if (srcInName == QSE_NULL)
|
||||||
|
{
|
||||||
|
io.setHandle (stdin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcInName[0] == QSE_T('\0')) fp = stdin;
|
||||||
|
else fp = qse_fopen (srcInName, QSE_T("r"));
|
||||||
|
}
|
||||||
|
else if (mode == Source::WRITE)
|
||||||
|
{
|
||||||
|
if (srcOutName == QSE_NULL)
|
||||||
|
{
|
||||||
|
io.setHandle (stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcOutName[0] == QSE_T('\0')) fp = stdout;
|
||||||
|
else fp = qse_fopen (srcOutName, QSE_T("w"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp == QSE_NULL) return -1;
|
||||||
|
io.setHandle (fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int closeSource (Source& io)
|
||||||
|
{
|
||||||
|
FILE* fp = (FILE*)io.getHandle();
|
||||||
|
if (fp == stdout || fp == stderr) fflush (fp);
|
||||||
|
if (fp != stdin && fp != stdout && fp != stderr) fclose (fp);
|
||||||
|
io.setHandle (QSE_NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t readSource (Source& io, char_t* buf, size_t len)
|
||||||
|
{
|
||||||
|
FILE* fp = (FILE*)io.getHandle();
|
||||||
|
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)) n = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[n++] = c;
|
||||||
|
if (c == QSE_T('\n')) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t writeSource (Source& io, char_t* buf, size_t len)
|
||||||
|
{
|
||||||
|
FILE* fp = (FILE*)io.getHandle();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* allocMem (size_t n) throw ()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return ::HeapAlloc (heap, 0, n);
|
||||||
|
#else
|
||||||
|
return ::malloc (n);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* reallocMem (void* ptr, size_t n) throw ()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (ptr == NULL)
|
||||||
|
return ::HeapAlloc (heap, 0, n);
|
||||||
|
else
|
||||||
|
return ::HeapReAlloc (heap, 0, ptr, n);
|
||||||
|
#else
|
||||||
|
return ::realloc (ptr, n);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeMem (void* ptr) throw ()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
::HeapFree (heap, 0, ptr);
|
||||||
|
#else
|
||||||
|
::free (ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char_t* srcInName;
|
||||||
|
const char_t* srcOutName;
|
||||||
|
|
||||||
|
int idLastSleep;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
void* heap;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static BOOL WINAPI stop_run (DWORD ctrl_type)
|
||||||
|
{
|
||||||
|
if (ctrl_type == CTRL_C_EVENT ||
|
||||||
|
ctrl_type == CTRL_CLOSE_EVENT)
|
||||||
|
{
|
||||||
|
if (app_awk) app_awk->stop ();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
static int setsignal (int sig, void(*handler)(int), int restart)
|
||||||
|
{
|
||||||
|
struct sigaction sa_int;
|
||||||
|
|
||||||
|
sa_int.sa_handler = handler;
|
||||||
|
sigemptyset (&sa_int.sa_mask);
|
||||||
|
|
||||||
|
sa_int.sa_flags = 0;
|
||||||
|
|
||||||
|
if (restart)
|
||||||
|
{
|
||||||
|
#ifdef SA_RESTART
|
||||||
|
sa_int.sa_flags |= SA_RESTART;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef SA_INTERRUPT
|
||||||
|
sa_int.sa_flags |= SA_INTERRUPT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return sigaction (sig, &sa_int, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stop_run (int sig)
|
||||||
|
{
|
||||||
|
int e = errno;
|
||||||
|
if (app_awk) app_awk->stop ();
|
||||||
|
errno = e;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void set_intr_run (void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleCtrlHandler (stop_run, TRUE);
|
||||||
|
#else
|
||||||
|
/*setsignal (SIGINT, stop_run, 1); TO BE MORE COMPATIBLE WITH WIN32*/
|
||||||
|
setsignal (SIGINT, stop_run, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unset_intr_run (void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleCtrlHandler (stop_run, FALSE);
|
||||||
|
#else
|
||||||
|
setsignal (SIGINT, SIG_DFL, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_error (const qse_char_t* msg)
|
||||||
|
{
|
||||||
|
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
const qse_char_t* name;
|
||||||
|
MyAwk::Option opt;
|
||||||
|
} otab[] =
|
||||||
|
{
|
||||||
|
{ QSE_T("implicit"), MyAwk::OPT_IMPLICIT },
|
||||||
|
{ QSE_T("explicit"), MyAwk::OPT_EXPLICIT },
|
||||||
|
{ QSE_T("bxor"), MyAwk::OPT_BXOR },
|
||||||
|
{ QSE_T("shift"), MyAwk::OPT_SHIFT },
|
||||||
|
{ QSE_T("idiv"), MyAwk::OPT_IDIV },
|
||||||
|
{ QSE_T("rio"), MyAwk::OPT_RIO },
|
||||||
|
{ QSE_T("rwpipe"), MyAwk::OPT_RWPIPE },
|
||||||
|
{ QSE_T("newline"), MyAwk::OPT_NEWLINE },
|
||||||
|
{ QSE_T("stripspaces"), MyAwk::OPT_STRIPSPACES },
|
||||||
|
{ QSE_T("nextofile"), MyAwk::OPT_NEXTOFILE },
|
||||||
|
{ QSE_T("crlf"), MyAwk::OPT_CRLF },
|
||||||
|
{ QSE_T("reset"), MyAwk::OPT_RESET },
|
||||||
|
{ QSE_T("maptovar"), MyAwk::OPT_MAPTOVAR },
|
||||||
|
{ QSE_T("pablock"), MyAwk::OPT_PABLOCK }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void print_usage (const qse_char_t* argv0)
|
||||||
|
{
|
||||||
|
const qse_char_t* base;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
base = qse_strrchr(argv0, QSE_T('/'));
|
||||||
|
if (base == QSE_NULL) base = qse_strrchr(argv0, QSE_T('\\'));
|
||||||
|
if (base == QSE_NULL) base = argv0; else base++;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("Usage: %s [-si file]? [-so file]? [-ci file]* [-co file]* [-w o:n]* \n"), base);
|
||||||
|
qse_printf (QSE_T(" -si file Specify the input source file\n"));
|
||||||
|
qse_printf (QSE_T(" The source code is read from stdin when it is not specified\n"));
|
||||||
|
qse_printf (QSE_T(" -so file Specify the output source file\n"));
|
||||||
|
qse_printf (QSE_T(" The deparsed code is not output when is it not specified\n"));
|
||||||
|
qse_printf (QSE_T(" -ci file Specify the input console file\n"));
|
||||||
|
qse_printf (QSE_T(" -co file Specify the output console file\n"));
|
||||||
|
qse_printf (QSE_T(" -w o:n Specify an old and new word pair\n"));
|
||||||
|
qse_printf (QSE_T(" o - an original word\n"));
|
||||||
|
qse_printf (QSE_T(" n - the new word to replace the original\n"));
|
||||||
|
qse_printf (QSE_T(" -v Print extra messages\n"));
|
||||||
|
|
||||||
|
|
||||||
|
qse_printf (QSE_T("\nYou may specify the following options to change the behavior of the interpreter.\n"));
|
||||||
|
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T(" -%-20s -no%-20s\n"), otab[j].name, otab[j].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int awk_main (int argc, qse_char_t* argv[])
|
||||||
|
{
|
||||||
|
MyAwk awk;
|
||||||
|
MyAwk::Run* run;
|
||||||
|
|
||||||
|
int mode = 0;
|
||||||
|
const qse_char_t* srcin = QSE_T("");
|
||||||
|
const qse_char_t* srcout = NULL;
|
||||||
|
qse_size_t nsrcins = 0;
|
||||||
|
qse_size_t nsrcouts = 0;
|
||||||
|
|
||||||
|
if (awk.open() <= -1)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorMessage());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARGV[0]
|
||||||
|
if (awk.addArgument (QSE_T("awk05")) <= -1)
|
||||||
|
{
|
||||||
|
print_error (awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (mode == 0)
|
||||||
|
{
|
||||||
|
if (qse_strcmp(argv[i], QSE_T("-si")) == 0) mode = 1;
|
||||||
|
else if (qse_strcmp(argv[i], QSE_T("-so")) == 0) mode = 2;
|
||||||
|
else if (qse_strcmp(argv[i], QSE_T("-ci")) == 0) mode = 3;
|
||||||
|
else if (qse_strcmp(argv[i], QSE_T("-co")) == 0) mode = 4;
|
||||||
|
else if (qse_strcmp(argv[i], QSE_T("-w")) == 0) mode = 5;
|
||||||
|
else if (qse_strcmp(argv[i], QSE_T("-v")) == 0)
|
||||||
|
{
|
||||||
|
verbose = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (argv[i][0] == QSE_T('-'))
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (argv[i][1] == QSE_T('n') && argv[i][2] == QSE_T('o'))
|
||||||
|
{
|
||||||
|
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||||
|
{
|
||||||
|
if (qse_strcmp(&argv[i][3], otab[j].name) == 0)
|
||||||
|
{
|
||||||
|
awk.setOption (awk.getOption() & ~otab[j].opt);
|
||||||
|
goto ok_valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||||
|
{
|
||||||
|
if (qse_strcmp(&argv[i][1], otab[j].name) == 0)
|
||||||
|
{
|
||||||
|
awk.setOption (awk.getOption() | otab[j].opt);
|
||||||
|
goto ok_valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_usage (argv[0]);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ok_valid:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (argv[i][0] == QSE_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.addArgument (argv[i]) <= -1)
|
||||||
|
{
|
||||||
|
print_error (QSE_T("too many console inputs"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
else if (mode == 4) // console output
|
||||||
|
{
|
||||||
|
if (awk.addConsoleOutput (argv[i]) <= -1)
|
||||||
|
{
|
||||||
|
print_error (QSE_T("too many console outputs"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
else if (mode == 5) // word replacement
|
||||||
|
{
|
||||||
|
const qse_char_t* p;
|
||||||
|
qse_size_t l;
|
||||||
|
|
||||||
|
p = qse_strchr(argv[i], QSE_T(':'));
|
||||||
|
if (p == QSE_NULL)
|
||||||
|
{
|
||||||
|
print_usage (argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = qse_strlen (argv[i]);
|
||||||
|
|
||||||
|
awk.setWord (
|
||||||
|
argv[i], p - argv[i],
|
||||||
|
p + 1, l - (p - argv[i] + 1));
|
||||||
|
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode != 0)
|
||||||
|
{
|
||||||
|
print_usage (argv[0]);
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
run = awk.parse (srcin, srcout);
|
||||||
|
if (run == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"),
|
||||||
|
awk.getErrorLine(), awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
awk.enableRunCallback ();
|
||||||
|
app_awk = &awk;
|
||||||
|
|
||||||
|
if (awk.loop () <= -1)
|
||||||
|
{
|
||||||
|
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
||||||
|
awk.getErrorLine(), awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
MyAwk::Return args[2];
|
||||||
|
|
||||||
|
args[0].setRun (run);
|
||||||
|
args[1].setRun (run);
|
||||||
|
|
||||||
|
if (awk.call (QSE_T("add"), args, 2) <= -1)
|
||||||
|
{
|
||||||
|
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
||||||
|
awk.getErrorLine(), awk.getErrorMessage());
|
||||||
|
awk.close ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
app_awk = QSE_NULL;
|
||||||
|
awk.close ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qse_main (int argc, qse_achar_t* argv[])
|
||||||
|
{
|
||||||
|
return qse_runmain (argc,argv,awk_main);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user