updated documentation

This commit is contained in:
2013-01-09 08:03:21 +00:00
parent 19b4e697af
commit 6e94d324ef
20 changed files with 1143 additions and 1317 deletions

View File

@ -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

View File

@ -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@

View File

@ -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"),
@ -99,31 +79,8 @@ int main ()
ret = -1; goto oops;
}
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;
}

View File

@ -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; \
}

View File

@ -40,63 +40,36 @@ 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[])
{
QSE::StdAwk awk;
int ret = awk.open();
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);
}

View File

@ -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"
"}"
));
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"
);
// add a global variable 'FOO'
int foo = awk.addGlobal (QSE_T("FOO"));
if (foo <= -1) return -1;
QSE::StdAwk::SourceString in (script);
QSE::StdAwk::SourceFile out (QSE_T("awk06.out"));
// parse the script and perform no deparsing
run = awk.parse (in, QSE::StdAwk::Source::NONE);
// parse the script and deparse it to awk06.out
run = awk.parse (in, out);
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;
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;
// 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;
// ret = add (-20, 51)
QSE::StdAwk::Value ret;
if (awk.call (QSE_T("add"), &ret, arg, 2) <= -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;
// ret = mul (ret, 51);
arg[0] = ret;
if (awk.call (QSE_T("mul"), &ret, arg, 2) <= -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;
// 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)r.toInt());
qse_printf (QSE_T(" (flt)[%Lf]\n"), (long double)r.toFlt());
qse_printf (QSE_T(" (str) [%s]\n"), r.toStr(QSE_NULL));
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));
// 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));
// ret = sine (ret);
arg[0] = ret;
if (awk.call (QSE_T("sine"), &ret, arg, 1) <= -1) return -1;
// 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()
);
iter = r.getNextIndex (&idx, iter);
}
// 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)
{

View File

@ -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());
}
}
#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);
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
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)
static int run_awk (QSE::StdAwk& awk)
{
int e = errno;
if (app_awk) app_awk->stop ();
errno = e;
}
#endif
QSE::StdAwk::Run* run;
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
}
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"
"}"
));
static void unset_signal (void)
{
#ifdef _WIN32
SetConsoleCtrlHandler (stop_run, FALSE);
#else
setsignal (SIGINT, SIG_DFL, 1);
#endif
}
// add a global variable 'FOO'
int foo = awk.addGlobal (QSE_T("FOO"));
if (foo <= -1) return -1;
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"));
}
// parse the script and perform no deparsing
run = awk.parse (in, QSE::StdAwk::Source::NONE);
if (run == QSE_NULL) return -1;
struct cmdline_t
{
qse_char_t* ins;
qse_char_t* inf;
qse_char_t* outf;
qse_char_t* outc;
qse_char_t* fs;
};
// set 'FOO' to 100000
QSE::StdAwk::Value foov (run);
if (foov.setInt (100000) <= -1) return -1;
if (awk.setGlobal (foo, foov) <= -1) return -1;
static int handle_cmdline (
MyAwk& awk, int argc, qse_char_t* argv[], cmdline_t* cmdline)
{
static qse_opt_t opt =
// prepare an indexed parameter
QSE::StdAwk::Value arg[1];
for (int i = 1; i <= 5; i++)
{
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 (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;
if (opt.ind < argc && !cmdline->inf)
cmdline->ins = argv[opt.ind++];
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;
while (opt.ind < argc)
// 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 (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;
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()
);
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);
}

View File

@ -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;
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;
}
void clearOutput () { this->output.clear (); }
const char_t* getOutput () { return this->output.c_str(); }
protected:
String input; // console input buffer
const char_t* inptr;
const char_t* inend;
String output; // console output buffer
int openConsole (Console& io)
{
return 1; // return open-success
}
int closeConsole (Console& io)
{
return 0; // return success
}
int flushConsole (Console& io)
int sleep (
Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
// 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);
return -1;
if (args[0].isIndexed())
{
run.setError (QSE_AWK_EINVAL);
return -1;
}
return size;
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)
static MyAwk* app_awk = QSE_NULL;
static void print_error (const qse_char_t* fmt, ...)
{
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);
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();
// 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 (loc.file)
{
qse_printf (QSE_T("%s"), awk.getOutput()); // print the console output
qse_printf (QSE_T("-----------------------------\n"));
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());
}
}
// 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;
#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;
}
awk.setInput (instr);
awk.clearOutput ();
return FALSE;
}
#else
int x = awk.loop (&r);
static int setsignal (int sig, void(*handler)(int), int restart)
{
struct sigaction sa_int;
if (x >= 0)
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)
{
qse_printf (QSE_T("%s"), awk.getOutput());
qse_printf (QSE_T("-----------------------------\n"));
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;
}
}
return x;
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;
}
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;
}

View File

@ -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);

View File

@ -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
View 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);
}