updated documentation
This commit is contained in:
		@ -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"), 
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
@ -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,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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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) 
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user