updated documentation
This commit is contained in:
parent
19b4e697af
commit
6e94d324ef
@ -9,7 +9,6 @@ EXTRA_DIST = \
|
||||
page/mem.doc \
|
||||
page/cenc.doc \
|
||||
page/io.doc \
|
||||
page/awk.doc \
|
||||
page/awk-embed.md \
|
||||
page/awk-lang.md \
|
||||
page/sed.doc \
|
||||
|
@ -234,7 +234,6 @@ EXTRA_DIST = \
|
||||
page/mem.doc \
|
||||
page/cenc.doc \
|
||||
page/io.doc \
|
||||
page/awk.doc \
|
||||
page/awk-embed.md \
|
||||
page/awk-lang.md \
|
||||
page/sed.doc \
|
||||
@ -432,6 +431,9 @@ uninstall-am:
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
|
||||
|
||||
|
||||
all:
|
||||
doxygen
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
@ -62,23 +62,31 @@ functions like *gsub* or *index*.
|
||||
|
||||
\includelineno awk03.c
|
||||
|
||||
If you want to pass arguments to the function you call with qse_awk_rtx_call(),
|
||||
you must create values with value creation functions, updates their reference
|
||||
count, and pass them to qse_awk_rtx_call(). The sample below creates 2 integer
|
||||
values with qse_awk_rtx_makeintval() and pass them to the *pow* function.
|
||||
If you want to pass arguments to the function, you must create values with
|
||||
value creation functions, updates their reference count, and pass them to
|
||||
qse_awk_rtx_call(). The sample below creates 2 integer values with
|
||||
qse_awk_rtx_makeintval() and pass them to the *pow* function.
|
||||
|
||||
\includelineno awk04.c
|
||||
|
||||
While qse_awk_rtx_call() looks up a function in the function table by name,
|
||||
you can find the function in advance and use the information found when
|
||||
calling a function. qse_awk_rtx_findfun() and qse_awk_rtx_callfun() come
|
||||
to play a role in this situation. qse_awk_rtx_call() in the sample above
|
||||
can be translated into 2 separate calls to qse_awk_rtx_findfun() and
|
||||
qse_awk_rtx_callfun(). You can reduce look-up overhead via these 2
|
||||
functions if you have to execute the same function multiple times.
|
||||
calling it. qse_awk_rtx_findfun() and qse_awk_rtx_callfun() come to play a role
|
||||
in this situation. qse_awk_rtx_call() in the sample above can be translated
|
||||
into 2 separate calls to qse_awk_rtx_findfun() and qse_awk_rtx_callfun().
|
||||
You can reduce look-up overhead via these 2 functions if you are to execute
|
||||
the same function multiple times.
|
||||
|
||||
\includelineno awk05.c
|
||||
|
||||
Similarly, you can pass a more complex value than a number. You can compose
|
||||
a map value with qse_awk_rtx_makemapval() or qse_awk_rtx_makemapvalwithdata().
|
||||
The sample below demonstrates how to use qse_awk_rtx_makemapvalwithdata(),
|
||||
pass a created map value to qse_awk_rtx_call(), and traverse a map value
|
||||
returned with qse_awk_rtx_getfirstmapvalitr() and qse_awk_rtx_getnextmapvalitr().
|
||||
|
||||
\includelineno awk06.c
|
||||
|
||||
Global Variables
|
||||
----------------
|
||||
|
||||
@ -91,6 +99,29 @@ Built-in Functions
|
||||
You can add built-in functions with qse_awk_addfnc().
|
||||
On the other hand, modular built-in functions reside in a shared object.
|
||||
|
||||
Single Script over Multiple Data Streams
|
||||
----------------------------------------
|
||||
|
||||
Customizing Language Features
|
||||
-----------------------------
|
||||
|
||||
Creating multiple awk objects
|
||||
-----------------------------
|
||||
|
||||
Memory Pool
|
||||
-----------
|
||||
|
||||
Embedding in C++
|
||||
-----------------
|
||||
|
||||
The QSE::Awk class and QSE::StdAwk classe wrap the underlying C library routines
|
||||
for better object-orientation. These two classes are defined in <qse/awk/Awk.hpp>
|
||||
and <qse/awk/StdAwk.hpp> respectively. The embedding task can be simplified despite
|
||||
slight performance overhead. The hello-world sample in C can be rewritten with
|
||||
less numbers of lines in C++.
|
||||
|
||||
\includelineno awk21.cpp
|
||||
|
||||
Changes in 0.6.0
|
||||
----------------
|
||||
|
||||
|
@ -1,180 +0,0 @@
|
||||
/** @page awk AWK
|
||||
|
||||
@section awk-content CONTENTS
|
||||
- @ref awk-intro "INTRODUCTION"
|
||||
|
||||
@section awk-intro INTRODUCTION
|
||||
|
||||
QSEAWK is an AWK interpreter and is a part of the @ref qse_intro "QSE" library.
|
||||
Its design focuses on building a flexible and robust embedding API with minimal
|
||||
platform dependency. An embedding application is capable of:
|
||||
- adding new global variables and functions.
|
||||
- getting and set the value of a global variable.
|
||||
- calling a function with or without parameters and getting its return value.
|
||||
- customizing I/O handlers for file, pipe, console I/O.
|
||||
- creating multiple interpreters independent of each other.
|
||||
- running a single script with different I/O streams independently.
|
||||
- changing language features by setting options.
|
||||
- and more
|
||||
|
||||
The library implements AWK in multiple levels:
|
||||
|
||||
- base interpreter
|
||||
- standard interpreter
|
||||
- parallel interpreter
|
||||
|
||||
The base interpreter provides most core language features while minimizing
|
||||
platform dependence. When working with the base interpreter, you're required
|
||||
to write primtive operation handlers like I/O and pass them in to make it
|
||||
useful. The standard interpreter is usable immediately since it implements
|
||||
all the primitive operations required by the base interpreter and adds
|
||||
standard AWK functions. The parallel interpreter enables parallel processing
|
||||
by adding various MPI variables and functions to the standard interpreter.
|
||||
|
||||
Embedding a standard interpreter typically involves the following steps.
|
||||
|
||||
- open a new interpreter
|
||||
- parse in a source script
|
||||
- open a new runtime context
|
||||
- execute pattern-action blocks or call a function
|
||||
- close the runtime context
|
||||
- close the interpter
|
||||
|
||||
The code example below demonstrates the steps in C. It executes the one liner
|
||||
<b>BEGIN { print "hello, world" }</b>.
|
||||
|
||||
@code
|
||||
/* cc -o hello hello.c -lqseawk -lqsecmn -lm */
|
||||
#include <qse/awk/std.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
|
||||
#define FAIL(msg) do { qse_printf(QSE_T("ERR: %s\n"),msg); goto oops; } while(0)
|
||||
|
||||
int main ()
|
||||
{
|
||||
qse_awk_t* awk = QSE_NULL;
|
||||
qse_awk_rtx_t* rtx = QSE_NULL;
|
||||
qse_awk_val_t* retv;
|
||||
qse_awk_parsestd_t psin;
|
||||
int ret = -1;
|
||||
|
||||
awk = qse_awk_openstd (0); /* open a new interpreter */
|
||||
if (!awk) FAIL ("cannot open awk");
|
||||
|
||||
/* parse the hello world script from a string */
|
||||
psin.type = QSE_AWK_PARSESTD_STR;
|
||||
psin.u.str.ptr = QSE_T("BEGIN { print \"hello, world\" }");
|
||||
psin.u.str.len = qse_strlen(psin.u.str.ptr);
|
||||
if (qse_awk_parsestd (awk, &psin, QSE_NULL) <= -1)
|
||||
FAIL (qse_awk_geterrmsg(awk));
|
||||
|
||||
rtx = qse_awk_rtx_openstd ( /* open a runtime context */
|
||||
awk, 0, /* no extension */
|
||||
QSE_T("hello"), /* ARGV[0] */
|
||||
QSE_NULL, /* stdin */
|
||||
QSE_NULL, /* stdout */
|
||||
QSE_NULL /* default cmgr */
|
||||
);
|
||||
if (!rtx) FAIL (qse_awk_geterrmsg(awk));
|
||||
|
||||
/* exeucte pattern-action blocks */
|
||||
retv = qse_awk_rtx_loop (rtx);
|
||||
if (!retv) FAIL (qse_awk_rtx_geterrmsg(rtx));
|
||||
|
||||
qse_awk_rtx_refdownval (rtx, retv); /* destroy the return value */
|
||||
ret = 0;
|
||||
|
||||
oops:
|
||||
if (rtx) qse_awk_rtx_close (rtx); /* close the runtime context */
|
||||
if (awk) qse_awk_close (awk); /* close the interpreter */
|
||||
return ret;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Things can get simpler when you use C++ API. Note that the C++ API supports
|
||||
1 single runtime context for each interpreter.
|
||||
|
||||
@code
|
||||
/* c++ -o hello hello.cpp -lqseawkxx -lqseawk -lqsecmnxx -lqsecmn -lm */
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef QSE_CHAR_IS_MCHAR
|
||||
# define xcout std::cout
|
||||
#else
|
||||
# define xcout std::wcout
|
||||
#endif
|
||||
|
||||
struct MyAwk: public QSE::StdAwk { ~MyAwk () { QSE::StdAwk::close (); } };
|
||||
|
||||
#define FAIL(awk) do { \
|
||||
xcout << QSE_T("ERR: ") << awk.getErrorMessage() << std::endl; \
|
||||
return -1; \
|
||||
} while (0)
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
MyAwk awk;
|
||||
|
||||
// open a new interpreter
|
||||
if (awk.open () <= -1) FAIL (awk);
|
||||
|
||||
// set ARGV[0]
|
||||
if (awk.addArgument (QSE_T("hello")) <= -1) FAIL (awk);
|
||||
|
||||
// parse the source script string
|
||||
MyAwk::SourceString in(QSE_T("BEGIN { print \"hello, world\" }"));
|
||||
if (awk.parse (in, MyAwk::Source::NONE) == QSE_NULL) FAIL (awk);
|
||||
|
||||
// execute pattern-action blocks.
|
||||
MyAwk::Value r;
|
||||
if (awk.loop (&r) <= -1) FAIL (awk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
This library also provides a stand-alone AWK interpreter that you can use
|
||||
in a console environment. The source code is located under the
|
||||
<project-root>/cmd/awk subdirectory. See the usage below.
|
||||
|
||||
@code
|
||||
$ qseawk
|
||||
USAGE: qseawk [options] -f sourcefile [ -- ] [datafile]*
|
||||
qseawk [options] [ -- ] sourcestring [datafile]*
|
||||
Where options are:
|
||||
-h/--help print this message
|
||||
--version print version
|
||||
-D show extra information
|
||||
-c/--call name call a function instead of entering
|
||||
the pattern-action loop
|
||||
-f/--file sourcefile set the source script file
|
||||
-d/--deparsed-file deparsedfile set the deparsing output file
|
||||
-F/--field-separator string set a field separator(FS)
|
||||
-v/--assign var=value add a global variable with a value
|
||||
-m/--memory-limit number limit the memory usage (bytes)
|
||||
-X number fail the number'th memory allocation
|
||||
--script-encoding string specify script file encoding name
|
||||
--console-encoding string specify console encoding name
|
||||
--implicit on/off allow undeclared variables
|
||||
--explicit on/off allow declared variables(local,global)
|
||||
--extraops on/off enable extra operators(<<,>>,^^,\)
|
||||
--rio on/off enable builtin I/O including getline & print
|
||||
--rwpipe on/off allow a dual-directional pipe
|
||||
--newline on/off enable a newline to terminate a statement
|
||||
--striprecspc on/off strip spaces in splitting a record
|
||||
--stripstrspc on/off strip spaces in converting a string to a number
|
||||
--nextofile on/off enable 'nextofile'
|
||||
--reset on/off enable 'reset'
|
||||
--crlf on/off use CRLF for a newline
|
||||
--maptovar on/off allow a map to be assigned or returned
|
||||
--pablock on/off enable pattern-action loop
|
||||
--rexbound on/off enable {n,m} in a regular expression
|
||||
--ncmponstr on/off perform numeric comparsion on numeric strings
|
||||
--strictnaming on/off enable the strict naming rule
|
||||
--include on/off enable '@include'
|
||||
--tolerant on/off make more I/O fault-tolerant
|
||||
--abort on/off enable 'abort'
|
||||
@endcode
|
||||
|
||||
*/
|
@ -13,7 +13,7 @@ aspects of embedding application and an embedded object from each other.
|
||||
The library is licensed under the GNU Lesser General Public License version 3:
|
||||
http://www.gnu.org/licenses/
|
||||
|
||||
The project webpage: http://code.abiyo.net/@qse
|
||||
The project webpage: http://code.abiyo.net/@qse or http://qse.googlecode.com
|
||||
|
||||
For further information, contact:
|
||||
Chung, Hyung-Hwan <hyunghwan.chung@gmail.com>
|
||||
@ -21,11 +21,10 @@ Chung, Hyung-Hwan <hyunghwan.chung@gmail.com>
|
||||
See the subpages for more information.
|
||||
|
||||
- @ref installation
|
||||
- @ref awk-lang
|
||||
- @ref awk-embed
|
||||
- @subpage mem "Memory Management"
|
||||
- @subpage cenc "Character Encoding"
|
||||
- @subpage io "I/O Handling"
|
||||
- @subpage awk "AWK Interpreter"
|
||||
- @subpage sed "SED Stream Editor"
|
||||
- @subpage awk-lang
|
||||
- @subpage awk-embed
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
/// @file
|
||||
/// AWK Interpreter
|
||||
///
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
|
@ -27,33 +27,6 @@
|
||||
|
||||
/// @file
|
||||
/// Standard AWK Interpreter
|
||||
///
|
||||
/// @example awk05.cpp
|
||||
/// This program demonstrates how to use QSE::StdAwk::loop().
|
||||
///
|
||||
/// @example awk06.cpp
|
||||
/// This program demonstrates how to use QSE::StdAwk::call().
|
||||
///
|
||||
/// @example awk07.cpp
|
||||
/// This program demonstrates how to handle an indexed value.
|
||||
///
|
||||
/// @example awk08.cpp
|
||||
/// This program shows how to add intrinsic functions.
|
||||
///
|
||||
/// @example awk12.cpp
|
||||
/// This program shows how to override console methods to use
|
||||
/// string buffers for console input and output.
|
||||
///
|
||||
/// @example awk13.cpp
|
||||
/// This program shows how to use resetRunContext(). It is similar
|
||||
/// to awk12.cpp in principle.
|
||||
///
|
||||
/// @example awk14.cpp
|
||||
/// This program shows how to define a console handler to use
|
||||
/// string buffers for console input and output. It is identical
|
||||
/// to awk13.cpp except that it relies an external console handler
|
||||
/// rather than overriding console methods.
|
||||
///
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,7 @@
|
||||
#include <qse/awk/awk.h>
|
||||
#include <qse/cmn/sio.h>
|
||||
|
||||
/** @file
|
||||
/** \file
|
||||
* This file defines functions and data types that help you create
|
||||
* an awk interpreter with less effort. It is designed to be as close
|
||||
* to conventional awk implementations as possible.
|
||||
@ -34,16 +34,6 @@
|
||||
* normal file name.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example awk09.c
|
||||
* This programs shows how to specify multiple console output files.
|
||||
*
|
||||
* @example awk11.c
|
||||
* This programs shows how to extend an I/O handler implemented by
|
||||
* qse_awk_rtx_openstd().
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The qse_awk_parsestd_type_t type defines the types of source I/O.
|
||||
*/
|
||||
@ -128,7 +118,7 @@ QSE_EXPORT void* qse_awk_getxtnstd (
|
||||
* The qse_awk_parsestd() functions parses source script.
|
||||
* The code below shows how to parse a literal string 'BEGIN { print 10; }'
|
||||
* and deparses it out to a buffer 'buf'.
|
||||
* @code
|
||||
* \code
|
||||
* int n;
|
||||
* qse_awk_parsestd_t in[2];
|
||||
* qse_awk_parsestd_t out;
|
||||
@ -144,7 +134,7 @@ QSE_EXPORT void* qse_awk_getxtnstd (
|
||||
* qse_printf (QSE_T("%s\n"), out.u.str.ptr);
|
||||
* QSE_MMGR_FREE (out.u.str.ptr);
|
||||
* }
|
||||
* @endcode
|
||||
* \endcode
|
||||
*/
|
||||
QSE_EXPORT int qse_awk_parsestd (
|
||||
qse_awk_t* awk,
|
||||
@ -154,9 +144,9 @@ QSE_EXPORT int qse_awk_parsestd (
|
||||
|
||||
/**
|
||||
* The qse_awk_rtx_openstd() function creates a standard runtime context.
|
||||
* The caller should keep the contents of @a icf and @a ocf valid throughout
|
||||
* the lifetime of the runtime context created. The @a cmgr is set to the
|
||||
* streams created with @a icf and @a ocf if it is not #QSE_NULL.
|
||||
* The caller should keep the contents of \a icf and \a ocf valid throughout
|
||||
* the lifetime of the runtime context created. The \a cmgr is set to the
|
||||
* streams created with \a icf and \a ocf if it is not #QSE_NULL.
|
||||
*/
|
||||
QSE_EXPORT qse_awk_rtx_t* qse_awk_rtx_openstd (
|
||||
qse_awk_t* awk,
|
||||
@ -178,7 +168,7 @@ QSE_EXPORT void* qse_awk_rtx_getxtnstd (
|
||||
/**
|
||||
* The qse_awk_rtx_getcmgrstd() function gets the current character
|
||||
* manager associated with a particular I/O target indicated by the name
|
||||
* @a ioname if #QSE_CHAR_IS_WCHAR is defined. It always returns #QSE_NULL
|
||||
* \a ioname if #QSE_CHAR_IS_WCHAR is defined. It always returns #QSE_NULL
|
||||
* if #QSE_CHAR_IS_MCHAR is defined.
|
||||
*/
|
||||
QSE_EXPORT qse_cmgr_t* qse_awk_rtx_getcmgrstd (
|
||||
|
@ -5,7 +5,7 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(includedir)
|
||||
|
||||
bin_PROGRAMS = awk01 awk02 awk03 awk04 awk05 awk09 awk10 awk11 awk15
|
||||
bin_PROGRAMS = awk01 awk02 awk03 awk04 awk05 awk06 awk09 awk11 awk15
|
||||
|
||||
LDFLAGS = -L../../lib/awk -L../../lib/cmn
|
||||
LDADD = -lqseawk -lqsecmn $(LIBM)
|
||||
@ -21,8 +21,8 @@ awk02_SOURCES = awk02.c
|
||||
awk03_SOURCES = awk03.c
|
||||
awk04_SOURCES = awk04.c
|
||||
awk05_SOURCES = awk05.c
|
||||
awk06_SOURCES = awk06.c
|
||||
awk09_SOURCES = awk09.c
|
||||
awk10_SOURCES = awk10.c
|
||||
awk11_SOURCES = awk11.c
|
||||
awk15_SOURCES = awk15.c
|
||||
|
||||
@ -30,7 +30,7 @@ if ENABLE_CXX
|
||||
|
||||
CXXLIB = -lqseawkxx -lqsecmnxx
|
||||
|
||||
bin_PROGRAMS += awk21 awk22 awk23 awk24 awk25 awk26 awk27
|
||||
bin_PROGRAMS += awk21 awk22 awk23 awk24 awk25 awk26 awk27 awk28
|
||||
|
||||
awk21_SOURCES = awk21.cpp
|
||||
awk22_SOURCES = awk22.cpp
|
||||
@ -39,6 +39,7 @@ awk24_SOURCES = awk24.cpp
|
||||
awk25_SOURCES = awk25.cpp
|
||||
awk26_SOURCES = awk26.cpp
|
||||
awk27_SOURCES = awk27.cpp
|
||||
awk28_SOURCES = awk27.cpp
|
||||
|
||||
awk21_LDADD = $(CXXLIB) $(LDADD)
|
||||
awk22_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ -47,4 +48,5 @@ awk24_LDADD = $(CXXLIB) $(LDADD)
|
||||
awk25_LDADD = $(CXXLIB) $(LDADD)
|
||||
awk26_LDADD = $(CXXLIB) $(LDADD)
|
||||
awk27_LDADD = $(CXXLIB) $(LDADD)
|
||||
awk28_LDADD = $(CXXLIB) $(LDADD)
|
||||
endif
|
||||
|
@ -35,10 +35,10 @@ POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
bin_PROGRAMS = awk01$(EXEEXT) awk02$(EXEEXT) awk03$(EXEEXT) \
|
||||
awk04$(EXEEXT) awk05$(EXEEXT) awk09$(EXEEXT) awk10$(EXEEXT) \
|
||||
awk04$(EXEEXT) awk05$(EXEEXT) awk06$(EXEEXT) awk09$(EXEEXT) \
|
||||
awk11$(EXEEXT) awk15$(EXEEXT) $(am__EXEEXT_1)
|
||||
@WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS)
|
||||
@ENABLE_CXX_TRUE@am__append_2 = awk21 awk22 awk23 awk24 awk25 awk26 awk27
|
||||
@ENABLE_CXX_TRUE@am__append_2 = awk21 awk22 awk23 awk24 awk25 awk26 awk27 awk28
|
||||
subdir = samples/awk
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
@ -56,7 +56,7 @@ CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
@ENABLE_CXX_TRUE@am__EXEEXT_1 = awk21$(EXEEXT) awk22$(EXEEXT) \
|
||||
@ENABLE_CXX_TRUE@ awk23$(EXEEXT) awk24$(EXEEXT) awk25$(EXEEXT) \
|
||||
@ENABLE_CXX_TRUE@ awk26$(EXEEXT) awk27$(EXEEXT)
|
||||
@ENABLE_CXX_TRUE@ awk26$(EXEEXT) awk27$(EXEEXT) awk28$(EXEEXT)
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_awk01_OBJECTS = awk01.$(OBJEXT)
|
||||
@ -81,14 +81,14 @@ am_awk05_OBJECTS = awk05.$(OBJEXT)
|
||||
awk05_OBJECTS = $(am_awk05_OBJECTS)
|
||||
awk05_LDADD = $(LDADD)
|
||||
awk05_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
|
||||
am_awk06_OBJECTS = awk06.$(OBJEXT)
|
||||
awk06_OBJECTS = $(am_awk06_OBJECTS)
|
||||
awk06_LDADD = $(LDADD)
|
||||
awk06_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
|
||||
am_awk09_OBJECTS = awk09.$(OBJEXT)
|
||||
awk09_OBJECTS = $(am_awk09_OBJECTS)
|
||||
awk09_LDADD = $(LDADD)
|
||||
awk09_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
|
||||
am_awk10_OBJECTS = awk10.$(OBJEXT)
|
||||
awk10_OBJECTS = $(am_awk10_OBJECTS)
|
||||
awk10_LDADD = $(LDADD)
|
||||
awk10_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
|
||||
am_awk11_OBJECTS = awk11.$(OBJEXT)
|
||||
awk11_OBJECTS = $(am_awk11_OBJECTS)
|
||||
awk11_LDADD = $(LDADD)
|
||||
@ -133,6 +133,11 @@ am__awk27_SOURCES_DIST = awk27.cpp
|
||||
awk27_OBJECTS = $(am_awk27_OBJECTS)
|
||||
@ENABLE_CXX_TRUE@awk27_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
||||
@ENABLE_CXX_TRUE@ $(am__DEPENDENCIES_3)
|
||||
am__awk28_SOURCES_DIST = awk27.cpp
|
||||
@ENABLE_CXX_TRUE@am_awk28_OBJECTS = awk27.$(OBJEXT)
|
||||
awk28_OBJECTS = $(am_awk28_OBJECTS)
|
||||
@ENABLE_CXX_TRUE@awk28_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
||||
@ENABLE_CXX_TRUE@ $(am__DEPENDENCIES_3)
|
||||
DEFAULT_INCLUDES =
|
||||
depcomp = $(SHELL) $(top_srcdir)/ac/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@ -156,18 +161,18 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
||||
$(awk04_SOURCES) $(awk05_SOURCES) $(awk09_SOURCES) \
|
||||
$(awk10_SOURCES) $(awk11_SOURCES) $(awk15_SOURCES) \
|
||||
$(awk04_SOURCES) $(awk05_SOURCES) $(awk06_SOURCES) \
|
||||
$(awk09_SOURCES) $(awk11_SOURCES) $(awk15_SOURCES) \
|
||||
$(awk21_SOURCES) $(awk22_SOURCES) $(awk23_SOURCES) \
|
||||
$(awk24_SOURCES) $(awk25_SOURCES) $(awk26_SOURCES) \
|
||||
$(awk27_SOURCES)
|
||||
$(awk27_SOURCES) $(awk28_SOURCES)
|
||||
DIST_SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
||||
$(awk04_SOURCES) $(awk05_SOURCES) $(awk09_SOURCES) \
|
||||
$(awk10_SOURCES) $(awk11_SOURCES) $(awk15_SOURCES) \
|
||||
$(awk04_SOURCES) $(awk05_SOURCES) $(awk06_SOURCES) \
|
||||
$(awk09_SOURCES) $(awk11_SOURCES) $(awk15_SOURCES) \
|
||||
$(am__awk21_SOURCES_DIST) $(am__awk22_SOURCES_DIST) \
|
||||
$(am__awk23_SOURCES_DIST) $(am__awk24_SOURCES_DIST) \
|
||||
$(am__awk25_SOURCES_DIST) $(am__awk26_SOURCES_DIST) \
|
||||
$(am__awk27_SOURCES_DIST)
|
||||
$(am__awk27_SOURCES_DIST) $(am__awk28_SOURCES_DIST)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
@ -354,8 +359,8 @@ awk02_SOURCES = awk02.c
|
||||
awk03_SOURCES = awk03.c
|
||||
awk04_SOURCES = awk04.c
|
||||
awk05_SOURCES = awk05.c
|
||||
awk06_SOURCES = awk06.c
|
||||
awk09_SOURCES = awk09.c
|
||||
awk10_SOURCES = awk10.c
|
||||
awk11_SOURCES = awk11.c
|
||||
awk15_SOURCES = awk15.c
|
||||
@ENABLE_CXX_TRUE@CXXLIB = -lqseawkxx -lqsecmnxx
|
||||
@ -366,6 +371,7 @@ awk15_SOURCES = awk15.c
|
||||
@ENABLE_CXX_TRUE@awk25_SOURCES = awk25.cpp
|
||||
@ENABLE_CXX_TRUE@awk26_SOURCES = awk26.cpp
|
||||
@ENABLE_CXX_TRUE@awk27_SOURCES = awk27.cpp
|
||||
@ENABLE_CXX_TRUE@awk28_SOURCES = awk27.cpp
|
||||
@ENABLE_CXX_TRUE@awk21_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk22_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk23_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ -373,6 +379,7 @@ awk15_SOURCES = awk15.c
|
||||
@ENABLE_CXX_TRUE@awk25_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk26_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk27_LDADD = $(CXXLIB) $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk28_LDADD = $(CXXLIB) $(LDADD)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
@ -465,12 +472,12 @@ awk04$(EXEEXT): $(awk04_OBJECTS) $(awk04_DEPENDENCIES) $(EXTRA_awk04_DEPENDENCIE
|
||||
awk05$(EXEEXT): $(awk05_OBJECTS) $(awk05_DEPENDENCIES) $(EXTRA_awk05_DEPENDENCIES)
|
||||
@rm -f awk05$(EXEEXT)
|
||||
$(LINK) $(awk05_OBJECTS) $(awk05_LDADD) $(LIBS)
|
||||
awk06$(EXEEXT): $(awk06_OBJECTS) $(awk06_DEPENDENCIES) $(EXTRA_awk06_DEPENDENCIES)
|
||||
@rm -f awk06$(EXEEXT)
|
||||
$(LINK) $(awk06_OBJECTS) $(awk06_LDADD) $(LIBS)
|
||||
awk09$(EXEEXT): $(awk09_OBJECTS) $(awk09_DEPENDENCIES) $(EXTRA_awk09_DEPENDENCIES)
|
||||
@rm -f awk09$(EXEEXT)
|
||||
$(LINK) $(awk09_OBJECTS) $(awk09_LDADD) $(LIBS)
|
||||
awk10$(EXEEXT): $(awk10_OBJECTS) $(awk10_DEPENDENCIES) $(EXTRA_awk10_DEPENDENCIES)
|
||||
@rm -f awk10$(EXEEXT)
|
||||
$(LINK) $(awk10_OBJECTS) $(awk10_LDADD) $(LIBS)
|
||||
awk11$(EXEEXT): $(awk11_OBJECTS) $(awk11_DEPENDENCIES) $(EXTRA_awk11_DEPENDENCIES)
|
||||
@rm -f awk11$(EXEEXT)
|
||||
$(LINK) $(awk11_OBJECTS) $(awk11_LDADD) $(LIBS)
|
||||
@ -498,6 +505,9 @@ awk26$(EXEEXT): $(awk26_OBJECTS) $(awk26_DEPENDENCIES) $(EXTRA_awk26_DEPENDENCIE
|
||||
awk27$(EXEEXT): $(awk27_OBJECTS) $(awk27_DEPENDENCIES) $(EXTRA_awk27_DEPENDENCIES)
|
||||
@rm -f awk27$(EXEEXT)
|
||||
$(CXXLINK) $(awk27_OBJECTS) $(awk27_LDADD) $(LIBS)
|
||||
awk28$(EXEEXT): $(awk28_OBJECTS) $(awk28_DEPENDENCIES) $(EXTRA_awk28_DEPENDENCIES)
|
||||
@rm -f awk28$(EXEEXT)
|
||||
$(CXXLINK) $(awk28_OBJECTS) $(awk28_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
@ -510,8 +520,8 @@ distclean-compile:
|
||||
@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)/awk05.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk06.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk09.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk10.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk11.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk15.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk21.Po@am__quote@
|
||||
|
@ -1,23 +1,3 @@
|
||||
/*
|
||||
* $Id: awk04.c 441 2011-04-22 14:28:43Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2012 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
|
||||
QSE is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
QSE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/awk/std.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
|
||||
@ -32,20 +12,18 @@ int main ()
|
||||
qse_awk_parsestd_t psin[2];
|
||||
qse_awk_val_t* rtv = QSE_NULL;
|
||||
qse_awk_val_t* arg = QSE_NULL;
|
||||
int ret, i, opt;
|
||||
struct
|
||||
int ret, opt;
|
||||
|
||||
/* this structure is passed to qse_awk_rtx_makemapvalwithdata() */
|
||||
qse_awk_val_map_data_t md[] =
|
||||
{
|
||||
const qse_char_t* kptr;
|
||||
qse_size_t klen;
|
||||
const qse_char_t* vptr;
|
||||
} xxx[] =
|
||||
{
|
||||
{ QSE_T("f0"), 2, QSE_T("linux") },
|
||||
{ QSE_T("f1"), 2, QSE_T("openvms") },
|
||||
{ QSE_T("f2"), 2, QSE_T("hpux") }
|
||||
{ { QSE_T("f0"), 2 }, QSE_AWK_VAL_MAP_DATA_STR, QSE_T("linux") },
|
||||
{ { QSE_T("f1"), 2 }, QSE_AWK_VAL_MAP_DATA_STR, QSE_T("openvms") },
|
||||
{ { QSE_T("f2"), 2 }, QSE_AWK_VAL_MAP_DATA_STR, QSE_T("hpux") },
|
||||
{ { QSE_NULL, 0 }, 0, QSE_NULL } /* last item */
|
||||
};
|
||||
|
||||
/* create a main processor */
|
||||
/* create a standard awk object */
|
||||
awk = qse_awk_openstd (0);
|
||||
if (awk == QSE_NULL)
|
||||
{
|
||||
@ -53,18 +31,20 @@ int main ()
|
||||
ret = -1; goto oops;
|
||||
}
|
||||
|
||||
/* get the awk's trait */
|
||||
qse_awk_getopt (awk, QSE_AWK_TRAIT, &opt);
|
||||
/* don't allow BEGIN, END, pattern-action blocks */
|
||||
/* change the trait value to disallow BEGIN, END, pattern-action blocks */
|
||||
opt &= ~QSE_AWK_PABLOCK;
|
||||
/* can assign a map to a variable */
|
||||
opt |= QSE_AWK_FLEXMAP;
|
||||
/* update the trait */
|
||||
qse_awk_setopt (awk, QSE_AWK_TRAIT, &opt);
|
||||
|
||||
/* prepare a script to parse */
|
||||
psin[0].type = QSE_AWK_PARSESTD_STR;
|
||||
psin[0].u.str.ptr = src;
|
||||
psin[0].u.str.len = qse_strlen(src);
|
||||
psin[1].type = QSE_AWK_PARSESTD_NULL;
|
||||
|
||||
/* parse the script */
|
||||
ret = qse_awk_parsestd (awk, psin, QSE_NULL);
|
||||
if (ret == -1)
|
||||
{
|
||||
@ -73,11 +53,11 @@ int main ()
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* create a runtime context */
|
||||
/* create a standard runtime context */
|
||||
rtx = qse_awk_rtx_openstd (
|
||||
awk,
|
||||
0,
|
||||
QSE_T("awk10"),
|
||||
QSE_T("awk06"),
|
||||
QSE_NULL, /* stdin */
|
||||
QSE_NULL, /* stdout */
|
||||
QSE_NULL /* default cmgr */
|
||||
@ -90,8 +70,8 @@ int main ()
|
||||
ret = -1; goto oops;
|
||||
}
|
||||
|
||||
/* prepare a argument to be a map */
|
||||
arg = qse_awk_rtx_makemapval (rtx);
|
||||
/* create a map value to pass as an argument */
|
||||
arg = qse_awk_rtx_makemapvalwithdata (rtx, md);
|
||||
if (arg == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"),
|
||||
@ -100,30 +80,7 @@ int main ()
|
||||
}
|
||||
qse_awk_rtx_refupval (rtx, arg);
|
||||
|
||||
/* insert some key/value pairs into the map */
|
||||
for (i = 0; i < QSE_COUNTOF(xxx); i++)
|
||||
{
|
||||
qse_awk_val_t* v, * fv;
|
||||
|
||||
fv = qse_awk_rtx_makestrvalwithstr (rtx, xxx[i].vptr);
|
||||
if (fv == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"),
|
||||
qse_awk_rtx_geterrmsg(rtx));
|
||||
ret = -1; goto oops;
|
||||
}
|
||||
qse_awk_rtx_refupval (rtx, fv);
|
||||
v = qse_awk_rtx_setmapvalfld (rtx, arg, xxx[i].kptr, xxx[i].klen, fv);
|
||||
qse_awk_rtx_refdownval (rtx, fv);
|
||||
if (v == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"),
|
||||
qse_awk_rtx_geterrmsg(rtx));
|
||||
ret = -1; goto oops;
|
||||
}
|
||||
}
|
||||
|
||||
/* invoke the dump function */
|
||||
/* execute the dump function in the awk script */
|
||||
rtv = qse_awk_rtx_call (rtx, QSE_T("dump"), &arg, 1);
|
||||
if (rtv == QSE_NULL)
|
||||
{
|
||||
@ -132,17 +89,21 @@ int main ()
|
||||
ret = -1; goto oops;
|
||||
}
|
||||
|
||||
/* print the return value */
|
||||
if (rtv->type == QSE_AWK_VAL_MAP)
|
||||
{
|
||||
/* if a returned value is a map,
|
||||
* traverse the map and print the key/value pairs. */
|
||||
|
||||
qse_awk_val_map_itr_t itr;
|
||||
qse_awk_val_map_itr_t* iptr;
|
||||
|
||||
/* get the iterator to the first key/value pair */
|
||||
iptr = qse_awk_rtx_getfirstmapvalitr (rtx, rtv, &itr);
|
||||
while (iptr)
|
||||
{
|
||||
qse_xstr_t str;
|
||||
|
||||
/* #QSE_AWK_VAL_MAP_ITR_VAL returns the value part */
|
||||
str.ptr = qse_awk_rtx_valtostrdup (
|
||||
rtx, QSE_AWK_VAL_MAP_ITR_VAL(iptr), &str.len);
|
||||
if (str.ptr == QSE_NULL)
|
||||
@ -152,6 +113,7 @@ int main ()
|
||||
ret = -1; goto oops;
|
||||
}
|
||||
|
||||
/* #QSE_AWK_VAL_MAP_ITR_KEY returns the key part */
|
||||
qse_printf (QSE_T("ret [%.*s]=[%.*s]\n"),
|
||||
(int)QSE_AWK_VAL_MAP_ITR_KEY(iptr)->len,
|
||||
QSE_AWK_VAL_MAP_ITR_KEY(iptr)->ptr,
|
||||
@ -159,11 +121,14 @@ int main ()
|
||||
);
|
||||
qse_awk_rtx_freemem (rtx, str.ptr);
|
||||
|
||||
/* get the iterator to the next key/value pair */
|
||||
iptr = qse_awk_rtx_getnextmapvalitr (rtx, rtv, &itr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if it is a plain value, convert it to a string
|
||||
* and print it */
|
||||
qse_xstr_t str;
|
||||
|
||||
str.ptr = qse_awk_rtx_valtostrdup (rtx, rtv, &str.len);
|
||||
@ -187,7 +152,9 @@ oops:
|
||||
|
||||
/* destroy a runtime context */
|
||||
if (rtx) qse_awk_rtx_close (rtx);
|
||||
|
||||
/* destroy the processor */
|
||||
if (awk) qse_awk_close (awk);
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,105 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright 2006-2012 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
|
||||
QSE is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
QSE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/main.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <locale.h>
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
static void print_error (
|
||||
const QSE::StdAwk::loc_t& loc, const QSE::StdAwk::char_t* msg)
|
||||
{
|
||||
if (loc.line > 0 || loc.colm > 0)
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu COLUMN %lu\n"), msg, loc.line, loc.colm);
|
||||
else
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
|
||||
}
|
||||
|
||||
static int run_awk (QSE::StdAwk& awk)
|
||||
{
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk05")) <= -1) return -1;
|
||||
|
||||
// ARGV[1] and/or the first console input file
|
||||
if (awk.addArgument (QSE_T("Makefile")) <= -1) 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.
|
||||
if (awk.parse (in, out) == QSE_NULL) return -1;
|
||||
|
||||
QSE::StdAwk::Value r;
|
||||
// execute the BEGIN, pattern-action, END blocks.
|
||||
return awk.loop (&r);
|
||||
}
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
QSE::StdAwk awk;
|
||||
|
||||
int ret = awk.open ();
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
|
||||
if (ret <= -1)
|
||||
{
|
||||
QSE::StdAwk::loc_t loc = awk.getErrorLocation();
|
||||
print_error (loc, awk.getErrorMessage());
|
||||
}
|
||||
|
||||
awk.close ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char locale[100];
|
||||
UINT codepage = GetConsoleOutputCP();
|
||||
if (codepage == CP_UTF8)
|
||||
{
|
||||
/*SetConsoleOUtputCP (CP_UTF8);*/
|
||||
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (locale, ".%u", (unsigned int)codepage);
|
||||
setlocale (LC_ALL, locale);
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
}
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
# define xcout std::cout
|
||||
#else
|
||||
setlocale (LC_ALL, "");
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
# define xcout std::wcout
|
||||
#endif
|
||||
|
||||
return qse_runmain (argc,argv,awk_main);
|
||||
struct MyAwk: public QSE::StdAwk
|
||||
{
|
||||
~MyAwk () { QSE::StdAwk::close (); }
|
||||
};
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
MyAwk awk;
|
||||
MyAwk::Value r;
|
||||
MyAwk::SourceString in (QSE_T("BEGIN { print \"hello, world\" }"));
|
||||
|
||||
if (awk.open () <= -1 || // initialize an awk object
|
||||
awk.addArgument (QSE_T("awk21")) <= -1 || // set ARGV[0]
|
||||
awk.parse (in, MyAwk::Source::NONE) == QSE_NULL || // parse the script
|
||||
awk.loop (&r) <= -1) goto oops;
|
||||
|
||||
// no need to close anything since the destructor performs it
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
xcout << QSE_T("ERR: ") << awk.getErrorMessage() << std::endl; \
|
||||
return -1; \
|
||||
}
|
||||
|
@ -40,54 +40,27 @@ static void print_error (
|
||||
|
||||
static int run_awk (QSE::StdAwk& awk)
|
||||
{
|
||||
QSE::StdAwk::Run* run;
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk05")) <= -1) return -1;
|
||||
|
||||
// ARGV[1] and/or the first console input file
|
||||
if (awk.addArgument (QSE_T("Makefile")) <= -1) return -1;
|
||||
|
||||
const qse_char_t* script = QSE_T(
|
||||
"function add (a, b) { return a + b }\n"
|
||||
"function mul (a, b) { return a * b }\n"
|
||||
"function div (a, b) { return a / b }\n"
|
||||
"function sine (a) { return sin(a) }\n"
|
||||
"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("awk06.out"));
|
||||
QSE::StdAwk::SourceFile out (QSE_T("awk05.out"));
|
||||
|
||||
// parse the script and deparse it to awk06.out
|
||||
run = awk.parse (in, out);
|
||||
if (run == QSE_NULL) return -1;
|
||||
// parse the script string and deparse it to awk05.out.
|
||||
if (awk.parse (in, out) == QSE_NULL) return -1;
|
||||
|
||||
QSE::StdAwk::Value arg[2];
|
||||
if (arg[0].setInt (run, -20) <= -1) return -1;
|
||||
if (arg[1].setStr (run, QSE_T("51")) <= -1) return -1;
|
||||
|
||||
// ret = add (-20, 51)
|
||||
QSE::StdAwk::Value ret;
|
||||
if (awk.call (QSE_T("add"), &ret, arg, 2) <= -1) return -1;
|
||||
|
||||
// ret = mul (ret, 51);
|
||||
arg[0] = ret;
|
||||
if (awk.call (QSE_T("mul"), &ret, arg, 2) <= -1) return -1;
|
||||
|
||||
// ret = div (ret, 2);
|
||||
arg[0] = ret;
|
||||
if (arg[1].setFlt (run, 2) <= -1) return -1;
|
||||
if (awk.call (QSE_T("div"), &ret, arg, 2) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)ret.toInt());
|
||||
qse_printf (QSE_T(" (flt) [%Lf]\n"), (long double)ret.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), ret.toStr(QSE_NULL));
|
||||
|
||||
// ret = sine (ret);
|
||||
arg[0] = ret;
|
||||
if (awk.call (QSE_T("sine"), &ret, arg, 1) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)ret.toInt());
|
||||
qse_printf (QSE_T(" (flt) [%Lf]\n"), (long double)ret.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), ret.toStr(QSE_NULL));
|
||||
|
||||
return 0;
|
||||
QSE::StdAwk::Value r;
|
||||
// execute the BEGIN, pattern-action, END blocks.
|
||||
return awk.loop (&r);
|
||||
}
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
@ -95,8 +68,8 @@ static int awk_main (int argc, qse_char_t* argv[])
|
||||
QSE::StdAwk awk;
|
||||
|
||||
int ret = awk.open ();
|
||||
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
|
||||
if (ret <= -1)
|
||||
{
|
||||
QSE::StdAwk::loc_t loc = awk.getErrorLocation();
|
||||
@ -104,7 +77,7 @@ static int awk_main (int argc, qse_char_t* argv[])
|
||||
}
|
||||
|
||||
awk.close ();
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
@ -127,5 +100,6 @@ int qse_main (int argc, qse_achar_t* argv[])
|
||||
setlocale (LC_ALL, "");
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
#endif
|
||||
|
||||
return qse_runmain (argc,argv,awk_main);
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
static void print_error (
|
||||
const QSE::StdAwk::loc_t& loc, const QSE::StdAwk::char_t* msg)
|
||||
{
|
||||
@ -43,88 +42,50 @@ static int run_awk (QSE::StdAwk& awk)
|
||||
{
|
||||
QSE::StdAwk::Run* run;
|
||||
|
||||
QSE::StdAwk::SourceString in (QSE_T(
|
||||
"function pa (x) {\n"
|
||||
" @reset ret;\n"
|
||||
" for (i in x) { print i, \"=>\", x[i]; ret += x[i]; }\n"
|
||||
" return ret + FOO++;\n"
|
||||
"}\n"
|
||||
"function pb (x) {\n"
|
||||
" @reset ret;\n"
|
||||
" for (i in x) { ret[-i] = -x[i]; }\n"
|
||||
" return ret;\n"
|
||||
"}"
|
||||
));
|
||||
|
||||
// add a global variable 'FOO'
|
||||
int foo = awk.addGlobal (QSE_T("FOO"));
|
||||
if (foo <= -1) return -1;
|
||||
|
||||
// parse the script and perform no deparsing
|
||||
run = awk.parse (in, QSE::StdAwk::Source::NONE);
|
||||
if (run == QSE_NULL) return -1;
|
||||
|
||||
// set 'FOO' to 100000
|
||||
QSE::StdAwk::Value foov (run);
|
||||
if (foov.setInt (100000) <= -1) return -1;
|
||||
if (awk.setGlobal (foo, foov) <= -1) return -1;
|
||||
|
||||
// prepare an indexed parameter
|
||||
QSE::StdAwk::Value arg[1];
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
if (arg[0].setIndexedInt (run,
|
||||
QSE::StdAwk::Value::IntIndex(i), i*20) <= -1) return -1;
|
||||
}
|
||||
if (arg[0].setIndexedStr (run,
|
||||
QSE::StdAwk::Value::IntIndex(99), QSE_T("-2345")) <= -1) return -1;
|
||||
|
||||
QSE::StdAwk::Value dummy;
|
||||
if (dummy.setStr (run, QSE_T("4567")) <= -1) return -1;
|
||||
if (arg[0].setIndexedVal (run,
|
||||
QSE::StdAwk::Value::IntIndex(999), dummy) <= -1) return -1;
|
||||
|
||||
// prepare a variable to hold the return value
|
||||
QSE::StdAwk::Value r;
|
||||
|
||||
// call the 'pa' function
|
||||
if (awk.call (QSE_T("pa"), &r, arg, 1) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)r.toInt());
|
||||
qse_printf (QSE_T(" (flt)[%Lf]\n"), (long double)r.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), r.toStr(QSE_NULL));
|
||||
|
||||
// get the value of 'FOO'
|
||||
if (awk.getGlobal (foo, foov) <= -1) return -1;
|
||||
qse_printf (QSE_T("FOO: (int) [%lld]\n"), (long long)foov.toInt());
|
||||
qse_printf (QSE_T(" (flt)[%Lf]\n"), (long double)foov.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), foov.toStr(QSE_NULL));
|
||||
|
||||
// call the 'pb' function
|
||||
if (awk.call (QSE_T("pb"), &r, arg, QSE_COUNTOF(arg)) <= -1) return -1;
|
||||
|
||||
// output the returned map.
|
||||
QSE_ASSERT (r.isIndexed());
|
||||
|
||||
QSE::StdAwk::Value::IndexIterator iter;
|
||||
QSE::StdAwk::Value::Index idx;
|
||||
QSE::StdAwk::Value v;
|
||||
|
||||
qse_printf (QSE_T("RESULT:\n"));
|
||||
|
||||
iter = r.getFirstIndex (&idx);
|
||||
while (iter != QSE::StdAwk::Value::IndexIterator::END)
|
||||
{
|
||||
if (r.getIndexed (idx, &v) <= -1) return -1;
|
||||
|
||||
qse_printf (QSE_T("\t[%.*s]=>[%lld]\n"),
|
||||
(int)idx.length(), idx.pointer(),
|
||||
(long long)v.toInt()
|
||||
const qse_char_t* script = QSE_T(
|
||||
"function add (a, b) { return a + b }\n"
|
||||
"function mul (a, b) { return a * b }\n"
|
||||
"function div (a, b) { return a / b }\n"
|
||||
"function sine (a) { return sin(a) }\n"
|
||||
);
|
||||
|
||||
iter = r.getNextIndex (&idx, iter);
|
||||
}
|
||||
QSE::StdAwk::SourceString in (script);
|
||||
QSE::StdAwk::SourceFile out (QSE_T("awk06.out"));
|
||||
|
||||
// parse the script and deparse it to awk06.out
|
||||
run = awk.parse (in, out);
|
||||
if (run == QSE_NULL) return -1;
|
||||
|
||||
QSE::StdAwk::Value arg[2];
|
||||
if (arg[0].setInt (run, -20) <= -1) return -1;
|
||||
if (arg[1].setStr (run, QSE_T("51")) <= -1) return -1;
|
||||
|
||||
// ret = add (-20, 51)
|
||||
QSE::StdAwk::Value ret;
|
||||
if (awk.call (QSE_T("add"), &ret, arg, 2) <= -1) return -1;
|
||||
|
||||
// ret = mul (ret, 51);
|
||||
arg[0] = ret;
|
||||
if (awk.call (QSE_T("mul"), &ret, arg, 2) <= -1) return -1;
|
||||
|
||||
// ret = div (ret, 2);
|
||||
arg[0] = ret;
|
||||
if (arg[1].setFlt (run, 2) <= -1) return -1;
|
||||
if (awk.call (QSE_T("div"), &ret, arg, 2) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)ret.toInt());
|
||||
qse_printf (QSE_T(" (flt) [%Lf]\n"), (long double)ret.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), ret.toStr(QSE_NULL));
|
||||
|
||||
// ret = sine (ret);
|
||||
arg[0] = ret;
|
||||
if (awk.call (QSE_T("sine"), &ret, arg, 1) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)ret.toInt());
|
||||
qse_printf (QSE_T(" (flt) [%Lf]\n"), (long double)ret.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), ret.toStr(QSE_NULL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -135,9 +96,6 @@ static int awk_main (int argc, qse_char_t* argv[])
|
||||
|
||||
int ret = awk.open();
|
||||
|
||||
// allow returning a map from a function
|
||||
awk.setTrait (awk.getTrait() | QSE_AWK_FLEXMAP);
|
||||
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
if (ret <= -1)
|
||||
{
|
||||
|
@ -19,402 +19,111 @@
|
||||
*/
|
||||
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <qse/cmn/opt.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/main.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSPROCESS
|
||||
# include <os2.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
/* these three definitions for doxygen cross-reference */
|
||||
typedef QSE::StdAwk StdAwk;
|
||||
typedef QSE::StdAwk::Run Run;
|
||||
typedef QSE::StdAwk::Value Value;
|
||||
|
||||
class MyAwk: public StdAwk
|
||||
static void print_error (
|
||||
const QSE::StdAwk::loc_t& loc, const QSE::StdAwk::char_t* msg)
|
||||
{
|
||||
public:
|
||||
MyAwk () { }
|
||||
~MyAwk () { close (); }
|
||||
|
||||
int open ()
|
||||
{
|
||||
if (StdAwk::open () <= -1) return -1;
|
||||
|
||||
idLastSleep = addGlobal (QSE_T("LAST_SLEEP"));
|
||||
if (idLastSleep <= -1) goto oops;
|
||||
|
||||
/* this is for demonstration only.
|
||||
* you can use sys::sleep() instead */
|
||||
if (addFunction (QSE_T("sleep"), 1, 1, QSE_NULL,
|
||||
(FunctionHandler)&MyAwk::sleep) <= -1) goto oops;
|
||||
|
||||
if (addFunction (QSE_T("sumintarray"), 1, 1, QSE_NULL,
|
||||
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto oops;
|
||||
|
||||
if (addFunction (QSE_T("arrayindices"), 1, 1, QSE_NULL,
|
||||
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto oops;
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
StdAwk::close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sleep (
|
||||
Run& run, Value& ret, Value* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
run.setError (QSE_AWK_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long_t x = args[0].toInt();
|
||||
|
||||
/*Value 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;
|
||||
|
||||
#if defined(_WIN32)
|
||||
::Sleep ((DWORD)(x * 1000));
|
||||
return ret.setInt (0);
|
||||
#elif defined(__OS2__)
|
||||
::DosSleep ((ULONG)(x * 1000));
|
||||
return ret.setInt (0);
|
||||
#else
|
||||
return ret.setInt (::sleep (x));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sumintarray (
|
||||
Run& run, Value& ret, Value* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
// BEGIN {
|
||||
// for(i=0;i<=10;i++) x[i]=i;
|
||||
// print sumintarray(x);
|
||||
// }
|
||||
long_t x = 0;
|
||||
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
Value val(run);
|
||||
Value::Index idx;
|
||||
Value::IndexIterator ii;
|
||||
|
||||
ii = args[0].getFirstIndex (&idx);
|
||||
while (ii != ii.END)
|
||||
{
|
||||
if (args[0].getIndexed(idx, &val) <= -1) return -1;
|
||||
x += val.toInt ();
|
||||
|
||||
ii = args[0].getNextIndex (&idx, ii);
|
||||
}
|
||||
}
|
||||
else x += args[0].toInt();
|
||||
|
||||
return ret.setInt (x);
|
||||
}
|
||||
|
||||
int arrayindices (
|
||||
Run& run,
|
||||
Value& ret,
|
||||
Value* args,
|
||||
size_t nargs,
|
||||
const char_t* name,
|
||||
size_t len)
|
||||
{
|
||||
// create another array composed of array indices
|
||||
// BEGIN {
|
||||
// for(i=0;i<=10;i++) x[i]=i;
|
||||
// y=arrayindices(x);
|
||||
// for (i in y) print y[i];
|
||||
// }
|
||||
if (!args[0].isIndexed()) return 0;
|
||||
|
||||
Value::Index idx;
|
||||
Value::IndexIterator ii;
|
||||
long_t i;
|
||||
|
||||
ii = args[0].getFirstIndex (&idx);
|
||||
for (i = 0; ii != ii.END ; i++)
|
||||
{
|
||||
Value::IntIndex iidx (i);
|
||||
if (ret.setIndexedStr (
|
||||
iidx, idx.pointer(), idx.length()) <= -1) return -1;
|
||||
ii = args[0].getNextIndex (&idx, ii);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int idLastSleep;
|
||||
};
|
||||
|
||||
static MyAwk* app_awk = QSE_NULL;
|
||||
|
||||
static void print_error (const qse_char_t* fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: "));
|
||||
|
||||
va_start (va, fmt);
|
||||
qse_vfprintf (QSE_STDERR, fmt, va);
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
static void print_error (MyAwk& awk)
|
||||
{
|
||||
MyAwk::loc_t loc = awk.getErrorLocation();
|
||||
|
||||
if (loc.file)
|
||||
{
|
||||
print_error (QSE_T("line %u at %s - %s\n"), (unsigned)loc.line, loc.file, awk.getErrorMessage());
|
||||
}
|
||||
if (loc.line > 0 || loc.colm > 0)
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu COLUMN %lu\n"), msg, loc.line, loc.colm);
|
||||
else
|
||||
{
|
||||
print_error (QSE_T("line %u - %s\n"), (unsigned)loc.line, awk.getErrorMessage());
|
||||
}
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static BOOL WINAPI stop_run (DWORD ctrl_type)
|
||||
static int run_awk (QSE::StdAwk& awk)
|
||||
{
|
||||
if (ctrl_type == CTRL_C_EVENT ||
|
||||
ctrl_type == CTRL_CLOSE_EVENT)
|
||||
QSE::StdAwk::Run* run;
|
||||
|
||||
QSE::StdAwk::SourceString in (QSE_T(
|
||||
"function pa (x) {\n"
|
||||
" @reset ret;\n"
|
||||
" for (i in x) { print i, \"=>\", x[i]; ret += x[i]; }\n"
|
||||
" return ret + FOO++;\n"
|
||||
"}\n"
|
||||
"function pb (x) {\n"
|
||||
" @reset ret;\n"
|
||||
" for (i in x) { ret[-i] = -x[i]; }\n"
|
||||
" return ret;\n"
|
||||
"}"
|
||||
));
|
||||
|
||||
// add a global variable 'FOO'
|
||||
int foo = awk.addGlobal (QSE_T("FOO"));
|
||||
if (foo <= -1) return -1;
|
||||
|
||||
// parse the script and perform no deparsing
|
||||
run = awk.parse (in, QSE::StdAwk::Source::NONE);
|
||||
if (run == QSE_NULL) return -1;
|
||||
|
||||
// set 'FOO' to 100000
|
||||
QSE::StdAwk::Value foov (run);
|
||||
if (foov.setInt (100000) <= -1) return -1;
|
||||
if (awk.setGlobal (foo, foov) <= -1) return -1;
|
||||
|
||||
// prepare an indexed parameter
|
||||
QSE::StdAwk::Value arg[1];
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
if (app_awk) app_awk->stop ();
|
||||
return TRUE;
|
||||
if (arg[0].setIndexedInt (run,
|
||||
QSE::StdAwk::Value::IntIndex(i), i*20) <= -1) return -1;
|
||||
}
|
||||
if (arg[0].setIndexedStr (run,
|
||||
QSE::StdAwk::Value::IntIndex(99), QSE_T("-2345")) <= -1) return -1;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
QSE::StdAwk::Value dummy;
|
||||
if (dummy.setStr (run, QSE_T("4567")) <= -1) return -1;
|
||||
if (arg[0].setIndexedVal (run,
|
||||
QSE::StdAwk::Value::IntIndex(999), dummy) <= -1) return -1;
|
||||
|
||||
static int setsignal (int sig, void(*handler)(int), int restart)
|
||||
// prepare a variable to hold the return value
|
||||
QSE::StdAwk::Value r;
|
||||
|
||||
// call the 'pa' function
|
||||
if (awk.call (QSE_T("pa"), &r, arg, 1) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)r.toInt());
|
||||
qse_printf (QSE_T(" (flt)[%Lf]\n"), (long double)r.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), r.toStr(QSE_NULL));
|
||||
|
||||
// get the value of 'FOO'
|
||||
if (awk.getGlobal (foo, foov) <= -1) return -1;
|
||||
qse_printf (QSE_T("FOO: (int) [%lld]\n"), (long long)foov.toInt());
|
||||
qse_printf (QSE_T(" (flt)[%Lf]\n"), (long double)foov.toFlt());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), foov.toStr(QSE_NULL));
|
||||
|
||||
// call the 'pb' function
|
||||
if (awk.call (QSE_T("pb"), &r, arg, QSE_COUNTOF(arg)) <= -1) return -1;
|
||||
|
||||
// output the returned map.
|
||||
QSE_ASSERT (r.isIndexed());
|
||||
|
||||
QSE::StdAwk::Value::IndexIterator iter;
|
||||
QSE::StdAwk::Value::Index idx;
|
||||
QSE::StdAwk::Value v;
|
||||
|
||||
qse_printf (QSE_T("RESULT:\n"));
|
||||
|
||||
iter = r.getFirstIndex (&idx);
|
||||
while (iter != QSE::StdAwk::Value::IndexIterator::END)
|
||||
{
|
||||
struct sigaction sa_int;
|
||||
if (r.getIndexed (idx, &v) <= -1) return -1;
|
||||
|
||||
sa_int.sa_handler = handler;
|
||||
sigemptyset (&sa_int.sa_mask);
|
||||
qse_printf (QSE_T("\t[%.*s]=>[%lld]\n"),
|
||||
(int)idx.length(), idx.pointer(),
|
||||
(long long)v.toInt()
|
||||
);
|
||||
|
||||
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_signal (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_signal (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler (stop_run, FALSE);
|
||||
#else
|
||||
setsignal (SIGINT, SIG_DFL, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_usage (QSE_FILE* out, const qse_char_t* argv0)
|
||||
{
|
||||
qse_fprintf (out, QSE_T("USAGE: %s [options] -f sourcefile [ -- ] [datafile]*\n"), argv0);
|
||||
qse_fprintf (out, QSE_T(" %s [options] [ -- ] sourcestring [datafile]*\n"), argv0);
|
||||
qse_fprintf (out, QSE_T("Where options are:\n"));
|
||||
qse_fprintf (out, QSE_T(" -h print this message\n"));
|
||||
qse_fprintf (out, QSE_T(" -f sourcefile set the source script file\n"));
|
||||
qse_fprintf (out, QSE_T(" -d deparsedfile set the deparsing output file\n"));
|
||||
qse_fprintf (out, QSE_T(" -o outputfile set the console output file\n"));
|
||||
qse_fprintf (out, QSE_T(" -F string set a field separator(FS)\n"));
|
||||
}
|
||||
|
||||
struct cmdline_t
|
||||
{
|
||||
qse_char_t* ins;
|
||||
qse_char_t* inf;
|
||||
qse_char_t* outf;
|
||||
qse_char_t* outc;
|
||||
qse_char_t* fs;
|
||||
};
|
||||
|
||||
static int handle_cmdline (
|
||||
MyAwk& awk, int argc, qse_char_t* argv[], cmdline_t* cmdline)
|
||||
{
|
||||
static qse_opt_t opt =
|
||||
{
|
||||
QSE_T("hF:f:d:o:"),
|
||||
QSE_NULL
|
||||
};
|
||||
qse_cint_t c;
|
||||
|
||||
std::memset (cmdline, 0, QSE_SIZEOF(*cmdline));
|
||||
while ((c = qse_getopt (argc, argv, &opt)) != QSE_CHAR_EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case QSE_T('h'):
|
||||
print_usage (QSE_STDOUT, argv[0]);
|
||||
return 0;
|
||||
|
||||
case QSE_T('F'):
|
||||
cmdline->fs = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('f'):
|
||||
cmdline->inf = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('d'):
|
||||
cmdline->outf = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('o'):
|
||||
cmdline->outc = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('?'):
|
||||
print_error (QSE_T("illegal option - '%c'\n"), opt.opt);
|
||||
return -1;
|
||||
|
||||
case QSE_T(':'):
|
||||
print_error (QSE_T("bad argument for '%c'\n"), opt.opt);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
print_usage (QSE_STDERR, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.ind < argc && !cmdline->inf)
|
||||
cmdline->ins = argv[opt.ind++];
|
||||
|
||||
while (opt.ind < argc)
|
||||
{
|
||||
if (awk.addArgument (argv[opt.ind++]) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmdline->ins && !cmdline->inf)
|
||||
{
|
||||
print_usage (QSE_STDERR, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int awk_main_2 (MyAwk& awk, int argc, qse_char_t* argv[])
|
||||
{
|
||||
MyAwk::Run* run;
|
||||
cmdline_t cmdline;
|
||||
int n;
|
||||
|
||||
awk.setTrait (awk.getTrait() | QSE_AWK_EXTRAKWS | QSE_AWK_FLEXMAP | QSE_AWK_RWPIPE);
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk08")) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((n = handle_cmdline (awk, argc, argv, &cmdline)) <= 0) return n;
|
||||
|
||||
MyAwk::Source* in, * out;
|
||||
MyAwk::SourceString in_str (cmdline.ins);
|
||||
MyAwk::SourceFile in_file (cmdline.inf);
|
||||
MyAwk::SourceFile out_file (cmdline.outf);
|
||||
|
||||
in = (cmdline.ins)? (MyAwk::Source*)&in_str: (MyAwk::Source*)&in_file;
|
||||
out = (cmdline.outf)? (MyAwk::Source*)&out_file: &MyAwk::Source::NONE;
|
||||
run = awk.parse (*in, *out);
|
||||
if (run == QSE_NULL)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmdline.fs)
|
||||
{
|
||||
MyAwk::Value fs (run);
|
||||
if (fs.setStr (cmdline.fs) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
if (awk.setGlobal (QSE_AWK_GBL_FS, fs) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdline.outc)
|
||||
{
|
||||
if (awk.addConsoleOutput (cmdline.outc) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
MyAwk::Value ret;
|
||||
if (awk.loop (&ret) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
iter = r.getNextIndex (&idx, iter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -422,34 +131,29 @@ static int awk_main_2 (MyAwk& awk, int argc, qse_char_t* argv[])
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
MyAwk awk;
|
||||
QSE::StdAwk awk;
|
||||
|
||||
if (awk.open() <= -1)
|
||||
int ret = awk.open();
|
||||
|
||||
// allow returning a map from a function
|
||||
awk.setTrait (awk.getTrait() | QSE_AWK_FLEXMAP);
|
||||
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
if (ret <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
QSE::StdAwk::loc_t loc = awk.getErrorLocation();
|
||||
print_error (loc, awk.getErrorMessage());
|
||||
}
|
||||
app_awk = &awk;
|
||||
|
||||
set_signal ();
|
||||
int n = awk_main_2 (awk, argc, argv);
|
||||
unset_signal ();
|
||||
|
||||
app_awk = QSE_NULL;
|
||||
awk.close ();
|
||||
return n;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(_WIN32)
|
||||
char locale[100];
|
||||
UINT codepage;
|
||||
WSADATA wsadata;
|
||||
|
||||
codepage = GetConsoleOutputCP();
|
||||
UINT codepage = GetConsoleOutputCP();
|
||||
if (codepage == CP_UTF8)
|
||||
{
|
||||
/*SetConsoleOUtputCP (CP_UTF8);*/
|
||||
@ -461,23 +165,9 @@ int qse_main (int argc, qse_achar_t* argv[])
|
||||
setlocale (LC_ALL, locale);
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
}
|
||||
|
||||
if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0)
|
||||
{
|
||||
print_error (QSE_T("Failed to start up winsock\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
setlocale (LC_ALL, "");
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
#endif
|
||||
|
||||
ret = qse_runmain (argc, argv, awk_main);
|
||||
|
||||
#if defined(_WIN32)
|
||||
WSACleanup ();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return qse_runmain (argc,argv,awk_main);
|
||||
}
|
||||
|
@ -19,23 +19,26 @@
|
||||
*/
|
||||
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/opt.h>
|
||||
#include <qse/cmn/main.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#if defined(QSE_CHAR_IS_WCHAR)
|
||||
typedef std::wstring String;
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSPROCESS
|
||||
# include <os2.h>
|
||||
#else
|
||||
typedef std::string String;
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
/* these three definitions for doxygen cross-reference */
|
||||
typedef QSE::StdAwk StdAwk;
|
||||
typedef QSE::StdAwk::Run Run;
|
||||
typedef QSE::StdAwk::Value Value;
|
||||
@ -43,159 +46,410 @@ typedef QSE::StdAwk::Value Value;
|
||||
class MyAwk: public StdAwk
|
||||
{
|
||||
public:
|
||||
//
|
||||
// this class overrides console methods to use
|
||||
// string buffers for console input and output.
|
||||
//
|
||||
MyAwk () { }
|
||||
~MyAwk () { close (); }
|
||||
|
||||
void setInput (const char_t* instr)
|
||||
int open ()
|
||||
{
|
||||
this->input = instr;
|
||||
this->inptr = this->input.c_str();
|
||||
this->inend = inptr + this->input.length();
|
||||
}
|
||||
if (StdAwk::open () <= -1) return -1;
|
||||
|
||||
void clearOutput () { this->output.clear (); }
|
||||
const char_t* getOutput () { return this->output.c_str(); }
|
||||
idLastSleep = addGlobal (QSE_T("LAST_SLEEP"));
|
||||
if (idLastSleep <= -1) goto oops;
|
||||
|
||||
protected:
|
||||
String input; // console input buffer
|
||||
const char_t* inptr;
|
||||
const char_t* inend;
|
||||
/* this is for demonstration only.
|
||||
* you can use sys::sleep() instead */
|
||||
if (addFunction (QSE_T("sleep"), 1, 1, QSE_NULL,
|
||||
(FunctionHandler)&MyAwk::sleep) <= -1) goto oops;
|
||||
|
||||
String output; // console output buffer
|
||||
if (addFunction (QSE_T("sumintarray"), 1, 1, QSE_NULL,
|
||||
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto oops;
|
||||
|
||||
int openConsole (Console& io)
|
||||
{
|
||||
return 1; // return open-success
|
||||
}
|
||||
if (addFunction (QSE_T("arrayindices"), 1, 1, QSE_NULL,
|
||||
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto oops;
|
||||
|
||||
int closeConsole (Console& io)
|
||||
{
|
||||
return 0; // return success
|
||||
}
|
||||
|
||||
int flushConsole (Console& io)
|
||||
{
|
||||
// there is nothing to flush since a string buffer
|
||||
// is used for a console output. just return success.
|
||||
return 0;
|
||||
}
|
||||
int nextConsole (Console& io)
|
||||
{
|
||||
// this stripped-down awk doesn't honor the nextfile statement
|
||||
// or the nextofile statement. just return success.
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t readConsole (Console& io, char_t* data, size_t size)
|
||||
{
|
||||
if (this->inptr >= this->inend) return 0; // EOF
|
||||
size_t x = qse_strxncpy (data, size, inptr, inend - inptr);
|
||||
this->inptr += x;
|
||||
return x;
|
||||
}
|
||||
|
||||
ssize_t writeConsole (Console& io, const char_t* data, size_t size)
|
||||
{
|
||||
try { this->output.append (data, size); }
|
||||
catch (...)
|
||||
{
|
||||
((Run*)io)->setError (QSE_AWK_ENOMEM);
|
||||
oops:
|
||||
StdAwk::close ();
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
|
||||
int sleep (
|
||||
Run& run, Value& ret, Value* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
run.setError (QSE_AWK_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long_t x = args[0].toInt();
|
||||
|
||||
/*Value 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;
|
||||
|
||||
#if defined(_WIN32)
|
||||
::Sleep ((DWORD)(x * 1000));
|
||||
return ret.setInt (0);
|
||||
#elif defined(__OS2__)
|
||||
::DosSleep ((ULONG)(x * 1000));
|
||||
return ret.setInt (0);
|
||||
#else
|
||||
return ret.setInt (::sleep (x));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sumintarray (
|
||||
Run& run, Value& ret, Value* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
// BEGIN {
|
||||
// for(i=0;i<=10;i++) x[i]=i;
|
||||
// print sumintarray(x);
|
||||
// }
|
||||
long_t x = 0;
|
||||
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
Value val(run);
|
||||
Value::Index idx;
|
||||
Value::IndexIterator ii;
|
||||
|
||||
ii = args[0].getFirstIndex (&idx);
|
||||
while (ii != ii.END)
|
||||
{
|
||||
if (args[0].getIndexed(idx, &val) <= -1) return -1;
|
||||
x += val.toInt ();
|
||||
|
||||
ii = args[0].getNextIndex (&idx, ii);
|
||||
}
|
||||
}
|
||||
else x += args[0].toInt();
|
||||
|
||||
return ret.setInt (x);
|
||||
}
|
||||
|
||||
int arrayindices (
|
||||
Run& run,
|
||||
Value& ret,
|
||||
Value* args,
|
||||
size_t nargs,
|
||||
const char_t* name,
|
||||
size_t len)
|
||||
{
|
||||
// create another array composed of array indices
|
||||
// BEGIN {
|
||||
// for(i=0;i<=10;i++) x[i]=i;
|
||||
// y=arrayindices(x);
|
||||
// for (i in y) print y[i];
|
||||
// }
|
||||
if (!args[0].isIndexed()) return 0;
|
||||
|
||||
Value::Index idx;
|
||||
Value::IndexIterator ii;
|
||||
long_t i;
|
||||
|
||||
ii = args[0].getFirstIndex (&idx);
|
||||
for (i = 0; ii != ii.END ; i++)
|
||||
{
|
||||
Value::IntIndex iidx (i);
|
||||
if (ret.setIndexedStr (
|
||||
iidx, idx.pointer(), idx.length()) <= -1) return -1;
|
||||
ii = args[0].getNextIndex (&idx, ii);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int idLastSleep;
|
||||
};
|
||||
|
||||
static void print_error (
|
||||
const MyAwk::loc_t& loc, const MyAwk::char_t* msg)
|
||||
{
|
||||
if (loc.line > 0 || loc.colm > 0)
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu COLUMN %lu\n"), msg, loc.line, loc.colm);
|
||||
else
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
static MyAwk* app_awk = QSE_NULL;
|
||||
|
||||
static void print_error (const qse_char_t* fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: "));
|
||||
|
||||
va_start (va, fmt);
|
||||
qse_vfprintf (QSE_STDERR, fmt, va);
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
static int run_awk (MyAwk& awk)
|
||||
static void print_error (MyAwk& awk)
|
||||
{
|
||||
// sample input string
|
||||
const qse_char_t* instr = QSE_T(
|
||||
"aardvark 555-5553 1200/300 B\n"
|
||||
"alpo-net 555-3412 2400/1200/300 A\n"
|
||||
"barfly 555-7685 1200/300 A\n"
|
||||
"bites 555-1675 2400/1200/300 A\n"
|
||||
"camelot 555-0542 300 C\n"
|
||||
"core 555-2912 1200/300 C\n"
|
||||
"fooey 555-1234 2400/1200/300 B\n"
|
||||
"foot 555-6699 1200/300 B\n"
|
||||
"macfoo 555-6480 1200/300 A\n"
|
||||
"sdace 555-3430 2400/1200/300 A\n"
|
||||
"sabafoo 555-2127 1200/300 C\n");
|
||||
MyAwk::loc_t loc = awk.getErrorLocation();
|
||||
|
||||
if (loc.file)
|
||||
{
|
||||
print_error (QSE_T("line %u at %s - %s\n"), (unsigned)loc.line, loc.file, awk.getErrorMessage());
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error (QSE_T("line %u - %s\n"), (unsigned)loc.line, awk.getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
#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_signal (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_signal (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler (stop_run, FALSE);
|
||||
#else
|
||||
setsignal (SIGINT, SIG_DFL, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_usage (QSE_FILE* out, const qse_char_t* argv0)
|
||||
{
|
||||
qse_fprintf (out, QSE_T("USAGE: %s [options] -f sourcefile [ -- ] [datafile]*\n"), argv0);
|
||||
qse_fprintf (out, QSE_T(" %s [options] [ -- ] sourcestring [datafile]*\n"), argv0);
|
||||
qse_fprintf (out, QSE_T("Where options are:\n"));
|
||||
qse_fprintf (out, QSE_T(" -h print this message\n"));
|
||||
qse_fprintf (out, QSE_T(" -f sourcefile set the source script file\n"));
|
||||
qse_fprintf (out, QSE_T(" -d deparsedfile set the deparsing output file\n"));
|
||||
qse_fprintf (out, QSE_T(" -o outputfile set the console output file\n"));
|
||||
qse_fprintf (out, QSE_T(" -F string set a field separator(FS)\n"));
|
||||
}
|
||||
|
||||
struct cmdline_t
|
||||
{
|
||||
qse_char_t* ins;
|
||||
qse_char_t* inf;
|
||||
qse_char_t* outf;
|
||||
qse_char_t* outc;
|
||||
qse_char_t* fs;
|
||||
};
|
||||
|
||||
static int handle_cmdline (
|
||||
MyAwk& awk, int argc, qse_char_t* argv[], cmdline_t* cmdline)
|
||||
{
|
||||
static qse_opt_t opt =
|
||||
{
|
||||
QSE_T("hF:f:d:o:"),
|
||||
QSE_NULL
|
||||
};
|
||||
qse_cint_t c;
|
||||
|
||||
std::memset (cmdline, 0, QSE_SIZEOF(*cmdline));
|
||||
while ((c = qse_getopt (argc, argv, &opt)) != QSE_CHAR_EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case QSE_T('h'):
|
||||
print_usage (QSE_STDOUT, argv[0]);
|
||||
return 0;
|
||||
|
||||
case QSE_T('F'):
|
||||
cmdline->fs = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('f'):
|
||||
cmdline->inf = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('d'):
|
||||
cmdline->outf = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('o'):
|
||||
cmdline->outc = opt.arg;
|
||||
break;
|
||||
|
||||
case QSE_T('?'):
|
||||
print_error (QSE_T("illegal option - '%c'\n"), opt.opt);
|
||||
return -1;
|
||||
|
||||
case QSE_T(':'):
|
||||
print_error (QSE_T("bad argument for '%c'\n"), opt.opt);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
print_usage (QSE_STDERR, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.ind < argc && !cmdline->inf)
|
||||
cmdline->ins = argv[opt.ind++];
|
||||
|
||||
while (opt.ind < argc)
|
||||
{
|
||||
if (awk.addArgument (argv[opt.ind++]) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmdline->ins && !cmdline->inf)
|
||||
{
|
||||
print_usage (QSE_STDERR, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int awk_main_2 (MyAwk& awk, int argc, qse_char_t* argv[])
|
||||
{
|
||||
MyAwk::Run* run;
|
||||
cmdline_t cmdline;
|
||||
int n;
|
||||
|
||||
awk.setTrait (awk.getTrait() | QSE_AWK_EXTRAKWS | QSE_AWK_FLEXMAP | QSE_AWK_RWPIPE);
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk12")) <= -1) return -1;
|
||||
|
||||
// prepare a script to print the second and the first column
|
||||
MyAwk::SourceString in (QSE_T("{ print $2, $1; }"));
|
||||
|
||||
// parse the script.
|
||||
if (awk.parse (in, MyAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
MyAwk::Value r;
|
||||
|
||||
awk.setInput (instr); // locate the input string
|
||||
awk.clearOutput (); // clear the output string
|
||||
int x = awk.loop (&r); // execute the BEGIN, pattern-action, END blocks.
|
||||
|
||||
if (x >= 0)
|
||||
if (awk.addArgument (QSE_T("awk08")) <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("%s"), awk.getOutput()); // print the console output
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// prepare a string to print lines with A in the fourth column
|
||||
MyAwk::SourceString in2 (QSE_T("$4 == \"A\" { print $1; }"));
|
||||
if (awk.parse (in2, MyAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
if ((n = handle_cmdline (awk, argc, argv, &cmdline)) <= 0) return n;
|
||||
|
||||
awk.setInput (instr);
|
||||
awk.clearOutput ();
|
||||
MyAwk::Source* in, * out;
|
||||
MyAwk::SourceString in_str (cmdline.ins);
|
||||
MyAwk::SourceFile in_file (cmdline.inf);
|
||||
MyAwk::SourceFile out_file (cmdline.outf);
|
||||
|
||||
int x = awk.loop (&r);
|
||||
|
||||
if (x >= 0)
|
||||
in = (cmdline.ins)? (MyAwk::Source*)&in_str: (MyAwk::Source*)&in_file;
|
||||
out = (cmdline.outf)? (MyAwk::Source*)&out_file: &MyAwk::Source::NONE;
|
||||
run = awk.parse (*in, *out);
|
||||
if (run == QSE_NULL)
|
||||
{
|
||||
qse_printf (QSE_T("%s"), awk.getOutput());
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmdline.fs)
|
||||
{
|
||||
MyAwk::Value fs (run);
|
||||
if (fs.setStr (cmdline.fs) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
if (awk.setGlobal (QSE_AWK_GBL_FS, fs) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
if (cmdline.outc)
|
||||
{
|
||||
if (awk.addConsoleOutput (cmdline.outc) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
MyAwk::Value ret;
|
||||
if (awk.loop (&ret) <= -1)
|
||||
{
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
MyAwk awk;
|
||||
|
||||
int ret = awk.open ();
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
|
||||
if (ret <= -1)
|
||||
if (awk.open() <= -1)
|
||||
{
|
||||
MyAwk::loc_t loc = awk.getErrorLocation();
|
||||
print_error (loc, awk.getErrorMessage());
|
||||
print_error (awk);
|
||||
return -1;
|
||||
}
|
||||
app_awk = &awk;
|
||||
|
||||
set_signal ();
|
||||
int n = awk_main_2 (awk, argc, argv);
|
||||
unset_signal ();
|
||||
|
||||
app_awk = QSE_NULL;
|
||||
awk.close ();
|
||||
return ret;
|
||||
return n;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(_WIN32)
|
||||
char locale[100];
|
||||
UINT codepage = GetConsoleOutputCP();
|
||||
UINT codepage;
|
||||
WSADATA wsadata;
|
||||
|
||||
codepage = GetConsoleOutputCP();
|
||||
if (codepage == CP_UTF8)
|
||||
{
|
||||
/*SetConsoleOUtputCP (CP_UTF8);*/
|
||||
@ -207,10 +461,23 @@ int qse_main (int argc, qse_achar_t* argv[])
|
||||
setlocale (LC_ALL, locale);
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
}
|
||||
|
||||
if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0)
|
||||
{
|
||||
print_error (QSE_T("Failed to start up winsock\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
setlocale (LC_ALL, "");
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
#endif
|
||||
|
||||
return qse_runmain (argc,argv,awk_main);
|
||||
ret = qse_runmain (argc, argv, awk_main);
|
||||
|
||||
#if defined(_WIN32)
|
||||
WSACleanup ();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
this->inend = inptr + this->input.length();
|
||||
}
|
||||
|
||||
void clearOutput () { this->output.clear (); }
|
||||
const char_t* getOutput () { return this->output.c_str(); }
|
||||
|
||||
protected:
|
||||
@ -68,16 +69,6 @@ protected:
|
||||
|
||||
int openConsole (Console& io)
|
||||
{
|
||||
if (io.getMode() == Console::READ)
|
||||
{
|
||||
this->inptr = this->input.c_str();
|
||||
this->inend = inptr + this->input.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->output.clear ();
|
||||
}
|
||||
|
||||
return 1; // return open-success
|
||||
}
|
||||
|
||||
@ -95,8 +86,8 @@ protected:
|
||||
int nextConsole (Console& io)
|
||||
{
|
||||
// this stripped-down awk doesn't honor the nextfile statement
|
||||
// or the nextofile statement. just return failure.
|
||||
return -1;
|
||||
// or the nextofile statement. just return success.
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t readConsole (Console& io, char_t* data, size_t size)
|
||||
@ -145,30 +136,18 @@ static int run_awk (MyAwk& awk)
|
||||
"sdace 555-3430 2400/1200/300 A\n"
|
||||
"sabafoo 555-2127 1200/300 C\n");
|
||||
|
||||
const qse_char_t* instr2 = QSE_T(
|
||||
"aardvark 555-5553 1200/300 A\n"
|
||||
"alpo-net 555-3412 2400/1200/300 B\n"
|
||||
"barfly 555-7685 1200/300 C\n"
|
||||
"bites 555-1675 2400/1200/300 A\n"
|
||||
"camelot 555-0542 300 C\n"
|
||||
"core 555-2912 1200/300 B\n"
|
||||
"fooey 555-1234 2400/1200/300 A\n"
|
||||
"foot 555-6699 1200/300 A\n"
|
||||
"macfoo 555-6480 1200/300 B\n"
|
||||
"sdace 555-3430 2400/1200/300 B\n"
|
||||
"sabafoo 555-2127 1200/300 A\n");
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk13")) <= -1) return -1;
|
||||
if (awk.addArgument (QSE_T("awk12")) <= -1) return -1;
|
||||
|
||||
// prepare a string to print lines with A in the fourth column
|
||||
MyAwk::SourceString in (QSE_T("$4 == \"A\" { print $2, $1, $3; }"));
|
||||
// prepare a script to print the second and the first column
|
||||
MyAwk::SourceString in (QSE_T("{ print $2, $1; }"));
|
||||
|
||||
// parse the script.
|
||||
if (awk.parse (in, MyAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
MyAwk::Value r;
|
||||
|
||||
awk.setInput (instr); // locate the input string
|
||||
awk.clearOutput (); // clear the output string
|
||||
int x = awk.loop (&r); // execute the BEGIN, pattern-action, END blocks.
|
||||
|
||||
if (x >= 0)
|
||||
@ -176,11 +155,12 @@ static int run_awk (MyAwk& awk)
|
||||
qse_printf (QSE_T("%s"), awk.getOutput()); // print the console output
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
|
||||
awk.setInput (instr2);
|
||||
// prepare a string to print lines with A in the fourth column
|
||||
MyAwk::SourceString in2 (QSE_T("$4 == \"A\" { print $1; }"));
|
||||
if (awk.parse (in2, MyAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
|
||||
// reset the runtime context so that the next loop() method
|
||||
// is performed over a new console stream.
|
||||
if (awk.resetRunContext() == QSE_NULL) return -1;
|
||||
awk.setInput (instr);
|
||||
awk.clearOutput ();
|
||||
|
||||
int x = awk.loop (&r);
|
||||
|
||||
|
@ -40,31 +40,35 @@ typedef QSE::StdAwk StdAwk;
|
||||
typedef QSE::StdAwk::Run Run;
|
||||
typedef QSE::StdAwk::Value Value;
|
||||
|
||||
class MyConsoleHandler: public StdAwk::Console::Handler
|
||||
class MyAwk: public StdAwk
|
||||
{
|
||||
public:
|
||||
// this class defines a console handler that can be
|
||||
// registered into an awk object.
|
||||
//
|
||||
// this class overrides console methods to use
|
||||
// string buffers for console input and output.
|
||||
//
|
||||
MyAwk () { }
|
||||
~MyAwk () { close (); }
|
||||
|
||||
void setInput (const StdAwk::char_t* instr)
|
||||
void setInput (const char_t* instr)
|
||||
{
|
||||
this->input = instr;
|
||||
this->inptr = this->input.c_str();
|
||||
this->inend = inptr + this->input.length();
|
||||
}
|
||||
|
||||
const StdAwk::char_t* getOutput () { return this->output.c_str(); }
|
||||
const char_t* getOutput () { return this->output.c_str(); }
|
||||
|
||||
protected:
|
||||
String input; // console input buffer
|
||||
const StdAwk::char_t* inptr;
|
||||
const StdAwk::char_t* inend;
|
||||
const char_t* inptr;
|
||||
const char_t* inend;
|
||||
|
||||
String output; // console output buffer
|
||||
|
||||
int open (StdAwk::Console& io)
|
||||
int openConsole (Console& io)
|
||||
{
|
||||
if (io.getMode() == StdAwk::Console::READ)
|
||||
if (io.getMode() == Console::READ)
|
||||
{
|
||||
this->inptr = this->input.c_str();
|
||||
this->inend = inptr + this->input.length();
|
||||
@ -77,25 +81,25 @@ protected:
|
||||
return 1; // return open-success
|
||||
}
|
||||
|
||||
int close (StdAwk::Console& io)
|
||||
int closeConsole (Console& io)
|
||||
{
|
||||
return 0; // return success
|
||||
}
|
||||
|
||||
int flush (StdAwk::Console& io)
|
||||
int flushConsole (Console& io)
|
||||
{
|
||||
// there is nothing to flush since a string buffer
|
||||
// is used for a console output. just return success.
|
||||
return 0;
|
||||
}
|
||||
int next (StdAwk::Console& io)
|
||||
int nextConsole (Console& io)
|
||||
{
|
||||
// this stripped-down awk doesn't honor the nextfile statement
|
||||
// or the nextofile statement. just return failure.
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t read (StdAwk::Console& io, StdAwk::char_t* data, size_t size)
|
||||
ssize_t readConsole (Console& io, char_t* data, size_t size)
|
||||
{
|
||||
if (this->inptr >= this->inend) return 0; // EOF
|
||||
size_t x = qse_strxncpy (data, size, inptr, inend - inptr);
|
||||
@ -103,12 +107,12 @@ protected:
|
||||
return x;
|
||||
}
|
||||
|
||||
ssize_t write (StdAwk::Console& io, const StdAwk::char_t* data, size_t size)
|
||||
ssize_t writeConsole (Console& io, const char_t* data, size_t size)
|
||||
{
|
||||
try { this->output.append (data, size); }
|
||||
catch (...)
|
||||
{
|
||||
((StdAwk::Run*)io)->setError (QSE_AWK_ENOMEM);
|
||||
((Run*)io)->setError (QSE_AWK_ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
@ -116,7 +120,7 @@ protected:
|
||||
};
|
||||
|
||||
static void print_error (
|
||||
const StdAwk::loc_t& loc, const StdAwk::char_t* msg)
|
||||
const MyAwk::loc_t& loc, const MyAwk::char_t* msg)
|
||||
{
|
||||
if (loc.line > 0 || loc.colm > 0)
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu COLUMN %lu\n"), msg, loc.line, loc.colm);
|
||||
@ -125,7 +129,7 @@ static void print_error (
|
||||
|
||||
}
|
||||
|
||||
static int run_awk (StdAwk& awk)
|
||||
static int run_awk (MyAwk& awk)
|
||||
{
|
||||
// sample input string
|
||||
const qse_char_t* instr = QSE_T(
|
||||
@ -155,26 +159,24 @@ static int run_awk (StdAwk& awk)
|
||||
"sabafoo 555-2127 1200/300 A\n");
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk14")) <= -1) return -1;
|
||||
if (awk.addArgument (QSE_T("awk13")) <= -1) return -1;
|
||||
|
||||
// prepare a string to print lines with A in the fourth column
|
||||
StdAwk::SourceString in (QSE_T("$4 == \"A\" { print $2, $1, $3; }"));
|
||||
MyAwk::SourceString in (QSE_T("$4 == \"A\" { print $2, $1, $3; }"));
|
||||
|
||||
// parse the script.
|
||||
if (awk.parse (in, StdAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
StdAwk::Value r;
|
||||
if (awk.parse (in, MyAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
MyAwk::Value r;
|
||||
|
||||
MyConsoleHandler* mch = (MyConsoleHandler*)awk.getConsoleHandler();
|
||||
|
||||
mch->setInput (instr); // locate the input string
|
||||
awk.setInput (instr); // locate the input string
|
||||
int x = awk.loop (&r); // execute the BEGIN, pattern-action, END blocks.
|
||||
|
||||
if (x >= 0)
|
||||
{
|
||||
qse_printf (QSE_T("%s"), mch->getOutput()); // print the console output
|
||||
qse_printf (QSE_T("%s"), awk.getOutput()); // print the console output
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
|
||||
mch->setInput (instr2);
|
||||
awk.setInput (instr2);
|
||||
|
||||
// reset the runtime context so that the next loop() method
|
||||
// is performed over a new console stream.
|
||||
@ -184,7 +186,7 @@ static int run_awk (StdAwk& awk)
|
||||
|
||||
if (x >= 0)
|
||||
{
|
||||
qse_printf (QSE_T("%s"), mch->getOutput());
|
||||
qse_printf (QSE_T("%s"), awk.getOutput());
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
}
|
||||
}
|
||||
@ -194,20 +196,14 @@ static int run_awk (StdAwk& awk)
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
|
||||
MyConsoleHandler mch;
|
||||
StdAwk awk;
|
||||
MyAwk awk;
|
||||
|
||||
int ret = awk.open ();
|
||||
if (ret >= 0)
|
||||
{
|
||||
awk.setConsoleHandler (&mch);
|
||||
ret = run_awk (awk);
|
||||
}
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
|
||||
if (ret <= -1)
|
||||
{
|
||||
StdAwk::loc_t loc = awk.getErrorLocation();
|
||||
MyAwk::loc_t loc = awk.getErrorLocation();
|
||||
print_error (loc, awk.getErrorMessage());
|
||||
}
|
||||
|
||||
|
240
qse/samples/awk/awk28.cpp
Normal file
240
qse/samples/awk/awk28.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright 2006-2012 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
|
||||
QSE is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
QSE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/main.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/str.h>
|
||||
|
||||
#include <locale.h>
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#if defined(QSE_CHAR_IS_WCHAR)
|
||||
typedef std::wstring String;
|
||||
#else
|
||||
typedef std::string String;
|
||||
#endif
|
||||
|
||||
typedef QSE::StdAwk StdAwk;
|
||||
typedef QSE::StdAwk::Run Run;
|
||||
typedef QSE::StdAwk::Value Value;
|
||||
|
||||
class MyConsoleHandler: public StdAwk::Console::Handler
|
||||
{
|
||||
public:
|
||||
// this class defines a console handler that can be
|
||||
// registered into an awk object.
|
||||
|
||||
void setInput (const StdAwk::char_t* instr)
|
||||
{
|
||||
this->input = instr;
|
||||
this->inptr = this->input.c_str();
|
||||
this->inend = inptr + this->input.length();
|
||||
}
|
||||
|
||||
const StdAwk::char_t* getOutput () { return this->output.c_str(); }
|
||||
|
||||
protected:
|
||||
String input; // console input buffer
|
||||
const StdAwk::char_t* inptr;
|
||||
const StdAwk::char_t* inend;
|
||||
|
||||
String output; // console output buffer
|
||||
|
||||
int open (StdAwk::Console& io)
|
||||
{
|
||||
if (io.getMode() == StdAwk::Console::READ)
|
||||
{
|
||||
this->inptr = this->input.c_str();
|
||||
this->inend = inptr + this->input.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->output.clear ();
|
||||
}
|
||||
|
||||
return 1; // return open-success
|
||||
}
|
||||
|
||||
int close (StdAwk::Console& io)
|
||||
{
|
||||
return 0; // return success
|
||||
}
|
||||
|
||||
int flush (StdAwk::Console& io)
|
||||
{
|
||||
// there is nothing to flush since a string buffer
|
||||
// is used for a console output. just return success.
|
||||
return 0;
|
||||
}
|
||||
int next (StdAwk::Console& io)
|
||||
{
|
||||
// this stripped-down awk doesn't honor the nextfile statement
|
||||
// or the nextofile statement. just return failure.
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t read (StdAwk::Console& io, StdAwk::char_t* data, size_t size)
|
||||
{
|
||||
if (this->inptr >= this->inend) return 0; // EOF
|
||||
size_t x = qse_strxncpy (data, size, inptr, inend - inptr);
|
||||
this->inptr += x;
|
||||
return x;
|
||||
}
|
||||
|
||||
ssize_t write (StdAwk::Console& io, const StdAwk::char_t* data, size_t size)
|
||||
{
|
||||
try { this->output.append (data, size); }
|
||||
catch (...)
|
||||
{
|
||||
((StdAwk::Run*)io)->setError (QSE_AWK_ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
static void print_error (
|
||||
const StdAwk::loc_t& loc, const StdAwk::char_t* msg)
|
||||
{
|
||||
if (loc.line > 0 || loc.colm > 0)
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu COLUMN %lu\n"), msg, loc.line, loc.colm);
|
||||
else
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
|
||||
}
|
||||
|
||||
static int run_awk (StdAwk& awk)
|
||||
{
|
||||
// sample input string
|
||||
const qse_char_t* instr = QSE_T(
|
||||
"aardvark 555-5553 1200/300 B\n"
|
||||
"alpo-net 555-3412 2400/1200/300 A\n"
|
||||
"barfly 555-7685 1200/300 A\n"
|
||||
"bites 555-1675 2400/1200/300 A\n"
|
||||
"camelot 555-0542 300 C\n"
|
||||
"core 555-2912 1200/300 C\n"
|
||||
"fooey 555-1234 2400/1200/300 B\n"
|
||||
"foot 555-6699 1200/300 B\n"
|
||||
"macfoo 555-6480 1200/300 A\n"
|
||||
"sdace 555-3430 2400/1200/300 A\n"
|
||||
"sabafoo 555-2127 1200/300 C\n");
|
||||
|
||||
const qse_char_t* instr2 = QSE_T(
|
||||
"aardvark 555-5553 1200/300 A\n"
|
||||
"alpo-net 555-3412 2400/1200/300 B\n"
|
||||
"barfly 555-7685 1200/300 C\n"
|
||||
"bites 555-1675 2400/1200/300 A\n"
|
||||
"camelot 555-0542 300 C\n"
|
||||
"core 555-2912 1200/300 B\n"
|
||||
"fooey 555-1234 2400/1200/300 A\n"
|
||||
"foot 555-6699 1200/300 A\n"
|
||||
"macfoo 555-6480 1200/300 B\n"
|
||||
"sdace 555-3430 2400/1200/300 B\n"
|
||||
"sabafoo 555-2127 1200/300 A\n");
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk14")) <= -1) return -1;
|
||||
|
||||
// prepare a string to print lines with A in the fourth column
|
||||
StdAwk::SourceString in (QSE_T("$4 == \"A\" { print $2, $1, $3; }"));
|
||||
|
||||
// parse the script.
|
||||
if (awk.parse (in, StdAwk::Source::NONE) == QSE_NULL) return -1;
|
||||
StdAwk::Value r;
|
||||
|
||||
MyConsoleHandler* mch = (MyConsoleHandler*)awk.getConsoleHandler();
|
||||
|
||||
mch->setInput (instr); // locate the input string
|
||||
int x = awk.loop (&r); // execute the BEGIN, pattern-action, END blocks.
|
||||
|
||||
if (x >= 0)
|
||||
{
|
||||
qse_printf (QSE_T("%s"), mch->getOutput()); // print the console output
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
|
||||
mch->setInput (instr2);
|
||||
|
||||
// reset the runtime context so that the next loop() method
|
||||
// is performed over a new console stream.
|
||||
if (awk.resetRunContext() == QSE_NULL) return -1;
|
||||
|
||||
int x = awk.loop (&r);
|
||||
|
||||
if (x >= 0)
|
||||
{
|
||||
qse_printf (QSE_T("%s"), mch->getOutput());
|
||||
qse_printf (QSE_T("-----------------------------\n"));
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
|
||||
MyConsoleHandler mch;
|
||||
StdAwk awk;
|
||||
|
||||
int ret = awk.open ();
|
||||
if (ret >= 0)
|
||||
{
|
||||
awk.setConsoleHandler (&mch);
|
||||
ret = run_awk (awk);
|
||||
}
|
||||
|
||||
if (ret <= -1)
|
||||
{
|
||||
StdAwk::loc_t loc = awk.getErrorLocation();
|
||||
print_error (loc, awk.getErrorMessage());
|
||||
}
|
||||
|
||||
awk.close ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char locale[100];
|
||||
UINT codepage = GetConsoleOutputCP();
|
||||
if (codepage == CP_UTF8)
|
||||
{
|
||||
/*SetConsoleOUtputCP (CP_UTF8);*/
|
||||
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (locale, ".%u", (unsigned int)codepage);
|
||||
setlocale (LC_ALL, locale);
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
}
|
||||
#else
|
||||
setlocale (LC_ALL, "");
|
||||
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
||||
#endif
|
||||
|
||||
return qse_runmain (argc,argv,awk_main);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user