at work
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||
|
||||
SUFFIXES = .c .o
|
||||
AM_CFLAGS = -Wall
|
||||
AM_LDFLAGS = -pthread
|
||||
|
||||
.c.o:
|
||||
$(CC) -I. -pthread $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
noinst_LTLIBRARIES = libcworker.la
|
||||
libcworker_la_SOURCES = \
|
||||
cflexer.c \
|
||||
cfparser.c \
|
||||
cllexer.c \
|
||||
clparser.c \
|
||||
jlexer.c \
|
||||
jparser.c \
|
||||
logger.c \
|
||||
massert.c \
|
||||
rcache.c \
|
||||
jblock.c
|
||||
|
||||
include_HEADERS = \
|
||||
cflexer.h \
|
||||
cfparser.h \
|
||||
cllexer.h \
|
||||
clparser.h \
|
||||
jlexer.h \
|
||||
jparser.h \
|
||||
logger.h \
|
||||
massert.h \
|
||||
rcache.h \
|
||||
jblock.h
|
||||
|
||||
|
||||
if HAVE_VALGRIND
|
||||
VALGRIND_OPT = --tool=memcheck
|
||||
endif
|
||||
|
||||
test: $(bin_TESTS)
|
||||
@for test in $(bin_TESTS); do \
|
||||
echo ====== Test $${test} ======; \
|
||||
./$${test}; \
|
||||
echo ====== Done $${test} ======; \
|
||||
done
|
||||
|
||||
|
||||
valgrind: $(bin_TESTS)
|
||||
@for test in $(bin_TESTS); do \
|
||||
echo ====== Test $${test} ======; \
|
||||
$(VALGRIND) $(VALGRIND_OPT) ./$${test}; \
|
||||
echo ====== Done $${test} ======; \
|
||||
done
|
||||
|
||||
common_SOURCES = libcworker.la
|
||||
|
||||
bin_TESTS = \
|
||||
jblock_test
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
cfparser_test \
|
||||
clparser_test \
|
||||
cflexer_test \
|
||||
cfparser_test \
|
||||
cllexer_test \
|
||||
clparser_test \
|
||||
jlexer_test \
|
||||
jparser_test \
|
||||
rcache_test \
|
||||
jblock_test
|
||||
|
||||
#TESTS = $(bin_TESTS)
|
||||
|
||||
cflexer_test_SOURCES = cflexer_test.c $(common_SOURCES)
|
||||
cfparser_test_SOURCES = cfparser_test.c $(common_SOURCES)
|
||||
cllexer_test_SOURCES = cllexer_test.c $(common_SOURCES)
|
||||
clparser_test_SOURCES = clparser_test.c $(common_SOURCES)
|
||||
jlexer_test_SOURCES = jlexer_test.c $(common_SOURCES)
|
||||
jparser_test_SOURCES = jparser_test.c $(common_SOURCES)
|
||||
rcache_test_SOURCES = rcache_test.c $(common_SOURCES)
|
||||
jblock_test_SOURCES = jblock_test.c $(common_SOURCES)
|
||||
|
||||
|
||||
cflexer_test_LDADD = libcworker.la
|
||||
cfparser_test_LDADD = libcworker.la
|
||||
cllexer_test_LDADD = libcworker.la
|
||||
clparser_test_LDADD = libcworker.la
|
||||
jblock_test_LDADD = libcworker.la
|
||||
jlexer_test_LDADD = libcworker.la
|
||||
jparser_test_LDADD = libcworker.la
|
||||
rcache_test_LDADD = libcworker.la
|
||||
|
||||
|
||||
|
||||
clean-local:
|
||||
rm -rf *~
|
||||
@@ -0,0 +1,793 @@
|
||||
# Makefile.in generated by automake 1.16.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
noinst_PROGRAMS = cfparser_test$(EXEEXT) clparser_test$(EXEEXT) \
|
||||
cflexer_test$(EXEEXT) cfparser_test$(EXEEXT) \
|
||||
cllexer_test$(EXEEXT) clparser_test$(EXEEXT) \
|
||||
jlexer_test$(EXEEXT) jparser_test$(EXEEXT) \
|
||||
rcache_test$(EXEEXT) jblock_test$(EXEEXT)
|
||||
subdir = clib
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(include_HEADERS) \
|
||||
$(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/defines.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
PROGRAMS = $(noinst_PROGRAMS)
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libcworker_la_LIBADD =
|
||||
am_libcworker_la_OBJECTS = cflexer.lo cfparser.lo cllexer.lo \
|
||||
clparser.lo jlexer.lo jparser.lo logger.lo massert.lo \
|
||||
rcache.lo jblock.lo
|
||||
libcworker_la_OBJECTS = $(am_libcworker_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
am__objects_1 =
|
||||
am_cflexer_test_OBJECTS = cflexer_test.$(OBJEXT) $(am__objects_1)
|
||||
cflexer_test_OBJECTS = $(am_cflexer_test_OBJECTS)
|
||||
cflexer_test_DEPENDENCIES = libcworker.la
|
||||
am_cfparser_test_OBJECTS = cfparser_test.$(OBJEXT) $(am__objects_1)
|
||||
cfparser_test_OBJECTS = $(am_cfparser_test_OBJECTS)
|
||||
cfparser_test_DEPENDENCIES = libcworker.la
|
||||
am_cllexer_test_OBJECTS = cllexer_test.$(OBJEXT) $(am__objects_1)
|
||||
cllexer_test_OBJECTS = $(am_cllexer_test_OBJECTS)
|
||||
cllexer_test_DEPENDENCIES = libcworker.la
|
||||
am_clparser_test_OBJECTS = clparser_test.$(OBJEXT) $(am__objects_1)
|
||||
clparser_test_OBJECTS = $(am_clparser_test_OBJECTS)
|
||||
clparser_test_DEPENDENCIES = libcworker.la
|
||||
am_jblock_test_OBJECTS = jblock_test.$(OBJEXT) $(am__objects_1)
|
||||
jblock_test_OBJECTS = $(am_jblock_test_OBJECTS)
|
||||
jblock_test_DEPENDENCIES = libcworker.la
|
||||
am_jlexer_test_OBJECTS = jlexer_test.$(OBJEXT) $(am__objects_1)
|
||||
jlexer_test_OBJECTS = $(am_jlexer_test_OBJECTS)
|
||||
jlexer_test_DEPENDENCIES = libcworker.la
|
||||
am_jparser_test_OBJECTS = jparser_test.$(OBJEXT) $(am__objects_1)
|
||||
jparser_test_OBJECTS = $(am_jparser_test_OBJECTS)
|
||||
jparser_test_DEPENDENCIES = libcworker.la
|
||||
am_rcache_test_OBJECTS = rcache_test.$(OBJEXT) $(am__objects_1)
|
||||
rcache_test_OBJECTS = $(am_rcache_test_OBJECTS)
|
||||
rcache_test_DEPENDENCIES = libcworker.la
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp =
|
||||
am__maybe_remake_depfiles =
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(libcworker_la_SOURCES) $(cflexer_test_SOURCES) \
|
||||
$(cfparser_test_SOURCES) $(cllexer_test_SOURCES) \
|
||||
$(clparser_test_SOURCES) $(jblock_test_SOURCES) \
|
||||
$(jlexer_test_SOURCES) $(jparser_test_SOURCES) \
|
||||
$(rcache_test_SOURCES)
|
||||
DIST_SOURCES = $(libcworker_la_SOURCES) $(cflexer_test_SOURCES) \
|
||||
$(cfparser_test_SOURCES) $(cllexer_test_SOURCES) \
|
||||
$(clparser_test_SOURCES) $(jblock_test_SOURCES) \
|
||||
$(jlexer_test_SOURCES) $(jparser_test_SOURCES) \
|
||||
$(rcache_test_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(includedir)"
|
||||
HEADERS = $(include_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
APP_CACHEDIR = @APP_CACHEDIR@
|
||||
APP_CONFIGDIR = @APP_CONFIGDIR@
|
||||
APP_DATABASEDIR = @APP_DATABASEDIR@
|
||||
APP_LIBDIR = @APP_LIBDIR@
|
||||
APP_LOGDIR = @APP_LOGDIR@
|
||||
APP_RUNDIR = @APP_RUNDIR@
|
||||
APP_USER = @APP_USER@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CP = @CP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
HAVE_CP = @HAVE_CP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VALGRIND = @VALGRIND@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
app_cachedir = @app_cachedir@
|
||||
app_configdir = @app_configdir@
|
||||
app_databasedir = @app_databasedir@
|
||||
app_libdir = @app_libdir@
|
||||
app_logdir = @app_logdir@
|
||||
app_name = @app_name@
|
||||
app_rundir = @app_rundir@
|
||||
app_user = @app_user@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||
SUFFIXES = .c .o
|
||||
AM_CFLAGS = -Wall
|
||||
AM_LDFLAGS = -pthread
|
||||
noinst_LTLIBRARIES = libcworker.la
|
||||
libcworker_la_SOURCES = \
|
||||
cflexer.c \
|
||||
cfparser.c \
|
||||
cllexer.c \
|
||||
clparser.c \
|
||||
jlexer.c \
|
||||
jparser.c \
|
||||
logger.c \
|
||||
massert.c \
|
||||
rcache.c \
|
||||
jblock.c
|
||||
|
||||
include_HEADERS = \
|
||||
cflexer.h \
|
||||
cfparser.h \
|
||||
cllexer.h \
|
||||
clparser.h \
|
||||
jlexer.h \
|
||||
jparser.h \
|
||||
logger.h \
|
||||
massert.h \
|
||||
rcache.h \
|
||||
jblock.h
|
||||
|
||||
@HAVE_VALGRIND_TRUE@VALGRIND_OPT = --tool=memcheck
|
||||
common_SOURCES = libcworker.la
|
||||
bin_TESTS = \
|
||||
jblock_test
|
||||
|
||||
|
||||
#TESTS = $(bin_TESTS)
|
||||
cflexer_test_SOURCES = cflexer_test.c $(common_SOURCES)
|
||||
cfparser_test_SOURCES = cfparser_test.c $(common_SOURCES)
|
||||
cllexer_test_SOURCES = cllexer_test.c $(common_SOURCES)
|
||||
clparser_test_SOURCES = clparser_test.c $(common_SOURCES)
|
||||
jlexer_test_SOURCES = jlexer_test.c $(common_SOURCES)
|
||||
jparser_test_SOURCES = jparser_test.c $(common_SOURCES)
|
||||
rcache_test_SOURCES = rcache_test.c $(common_SOURCES)
|
||||
jblock_test_SOURCES = jblock_test.c $(common_SOURCES)
|
||||
cflexer_test_LDADD = libcworker.la
|
||||
cfparser_test_LDADD = libcworker.la
|
||||
cllexer_test_LDADD = libcworker.la
|
||||
clparser_test_LDADD = libcworker.la
|
||||
jblock_test_LDADD = libcworker.la
|
||||
jlexer_test_LDADD = libcworker.la
|
||||
jparser_test_LDADD = libcworker.la
|
||||
rcache_test_LDADD = libcworker.la
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .lo .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clib/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign clib/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstPROGRAMS:
|
||||
@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list || exit $$?; \
|
||||
test -n "$(EXEEXT)" || exit 0; \
|
||||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; \
|
||||
locs=`for p in $$list; do echo $$p; done | \
|
||||
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
|
||||
sort -u`; \
|
||||
test -z "$$locs" || { \
|
||||
echo rm -f $${locs}; \
|
||||
rm -f $${locs}; \
|
||||
}
|
||||
|
||||
libcworker.la: $(libcworker_la_OBJECTS) $(libcworker_la_DEPENDENCIES) $(EXTRA_libcworker_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(libcworker_la_OBJECTS) $(libcworker_la_LIBADD) $(LIBS)
|
||||
|
||||
cflexer_test$(EXEEXT): $(cflexer_test_OBJECTS) $(cflexer_test_DEPENDENCIES) $(EXTRA_cflexer_test_DEPENDENCIES)
|
||||
@rm -f cflexer_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(cflexer_test_OBJECTS) $(cflexer_test_LDADD) $(LIBS)
|
||||
|
||||
cfparser_test$(EXEEXT): $(cfparser_test_OBJECTS) $(cfparser_test_DEPENDENCIES) $(EXTRA_cfparser_test_DEPENDENCIES)
|
||||
@rm -f cfparser_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(cfparser_test_OBJECTS) $(cfparser_test_LDADD) $(LIBS)
|
||||
|
||||
cllexer_test$(EXEEXT): $(cllexer_test_OBJECTS) $(cllexer_test_DEPENDENCIES) $(EXTRA_cllexer_test_DEPENDENCIES)
|
||||
@rm -f cllexer_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(cllexer_test_OBJECTS) $(cllexer_test_LDADD) $(LIBS)
|
||||
|
||||
clparser_test$(EXEEXT): $(clparser_test_OBJECTS) $(clparser_test_DEPENDENCIES) $(EXTRA_clparser_test_DEPENDENCIES)
|
||||
@rm -f clparser_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(clparser_test_OBJECTS) $(clparser_test_LDADD) $(LIBS)
|
||||
|
||||
jblock_test$(EXEEXT): $(jblock_test_OBJECTS) $(jblock_test_DEPENDENCIES) $(EXTRA_jblock_test_DEPENDENCIES)
|
||||
@rm -f jblock_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(jblock_test_OBJECTS) $(jblock_test_LDADD) $(LIBS)
|
||||
|
||||
jlexer_test$(EXEEXT): $(jlexer_test_OBJECTS) $(jlexer_test_DEPENDENCIES) $(EXTRA_jlexer_test_DEPENDENCIES)
|
||||
@rm -f jlexer_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(jlexer_test_OBJECTS) $(jlexer_test_LDADD) $(LIBS)
|
||||
|
||||
jparser_test$(EXEEXT): $(jparser_test_OBJECTS) $(jparser_test_DEPENDENCIES) $(EXTRA_jparser_test_DEPENDENCIES)
|
||||
@rm -f jparser_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(jparser_test_OBJECTS) $(jparser_test_LDADD) $(LIBS)
|
||||
|
||||
rcache_test$(EXEEXT): $(rcache_test_OBJECTS) $(rcache_test_DEPENDENCIES) $(EXTRA_rcache_test_DEPENDENCIES)
|
||||
@rm -f rcache_test$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(rcache_test_OBJECTS) $(rcache_test_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
.c.obj:
|
||||
$(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-includeHEADERS: $(include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
|
||||
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
|
||||
done
|
||||
|
||||
uninstall-includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(includedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-local \
|
||||
clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-includeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-includeHEADERS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-local clean-noinstLTLIBRARIES \
|
||||
clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-includeHEADERS install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-includeHEADERS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -I. -pthread $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
test: $(bin_TESTS)
|
||||
@for test in $(bin_TESTS); do \
|
||||
echo ====== Test $${test} ======; \
|
||||
./$${test}; \
|
||||
echo ====== Done $${test} ======; \
|
||||
done
|
||||
|
||||
valgrind: $(bin_TESTS)
|
||||
@for test in $(bin_TESTS); do \
|
||||
echo ====== Test $${test} ======; \
|
||||
$(VALGRIND) $(VALGRIND_OPT) ./$${test}; \
|
||||
echo ====== Done $${test} ======; \
|
||||
done
|
||||
|
||||
clean-local:
|
||||
rm -rf *~
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rcache.h>
|
||||
#include <cflexer.h>
|
||||
|
||||
|
||||
#define CFLEXCONT_COMM 1
|
||||
#define CFLEXCONT_END 2
|
||||
#define CFLEXCONT_LWORD 3
|
||||
#define CFLEXCONT_SEPAR 4
|
||||
#define CFLEXCONT_SPACE 5
|
||||
#define CFLEXCONT_UNDEF 6
|
||||
#define CFLEXCONT_UNKNOW 7
|
||||
#define CFLEXCONT_WORD 8
|
||||
#define CFLEXCONT_NEWLN 9
|
||||
|
||||
#define CFLEXTYPE_CHAR 1
|
||||
#define CFLEXTYPE_COMM 2
|
||||
#define CFLEXTYPE_EOF 3
|
||||
#define CFLEXTYPE_NEWLN 4
|
||||
#define CFLEXTYPE_SCR 5
|
||||
#define CFLEXTYPE_SEPAR 6
|
||||
#define CFLEXTYPE_SPACE 7
|
||||
#define CFLEXTYPE_UNDEF 8
|
||||
#define CFLEXTYPE_WORDL 9
|
||||
|
||||
static int get_ltype(char letter) {
|
||||
switch (letter) {
|
||||
case EOF:
|
||||
return CFLEXTYPE_EOF;
|
||||
case ' ':
|
||||
case '\t':
|
||||
return CFLEXTYPE_SPACE;
|
||||
case '=':
|
||||
return CFLEXTYPE_SEPAR;
|
||||
case '\n':
|
||||
return CFLEXTYPE_NEWLN;
|
||||
case '#':
|
||||
return CFLEXTYPE_COMM;
|
||||
case '"':
|
||||
return CFLEXTYPE_WORDL;
|
||||
case '\\':
|
||||
return CFLEXTYPE_SCR;
|
||||
default:
|
||||
return CFLEXTYPE_CHAR;
|
||||
}
|
||||
return CFLEXTYPE_UNDEF;
|
||||
}
|
||||
|
||||
void cflexer_init(cflexer_t * lexer, rcache_t * cache) {
|
||||
lexer->cache = cache;
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
lexer->tokpos = 0;
|
||||
lexer->letter = EOF;
|
||||
lexer->rewind = false;
|
||||
lexer->screen = false;
|
||||
}
|
||||
|
||||
int cflexer_gettoken(cflexer_t * lexer, char* token) {
|
||||
|
||||
while (true) {
|
||||
if (!lexer->rewind) {
|
||||
lexer->letter = rcache_getc(lexer->cache);
|
||||
}
|
||||
lexer->rewind = false;
|
||||
int type = get_ltype(lexer->letter);
|
||||
|
||||
switch (lexer->context) {
|
||||
case CFLEXCONT_END:{
|
||||
lexer->context = CFLEXCONT_END;
|
||||
lexer->tokpos = 0;
|
||||
lexer->rewind = true;
|
||||
strcpy(token, "END");
|
||||
return CFLEXTOK_END;
|
||||
}
|
||||
case CFLEXCONT_UNDEF:{
|
||||
switch (type) {
|
||||
case CFLEXTYPE_EOF:{
|
||||
lexer->context = CFLEXCONT_END;
|
||||
lexer->rewind = true;
|
||||
break;
|
||||
}
|
||||
case CFLEXTYPE_CHAR:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = CFLEXCONT_WORD;
|
||||
break;
|
||||
}
|
||||
case CFLEXTYPE_SEPAR:{
|
||||
strcpy(token, "=");
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
return CFLEXTOK_SEPAR;
|
||||
}
|
||||
case CFLEXTYPE_NEWLN:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos] = '\0';
|
||||
strcpy(token, "NEWLN");
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
return CFLEXTOK_NEXT;
|
||||
}
|
||||
case CFLEXTYPE_SPACE:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos] = '\0';
|
||||
lexer->context = CFLEXCONT_SPACE;
|
||||
break;
|
||||
}
|
||||
case CFLEXTYPE_COMM:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos] = '\0';
|
||||
lexer->context = CFLEXCONT_COMM;
|
||||
break;
|
||||
}
|
||||
case CFLEXTYPE_WORDL:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos] = '\0';
|
||||
lexer->context = CFLEXCONT_LWORD;
|
||||
break;
|
||||
}
|
||||
case CFLEXTYPE_SCR: {
|
||||
lexer->tokpos = 0;
|
||||
lexer->screen = true;
|
||||
lexer->context = CFLEXCONT_WORD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CFLEXCONT_WORD:{
|
||||
switch (type) {
|
||||
case CFLEXTYPE_SCR: {
|
||||
if (lexer->screen == true) {
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->screen = false;
|
||||
} else {
|
||||
lexer->screen = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case CFLEXTYPE_CHAR:
|
||||
break;
|
||||
case CFLEXTYPE_EOF:
|
||||
default: {
|
||||
if (lexer->screen == true) {
|
||||
lexer->screen = false;
|
||||
break;
|
||||
}
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
lexer->screen = false;
|
||||
return CFLEXTOK_WORD;
|
||||
}
|
||||
}
|
||||
lexer->screen = false;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case CFLEXCONT_LWORD:{
|
||||
switch (type) {
|
||||
case CFLEXTYPE_SCR: {
|
||||
if (lexer->screen == true) {
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->screen = false;
|
||||
} else {
|
||||
lexer->screen = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case CFLEXTYPE_WORDL: {
|
||||
if (lexer->screen == true) {
|
||||
lexer->screen = false;
|
||||
break;
|
||||
}
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
lexer->screen = false;
|
||||
return CFLEXTOK_WORD;
|
||||
}
|
||||
case CFLEXTYPE_EOF: {
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
return CFLEXTOK_WORD;
|
||||
}
|
||||
default:{
|
||||
break;
|
||||
}
|
||||
}
|
||||
lexer->screen = false;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case CFLEXCONT_SPACE:{
|
||||
switch (type) {
|
||||
case CFLEXTYPE_SPACE:
|
||||
break;
|
||||
case CFLEXTYPE_EOF:
|
||||
default: {
|
||||
lexer->rewind = true;
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
continue;
|
||||
//lexer->context = CFLEXCONT_UNDEF;
|
||||
//lexer->rewind = true;
|
||||
//strcpy(token, "SPACE");
|
||||
//return CFLEXTOK_SPACE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CFLEXCONT_NEWLN:{
|
||||
switch (type) {
|
||||
case CFLEXTYPE_NEWLN:
|
||||
break;
|
||||
case CFLEXTYPE_EOF:
|
||||
default: {
|
||||
lexer->rewind = true;
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
strcpy(token, "NEWSLN");
|
||||
return CFLEXTOK_NEXT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CFLEXCONT_COMM:{
|
||||
switch (type) {
|
||||
case CFLEXTYPE_EOF:
|
||||
case CFLEXTYPE_NEWLN:
|
||||
lexer->context = CFLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
strcpy(token, "COMMENT");
|
||||
return CFLEXTOK_COMM;
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(token, "UNDEF");
|
||||
return CFLEXTOK_UNDEF;
|
||||
}
|
||||
|
||||
void cflexer_destroy(cflexer_t * lexer) {
|
||||
(void)lexer;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
#ifndef CFLEXER_H_QWERTY
|
||||
#define CFLEXER_H_QWERTY
|
||||
|
||||
#include <rcache.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
rcache_t* cache;
|
||||
int fd;
|
||||
int context;
|
||||
char letter;
|
||||
int tokpos;
|
||||
bool rewind;
|
||||
bool screen;
|
||||
} cflexer_t;
|
||||
|
||||
|
||||
#define CFLEXTOK_BLOCKB 1
|
||||
#define CFLEXTOK_COMM 2
|
||||
#define CFLEXTOK_END 3
|
||||
#define CFLEXTOK_NEXT 4
|
||||
#define CFLEXTOK_SEPAR 5
|
||||
#define CFLEXTOK_SPACE 6
|
||||
#define CFLEXTOK_UNDEF 7
|
||||
#define CFLEXTOK_UNKNOW 8
|
||||
#define CFLEXTOK_WORD 9
|
||||
|
||||
|
||||
void cflexer_init(cflexer_t * lexer, rcache_t * cache);
|
||||
int cflexer_gettoken(cflexer_t * lexer, char* token);
|
||||
void cflexer_destroy(cflexer_t * lexer);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <massert.h>
|
||||
#include <rcache.h>
|
||||
#include <cflexer.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
int fd = open("test.conf", O_RDONLY);
|
||||
MASSERT(fd > 0);
|
||||
|
||||
rcache_t cache;
|
||||
rcache_init(&cache, fd);
|
||||
|
||||
cflexer_t lexer;
|
||||
cflexer_init(&lexer, &cache);
|
||||
|
||||
char token[1024];
|
||||
int type = 0;
|
||||
|
||||
while ((type = cflexer_gettoken(&lexer, token)) != CFLEXTOK_END) {
|
||||
printf("[%d]: [%s]\n", type, token);
|
||||
}
|
||||
printf("[%d]: [%s]\n", type, token);
|
||||
|
||||
rcache_destroy(&cache);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <cfparser.h>
|
||||
#include <logger.h>
|
||||
|
||||
|
||||
#define INIT_BSIZE 64
|
||||
|
||||
|
||||
static char* strcopy(char* src) {
|
||||
size_t srcsize = strlen(src) + 1;
|
||||
char* dst = malloc(srcsize);
|
||||
|
||||
memset(dst, '\0', srcsize);
|
||||
strcpy(dst, src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char* strconcat(char** str, int num) {
|
||||
size_t tsize = 0;
|
||||
size_t size[num];
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
size[i] = 0;
|
||||
if (str[i] != NULL) {
|
||||
size[i] = strlen(str[i]);
|
||||
tsize += size[i];
|
||||
}
|
||||
}
|
||||
tsize++;
|
||||
char* dst = malloc(tsize);
|
||||
|
||||
memset(dst, '\0', tsize);
|
||||
int pos = 0;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (str[i] != NULL) {
|
||||
strcpy(&dst[pos], str[i]);
|
||||
pos += size[i];
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void cfparser_init(cfparser_t * parser, cflexer_t * lexer) {
|
||||
parser->lexer = lexer;
|
||||
parser->kvalarr = malloc(sizeof(cfkval_t) * INIT_BSIZE);
|
||||
parser->kvalcapa = INIT_BSIZE;
|
||||
parser->kvalsize = 0;
|
||||
}
|
||||
|
||||
int cfparser_bind(cfparser_t * parser, int type, char* key, void* ref) {
|
||||
for (int i = 0; i < parser->kvalsize; i++) {
|
||||
if (strcmp(key, parser->kvalarr[i].key) == 0) {
|
||||
char* key = parser->kvalarr[i].key;
|
||||
char* val = parser->kvalarr[i].val;
|
||||
switch (type) {
|
||||
case CFVALTYPE_STR: {
|
||||
*(char**)(ref) = strcopy(val);
|
||||
break;
|
||||
}
|
||||
case CFVALTYPE_INT: {
|
||||
for (size_t i = 0; i < strlen(val); i++) {
|
||||
if (isdigit(val[i]) == 0 && val[i] != '-' ) {
|
||||
log_error("wrong integer value: %s = %s", key, val);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
char* eptr = NULL;
|
||||
*(int64_t*)(ref) = (int64_t)strtol(val, &eptr, 10);
|
||||
break;
|
||||
}
|
||||
case CFVALTYPE_BOOL:{
|
||||
*(bool*)(ref) = false;
|
||||
if (strcmp(val, "true") == 0) {
|
||||
*(bool*)(ref) = true;
|
||||
} else if (strcmp(val, "false") == 0) {
|
||||
*(bool*)(ref) = false;
|
||||
} else {
|
||||
log_error("wrong boolean key value: %s = %s", key, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_TOKEN_SIZE 1024
|
||||
|
||||
|
||||
int cfparser_parse(cfparser_t * parser) {
|
||||
cflexer_t* lex = parser->lexer;
|
||||
|
||||
char token[MAX_TOKEN_SIZE];
|
||||
int type = 0;
|
||||
int pos = 0;
|
||||
|
||||
char* key;
|
||||
//char* val;
|
||||
|
||||
while ((type = cflexer_gettoken(lex, token)) != CFLEXTOK_END) {
|
||||
switch (pos) {
|
||||
// POS 0
|
||||
case 0:{
|
||||
if (type == CFLEXTOK_SPACE) continue;
|
||||
if (type == CFLEXTOK_COMM) continue;
|
||||
if (type == CFLEXTOK_NEXT) continue;
|
||||
if (type == CFLEXTOK_WORD) {
|
||||
key = strcopy(token);
|
||||
pos++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// POS 1
|
||||
case 1:{
|
||||
if (type == CFLEXTOK_SPACE) continue;
|
||||
if (type == CFLEXTOK_SEPAR) {
|
||||
pos++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// POS 2
|
||||
case 2:{
|
||||
if (type == CFLEXTOK_SPACE) continue;
|
||||
if (type == CFLEXTOK_WORD) {
|
||||
char* val = strcopy(token);
|
||||
if (parser->kvalsize >= parser->kvalcapa) {
|
||||
// TODO
|
||||
}
|
||||
parser->kvalarr[parser->kvalsize].key = key;
|
||||
parser->kvalarr[parser->kvalsize].val = val;
|
||||
parser->kvalsize++;
|
||||
pos++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:{
|
||||
if (type == CFLEXTOK_SPACE) continue;
|
||||
if (type == CFLEXTOK_COMM) continue;
|
||||
if (type == CFLEXTOK_NEXT) {
|
||||
pos = 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cfparser_destroy(cfparser_t * parser) {
|
||||
free(parser->kvalarr);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
#ifndef CFPARSER_H_QWERTY
|
||||
#define CFPARSER_H_QWERTY
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <cflexer.h>
|
||||
|
||||
typedef struct {
|
||||
char* key;
|
||||
char* val;
|
||||
} cfkval_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
cflexer_t* lexer;
|
||||
cfkval_t* kvalarr;
|
||||
int kvalcapa;
|
||||
int kvalsize;
|
||||
} cfparser_t;
|
||||
|
||||
#define CFVALTYPE_STR 1
|
||||
#define CFVALTYPE_INT 2
|
||||
#define CFVALTYPE_BOOL 3
|
||||
|
||||
void cfparser_init(cfparser_t* parser, cflexer_t* lexer);
|
||||
int cfparser_parse(cfparser_t* parser);
|
||||
int cfparser_bind(cfparser_t* parser, int type, char* key, void* ref);
|
||||
void cfparser_destroy(cfparser_t * parser);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <cflexer.h>
|
||||
#include <cfparser.h>
|
||||
#include <massert.h>
|
||||
#include <rcache.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
int fd = open("test.conf", O_RDONLY);
|
||||
MASSERT(fd > 0);
|
||||
|
||||
rcache_t cache;
|
||||
cflexer_t lexer;
|
||||
cfparser_t parser;
|
||||
|
||||
rcache_init(&cache, fd);
|
||||
cflexer_init(&lexer, &cache);
|
||||
cfparser_init(&parser, &lexer);
|
||||
|
||||
if (cfparser_parse(&parser)) {
|
||||
printf("parse args error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int64_t id = 0;
|
||||
char* name = "";
|
||||
bool debug = false;
|
||||
|
||||
cfparser_bind(&parser, CFVALTYPE_BOOL, "debug", (void *)&debug);
|
||||
cfparser_bind(&parser, CFVALTYPE_INT, "id", (void *)&id);
|
||||
cfparser_bind(&parser, CFVALTYPE_STR, "name", (void *)&name);
|
||||
|
||||
cfparser_destroy(&parser);
|
||||
cflexer_destroy(&lexer);
|
||||
rcache_destroy(&cache);
|
||||
|
||||
MASSERT(id == -123);
|
||||
MASSERT(strcmp(name, "qwerty\"567") == 0);
|
||||
MASSERT(debug == true);
|
||||
|
||||
printf("id = %ld\n", id);
|
||||
printf("name = %s\n", name);
|
||||
printf("debug = %d\n", debug);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cllexer.h>
|
||||
|
||||
#define CLLEXCONT_UNDEF 0
|
||||
#define CLLEXCONT_KEY 1
|
||||
#define CLLEXCONT_WORD 2
|
||||
#define CLLEXCONT_SPACE 3
|
||||
#define CLLEXCONT_SEP 4
|
||||
#define CLLEXCONT_END 5
|
||||
#define CLLEXCONT_LWORD 6
|
||||
|
||||
#define CLLEXTYPE_UNDEF 0
|
||||
#define CLLEXTYPE_KEY 1
|
||||
#define CLLEXTYPE_CHAR 2
|
||||
#define CLLEXTYPE_SEP 3
|
||||
#define CLLEXTYPE_SPACE 4
|
||||
#define CLLEXTYPE_WORDL 5
|
||||
#define CLLEXTYPE_SCR 6
|
||||
#define CLLEXTYPE_EOF 7
|
||||
|
||||
static int get_ltype(char letter) {
|
||||
switch (letter) {
|
||||
case EOF:
|
||||
return CLLEXTYPE_EOF;
|
||||
case '"':
|
||||
return CLLEXTYPE_WORDL;
|
||||
case '\\':
|
||||
return CLLEXTYPE_SCR;
|
||||
case '-':
|
||||
return CLLEXTYPE_KEY;
|
||||
case ' ':
|
||||
case '\t':
|
||||
return CLLEXTYPE_SPACE;
|
||||
case '=':
|
||||
return CLLEXTYPE_SEP;
|
||||
default:
|
||||
return CLLEXTYPE_CHAR;
|
||||
}
|
||||
return CLLEXTYPE_UNDEF;
|
||||
}
|
||||
|
||||
void cllexer_init(cllexer_t * lexer) {
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->tokpos = 0;
|
||||
lexer->letter = EOF;
|
||||
lexer->rewind = false;
|
||||
lexer->argstr = NULL;
|
||||
lexer->arglen = 0;
|
||||
lexer->argpos = 0;
|
||||
lexer->screen = false;
|
||||
}
|
||||
|
||||
void cllexer_reset(cllexer_t * lexer, char* argstr) {
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->tokpos = 0;
|
||||
lexer->letter = EOF;
|
||||
lexer->rewind = false;
|
||||
lexer->argstr = argstr;
|
||||
lexer->arglen = strlen(argstr);
|
||||
lexer->argpos = 0;
|
||||
lexer->screen = false;
|
||||
}
|
||||
|
||||
int cllexer_gettoken(cllexer_t * lexer, char* token) {
|
||||
while (true) {
|
||||
if (!lexer->rewind) {
|
||||
if (lexer->argpos >= lexer->arglen) {
|
||||
lexer->letter = EOF;
|
||||
} else {
|
||||
lexer->letter = lexer->argstr[lexer->argpos++];
|
||||
}
|
||||
}
|
||||
lexer->rewind = false;
|
||||
|
||||
int type = get_ltype(lexer->letter);
|
||||
|
||||
switch (lexer->context) {
|
||||
case CLLEXCONT_END:{
|
||||
lexer->context = CLLEXCONT_END;
|
||||
lexer->tokpos = 0;
|
||||
strcpy(token, "END");
|
||||
return CLLEXTOK_END;
|
||||
}
|
||||
case CLLEXCONT_UNDEF:{
|
||||
switch (type) {
|
||||
case CLLEXTYPE_WORDL:{
|
||||
lexer->tokpos = 0;
|
||||
lexer->context = CLLEXCONT_LWORD;
|
||||
break;
|
||||
}
|
||||
case CLLEXTYPE_EOF:{
|
||||
lexer->tokpos = 0;
|
||||
lexer->context = CLLEXCONT_END;
|
||||
lexer->rewind = true;
|
||||
break;
|
||||
}
|
||||
case CLLEXTYPE_KEY:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = CLLEXCONT_KEY;
|
||||
break;
|
||||
}
|
||||
case CLLEXTYPE_SEP:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = CLLEXCONT_SEP;
|
||||
break;
|
||||
}
|
||||
case CLLEXTYPE_SCR: {
|
||||
lexer->tokpos = 0;
|
||||
lexer->screen = true;
|
||||
lexer->context = CLLEXCONT_WORD;
|
||||
break;
|
||||
}
|
||||
case CLLEXTYPE_CHAR:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = CLLEXCONT_WORD;
|
||||
break;
|
||||
}
|
||||
case CLLEXTYPE_SPACE:{
|
||||
lexer->tokpos = 0;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = CLLEXCONT_SPACE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLLEXCONT_KEY:{
|
||||
switch (type) {
|
||||
case CLLEXTYPE_KEY:
|
||||
break;
|
||||
case CLLEXTYPE_EOF:
|
||||
default:{
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
return CLLEXTOK_KEY;
|
||||
}
|
||||
}
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case CLLEXCONT_WORD:{
|
||||
switch (type) {
|
||||
case CLLEXTYPE_SCR: {
|
||||
if (lexer->screen == true) {
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->screen = false;
|
||||
} else {
|
||||
lexer->screen = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case CLLEXTYPE_CHAR:
|
||||
break;
|
||||
case CLLEXTYPE_EOF:
|
||||
default: {
|
||||
if (lexer->screen == true) {
|
||||
lexer->screen = false;
|
||||
break;
|
||||
}
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
return CLLEXTOK_WORD;
|
||||
}
|
||||
}
|
||||
lexer->screen = false;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case CLLEXCONT_LWORD:{
|
||||
switch (type) {
|
||||
case CLLEXTYPE_SCR:
|
||||
if (lexer->screen == true) {
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->screen = false;
|
||||
} else {
|
||||
lexer->screen = true;
|
||||
}
|
||||
continue;
|
||||
case CLLEXTYPE_WORDL:
|
||||
if (lexer->screen == true) {
|
||||
lexer->screen = false;
|
||||
break;
|
||||
}
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->screen = false;
|
||||
return CLLEXTOK_WORD;
|
||||
case CLLEXTYPE_EOF:
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
lexer->screen = false;
|
||||
return CLLEXTOK_WORD;
|
||||
default:{
|
||||
break;
|
||||
}
|
||||
}
|
||||
lexer->screen = false;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case CLLEXCONT_SPACE:{
|
||||
switch (type) {
|
||||
case CLLEXTYPE_SPACE:
|
||||
break;
|
||||
case CLLEXTYPE_EOF:
|
||||
default:{
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
return CLLEXTOK_SPACE;
|
||||
}
|
||||
}
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case CLLEXCONT_SEP:{
|
||||
switch (type) {
|
||||
case CLLEXTYPE_SEP:
|
||||
break;
|
||||
case CLLEXTYPE_EOF:
|
||||
default:{
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = CLLEXCONT_UNDEF;
|
||||
lexer->rewind = true;
|
||||
return CLLEXTOK_SEP;
|
||||
}
|
||||
}
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(token, "UNDEF");
|
||||
return CLLEXTOK_UNDEF;
|
||||
}
|
||||
|
||||
void cllexer_destroy(cllexer_t * lexer) {
|
||||
(void)lexer;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef CLLEXER_H_QWERTY
|
||||
#define CLLEXER_H_QWERTY
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
int context;
|
||||
char letter;
|
||||
int tokpos;
|
||||
bool rewind;
|
||||
char* argstr;
|
||||
int arglen;
|
||||
int argpos;
|
||||
bool screen;
|
||||
} cllexer_t;
|
||||
|
||||
|
||||
#define CLLEXTOK_UNDEF 0
|
||||
#define CLLEXTOK_KEY 1
|
||||
#define CLLEXTOK_WORD 2
|
||||
#define CLLEXTOK_SPACE 3
|
||||
#define CLLEXTOK_SEP 4
|
||||
#define CLLEXTOK_END 5
|
||||
|
||||
void cllexer_init(cllexer_t* lexer);
|
||||
void cllexer_reset(cllexer_t* lexer, char* argstr);
|
||||
int cllexer_gettoken(cllexer_t* lexer, char* token);
|
||||
void cllexer_destroy(cllexer_t* lexer);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cllexer.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
char* src = "\\\"---\"\\\"qwer\\1-ty\"=\"a123-45\\\" \\\"5678\"";
|
||||
|
||||
cllexer_t lexer;
|
||||
|
||||
cllexer_init(&lexer);
|
||||
cllexer_reset(&lexer, src);
|
||||
|
||||
char token[1024];
|
||||
int type = 0;
|
||||
|
||||
while ((type = cllexer_gettoken(&lexer, token)) != CLLEXTOK_END) {
|
||||
printf("[%d]: [%s]\n", type, token);
|
||||
}
|
||||
printf("[%d]: [%s]\n", type, token);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <logger.h>
|
||||
#include <clparser.h>
|
||||
|
||||
#define INIT_BSIZE 64
|
||||
|
||||
|
||||
static char* strcopy(char* src) {
|
||||
size_t srcsize = strlen(src) + 1;
|
||||
char* dst = malloc(srcsize);
|
||||
|
||||
memset(dst, '\0', srcsize);
|
||||
strcpy(dst, src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
#if 1
|
||||
static char* strconcat(char** str, int num) {
|
||||
size_t tsize = 0;
|
||||
size_t size[num];
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
size[i] = 0;
|
||||
if (str[i] != NULL) {
|
||||
size[i] = strlen(str[i]);
|
||||
tsize += size[i];
|
||||
}
|
||||
}
|
||||
tsize++;
|
||||
char* dst = malloc(tsize);
|
||||
|
||||
memset(dst, '\0', tsize);
|
||||
int pos = 0;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (str[i] != NULL) {
|
||||
strcpy(&dst[pos], str[i]);
|
||||
pos += size[i];
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
void clparser_init(clparser_t * parser, cllexer_t * lexer) {
|
||||
parser->lexer = lexer;
|
||||
parser->bindarr = malloc(sizeof(clbind_t) * INIT_BSIZE);
|
||||
parser->bindcapa = INIT_BSIZE;
|
||||
parser->bindsize = 0;
|
||||
}
|
||||
|
||||
void clparser_bind(clparser_t * parser, int type, char* key, void* ref) {
|
||||
if (parser->bindsize >= parser->bindcapa) {
|
||||
return; // TODO
|
||||
}
|
||||
clbind_t* b = &(parser->bindarr[parser->bindsize]);
|
||||
|
||||
b->type = type;
|
||||
b->key = key;
|
||||
b->ref = ref;
|
||||
parser->bindsize++;
|
||||
}
|
||||
|
||||
#define MAX_TOKEN_SIZE 1024
|
||||
|
||||
static int clparser_compile(clparser_t * parser, char* arg, char** refkey, char** refval) {
|
||||
cllexer_t* lex = parser->lexer;
|
||||
|
||||
cllexer_reset(lex, arg);
|
||||
|
||||
char token[MAX_TOKEN_SIZE];
|
||||
int type = 0;
|
||||
int pos = 0;
|
||||
|
||||
char* key;
|
||||
char* vals[2] = { NULL };
|
||||
|
||||
while ((type = cllexer_gettoken(lex, token)) != CLLEXTOK_END) {
|
||||
switch (pos) {
|
||||
// POS 0
|
||||
case 0:{
|
||||
if (type == CLLEXTOK_KEY) {
|
||||
pos++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// POS 1
|
||||
case 1:{
|
||||
if (type == CLLEXTOK_WORD) {
|
||||
key = strcopy(token);
|
||||
pos++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// POS 2
|
||||
case 2:{
|
||||
if (type == CLLEXTOK_SEP) {
|
||||
pos++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// POS 3
|
||||
case 3:{
|
||||
if (type == CLLEXTOK_WORD || type == CLLEXTOK_KEY) {
|
||||
pos++;
|
||||
vals[0] = strcopy(token);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// POS 4
|
||||
case 4:{
|
||||
if (type == CLLEXTOK_WORD) {
|
||||
pos++;
|
||||
vals[1] = strcopy(token);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
*refkey = key;
|
||||
*refval = strconcat(vals, 2);
|
||||
free(vals[0]);
|
||||
free(vals[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clparser_parse(clparser_t * parser, char** argv, int argc) {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
char* key;
|
||||
char* val;
|
||||
|
||||
if (clparser_compile(parser, argv[i], &key, &val) < 0) {
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < parser->bindsize; i++) {
|
||||
if (strcmp(parser->bindarr[i].key, key) == 0) {
|
||||
switch (parser->bindarr[i].type) {
|
||||
case CLVALTYPE_STR:{
|
||||
*(char **)(parser->bindarr[i].ref) = strcopy(val);
|
||||
free(key);
|
||||
free(val);
|
||||
break;
|
||||
}
|
||||
case CLVALTYPE_INT:{
|
||||
for (size_t i = 0; i < strlen(val); i++) {
|
||||
if (isdigit(val[i]) == 0 && val[i] != '-' ) {
|
||||
log_error("wrong integer value: %s = %s", key, val);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
char* eptr = NULL;
|
||||
*(int *)(parser->bindarr[i].ref) = (int)strtol(val, &eptr, 10);
|
||||
free(key);
|
||||
free(val);
|
||||
break;
|
||||
}
|
||||
case CLVALTYPE_BOOL:{
|
||||
*(bool*)(parser->bindarr[i].ref) = false;
|
||||
if (strcmp(val, "true") == 0) {
|
||||
*(bool*)(parser->bindarr[i].ref) = true;
|
||||
} else if (strcmp(val, "false") == 0) {
|
||||
*(bool*)(parser->bindarr[i].ref) = false;
|
||||
} else {
|
||||
log_error("wrong boolean value: %s = %s", key, val);
|
||||
//return -1;
|
||||
}
|
||||
free(key);
|
||||
free(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clparser_destroy(clparser_t * parser) {
|
||||
free(parser->bindarr);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef CLPARSER_H_QWERTY
|
||||
#define CLPARSER_H_QWERTY
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <cllexer.h>
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
char* key;
|
||||
void* ref;
|
||||
} clbind_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
cllexer_t* lexer;
|
||||
clbind_t* bindarr;
|
||||
int bindcapa;
|
||||
int bindsize;
|
||||
} clparser_t;
|
||||
|
||||
#define CLVALTYPE_INT 1
|
||||
#define CLVALTYPE_STR 2
|
||||
#define CLVALTYPE_BOOL 3
|
||||
|
||||
void clparser_init(clparser_t* parser, cllexer_t* lexer);
|
||||
void clparser_bind(clparser_t* parser, int type, char* key, void* ref);
|
||||
int clparser_parse(clparser_t* parser, char** argv, int argc);
|
||||
void clparser_destroy(clparser_t * parser);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cllexer.h>
|
||||
#include <clparser.h>
|
||||
|
||||
int main(void) {
|
||||
//(void)argc;
|
||||
//(void)argv;
|
||||
|
||||
char* argv[] = { "main", "--id=-123", "--name=qwerty12234", "--debug=truew" };
|
||||
int argc = 4;
|
||||
|
||||
cllexer_t lexer;
|
||||
clparser_t parser;
|
||||
|
||||
cllexer_init(&lexer);
|
||||
clparser_init(&parser, &lexer);
|
||||
|
||||
int id = 0;
|
||||
char* name = "";
|
||||
bool debug = false;
|
||||
|
||||
clparser_bind(&parser, CLVALTYPE_INT, "id", (void *)&id);
|
||||
clparser_bind(&parser, CLVALTYPE_STR, "name", (void *)&name);
|
||||
clparser_bind(&parser, CLVALTYPE_BOOL, "debug", (void *)&debug);
|
||||
|
||||
if (clparser_parse(&parser, &argv[1], argc - 1) < 0) {
|
||||
printf("parse args error\n");
|
||||
return 1;
|
||||
}
|
||||
printf("id = %d\n", id);
|
||||
printf("name = %s\n", name);
|
||||
printf("debug = %d\n", debug);
|
||||
|
||||
clparser_destroy(&parser);
|
||||
cllexer_destroy(&lexer);
|
||||
|
||||
free(name);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef CONFIG_H_QWER
|
||||
#define CONFIG_H_QWER
|
||||
|
||||
static const char *srv_runpath = "/home/ziggi/Projects/cworker/run/cworker.pid";
|
||||
static const char *srv_logpath = "/home/ziggi/Projects/cworker/log/cworker.log";
|
||||
static const char *srv_configpath = "/home/ziggi/Projects/cworker//cworker.conf";
|
||||
|
||||
#endif
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
/* defines.h. Generated from defines.h.in by configure. */
|
||||
/* defines.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* location of cache dir */
|
||||
#define APP_CACHEDIR "/home/ziggi/Projects/cworker/cache"
|
||||
|
||||
/* location of configuration files for ${PACKAGE} */
|
||||
#define APP_CONFIGDIR "/home/ziggi/Projects/cworker/"
|
||||
|
||||
/* location of database dir */
|
||||
#define APP_DATABASEDIR "/home/ziggi/Projects/cworker/data"
|
||||
|
||||
/* location of libs */
|
||||
#define APP_LIBDIR "/home/ziggi/Projects/cworker/lib"
|
||||
|
||||
/* location of ${PACKAGE} logdir */
|
||||
#define APP_LOGDIR "/home/ziggi/Projects/cworker/log"
|
||||
|
||||
/* location of pid file */
|
||||
#define APP_RUNDIR "/home/ziggi/Projects/cworker/run"
|
||||
|
||||
/* effective user */
|
||||
#define APP_USER "ziggi"
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't.
|
||||
*/
|
||||
/* #undef HAVE_DECL_TZNAME */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `dup2' function. */
|
||||
#define HAVE_DUP2 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#define HAVE_FORK 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `mkdir' function. */
|
||||
#define HAVE_MKDIR 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#define HAVE_SETLOCALE 1
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#define HAVE_SOCKET 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if `tm_zone' is a member of `struct tm'. */
|
||||
#define HAVE_STRUCT_TM_TM_ZONE 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
|
||||
`HAVE_STRUCT_TM_TM_ZONE' instead. */
|
||||
#define HAVE_TM_ZONE 1
|
||||
|
||||
/* Define to 1 if you don't have `tm_zone' but do have the external array
|
||||
`tzname'. */
|
||||
/* #undef HAVE_TZNAME */
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#define HAVE_VFORK 1
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
/* #undef HAVE_VFORK_H */
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#define HAVE_WCHAR_H 1
|
||||
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#define HAVE_WCTYPE_H 1
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#define HAVE_WORKING_FORK 1
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#define HAVE_WORKING_VFORK 1
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#define HAVE__BOOL 1
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "cworker"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "cworker"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "cworker 0.0.1"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "cworker"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.0.1"
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||
/* #undef TM_IN_SYS_TIME */
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
/* #undef malloc */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef mode_t */
|
||||
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef ssize_t */
|
||||
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
/* #undef vfork */
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <jblock.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define INIT_CAPA 64
|
||||
|
||||
static void* jstring_init(jstring_t* str);
|
||||
static void* jstring_append(jstring_t* str, char* add);
|
||||
static char* jstring_getref(jstring_t* str);
|
||||
static char* strcopy(char* src);
|
||||
|
||||
void jblock_init(jblock_t* jb) {
|
||||
jb->kvsize = 0;
|
||||
jb->kvcapa = INIT_CAPA;
|
||||
jb->kvarr = malloc(sizeof(jkeyval_t) * INIT_CAPA);
|
||||
}
|
||||
|
||||
static void* jblock_checkalloc(jblock_t* jb) {
|
||||
if (jb->kvsize == jb->kvcapa) {
|
||||
size_t newsize = jb->kvcapa * 2;
|
||||
jkeyval_t* newarr = realloc(jb->kvarr, sizeof(jkeyval_t) * newsize);
|
||||
if (newarr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
jb->kvarr = newarr;
|
||||
jb->kvcapa = newsize;
|
||||
}
|
||||
return jb->kvarr;
|
||||
}
|
||||
|
||||
static bool jblock_keyexists(jblock_t* jb, char* key) {
|
||||
for (int i = 0; i < jb->kvsize; i++) {
|
||||
if (strcmp(key, jb->kvarr[i].key) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int jblock_addint(jblock_t* jb, char* key, int64_t val) {
|
||||
if (jblock_keyexists(jb, key)) {
|
||||
return -2;
|
||||
}
|
||||
if (jblock_checkalloc(jb) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
jb->kvarr[jb->kvsize].key = strcopy(key);
|
||||
jb->kvarr[jb->kvsize].num = val;
|
||||
jb->kvarr[jb->kvsize].type = JKVTYPE_INT;
|
||||
return ++jb->kvsize;
|
||||
}
|
||||
|
||||
int jblock_addfloat(jblock_t* jb, char* key, double val) {
|
||||
if (jblock_keyexists(jb, key)) {
|
||||
return -2;
|
||||
}
|
||||
if (jblock_checkalloc(jb) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
jb->kvarr[jb->kvsize].key = strcopy(key);
|
||||
jb->kvarr[jb->kvsize].flt = val;
|
||||
jb->kvarr[jb->kvsize].type = JKVTYPE_FLT;
|
||||
return ++jb->kvsize;
|
||||
}
|
||||
|
||||
int jblock_addbool(jblock_t* jb, char* key, bool val) {
|
||||
if (jblock_keyexists(jb, key)) {
|
||||
return -2;
|
||||
}
|
||||
if (jblock_checkalloc(jb) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
jb->kvarr[jb->kvsize].key = strcopy(key);
|
||||
jb->kvarr[jb->kvsize].flag = val;
|
||||
jb->kvarr[jb->kvsize].type = JKVTYPE_BOOL;
|
||||
return ++jb->kvsize;
|
||||
}
|
||||
|
||||
int jblock_addstr(jblock_t* jb, char* key, char* val) {
|
||||
if (jblock_keyexists(jb, key)) {
|
||||
return -2;
|
||||
}
|
||||
if (jblock_checkalloc(jb) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
jb->kvarr[jb->kvsize].key = strcopy(key);
|
||||
jb->kvarr[jb->kvsize].str = strcopy(val);
|
||||
jb->kvarr[jb->kvsize].type = JKVTYPE_STR;
|
||||
return ++jb->kvsize;
|
||||
}
|
||||
|
||||
void jblock_outjson(jblock_t* jb, char** res) {
|
||||
jstring_t jstr;
|
||||
jstring_init(&jstr);
|
||||
jstring_append(&jstr, "{");
|
||||
for (int i = 0; i < jb->kvsize; i++) {
|
||||
switch (jb->kvarr[i].type) {
|
||||
case JKVTYPE_STR:
|
||||
case JKVTYPE_BOOL:
|
||||
case JKVTYPE_FLT:
|
||||
case JKVTYPE_INT: {
|
||||
char* buffer = NULL;
|
||||
asprintf(&buffer, "\"%s\":", jb->kvarr[i].key);
|
||||
jstring_append(&jstr, buffer);
|
||||
free(buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch (jb->kvarr[i].type) {
|
||||
case JKVTYPE_INT: {
|
||||
char* buffer = NULL;
|
||||
asprintf(&buffer, "%ld", jb->kvarr[i].num);
|
||||
jstring_append(&jstr, buffer);
|
||||
free(buffer);
|
||||
break;
|
||||
}
|
||||
case JKVTYPE_FLT: {
|
||||
char* buffer = NULL;
|
||||
asprintf(&buffer, "%e", jb->kvarr[i].flt);
|
||||
jstring_append(&jstr, buffer);
|
||||
free(buffer);
|
||||
break;
|
||||
}
|
||||
case JKVTYPE_BOOL: {
|
||||
if (jb->kvarr[i].flag) {
|
||||
jstring_append(&jstr, "true");
|
||||
} else {
|
||||
jstring_append(&jstr, "false");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JKVTYPE_STR: {
|
||||
char* buffer = NULL;
|
||||
asprintf(&buffer, "\"%s\"", jb->kvarr[i].str);
|
||||
jstring_append(&jstr, buffer);
|
||||
free(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < jb->kvsize - 1) {
|
||||
jstring_append(&jstr, ",");
|
||||
}
|
||||
}
|
||||
jstring_append(&jstr, "}");
|
||||
*res = jstring_getref(&jstr);
|
||||
}
|
||||
|
||||
|
||||
void jblock_destroy(jblock_t* jb) {
|
||||
if (jb == NULL) return;
|
||||
for (int i = 0; i < jb->kvsize; i++) {
|
||||
free(jb->kvarr[i].key);
|
||||
switch (jb->kvarr[i].type) {
|
||||
case JKVTYPE_STR: {
|
||||
free(jb->kvarr[i].str);
|
||||
}
|
||||
}
|
||||
}
|
||||
jb->kvsize = 0;
|
||||
jb->kvcapa = 0;
|
||||
jb->kvarr = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void* jstring_init(jstring_t* str) {
|
||||
str->data = malloc(INIT_CAPA + 1);
|
||||
if (str->data == NULL) return NULL;
|
||||
memset(str->data, '\0', INIT_CAPA + 1);
|
||||
str->capa = INIT_CAPA;
|
||||
str->size = 0;
|
||||
return str->data;
|
||||
}
|
||||
|
||||
|
||||
static void* jstring_append(jstring_t* str, char* add) {
|
||||
size_t addsize = strlen(add);
|
||||
size_t newsize = str->size + addsize;
|
||||
if (newsize > str->capa) {
|
||||
char* newstr = malloc(newsize + 1);
|
||||
if (newstr == NULL) return NULL;
|
||||
}
|
||||
strcpy(&(str->data[str->size]), add);
|
||||
str->data[newsize + 1] = '\0';
|
||||
str->capa = newsize;
|
||||
str->size = newsize;
|
||||
return str->data;
|
||||
}
|
||||
|
||||
static char* jstring_getref(jstring_t* str) {
|
||||
return str->data;
|
||||
}
|
||||
|
||||
static char* strcopy(char* src) {
|
||||
size_t srcsize = strlen(src) + 1;
|
||||
char* dst = malloc(srcsize);
|
||||
memset(dst, '\0', srcsize);
|
||||
strcpy(dst, src);
|
||||
return dst;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
#ifndef JKEYVAL_H_QWERTY
|
||||
#define JKEYVAL_H_QWERTY
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
char* data;
|
||||
int capa;
|
||||
int size;
|
||||
} jstring_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
char* key;
|
||||
int type;
|
||||
union {
|
||||
int64_t num;
|
||||
bool flag;
|
||||
char* str;
|
||||
double flt;
|
||||
int64_t* numarr;
|
||||
char** strarr;
|
||||
double* fltarr;
|
||||
bool* flagarr;
|
||||
};
|
||||
int arrsize;
|
||||
int arrcapa;
|
||||
} jkeyval_t;
|
||||
|
||||
typedef struct {
|
||||
jkeyval_t* kvarr;
|
||||
int kvsize;
|
||||
int kvcapa;
|
||||
} jblock_t;
|
||||
|
||||
#define JKVTYPE_INT 0x01
|
||||
#define JKVTYPE_STR 0x02
|
||||
#define JKVTYPE_BOOL 0x03
|
||||
#define JKVTYPE_FLT 0x04
|
||||
#define JKVTYPE_INTARR 0x11
|
||||
#define JKVTYPE_STRARR 0x12
|
||||
#define JKVTYPE_BOOLARR 0x13
|
||||
#define JKVTYPE_FLTARR 0x14
|
||||
|
||||
#define JB_MALLOCERR -1
|
||||
#define JB_KEYEXISTS -2
|
||||
|
||||
|
||||
void jblock_init(jblock_t* kv);
|
||||
void jblock_outjson(jblock_t* kv, char** res);
|
||||
void jblock_destroy(jblock_t* kv);
|
||||
|
||||
int jblock_addint(jblock_t* kv, char* key, int64_t val);
|
||||
int jblock_addfloat(jblock_t* kv, char* key, double val);
|
||||
int jblock_addstr(jblock_t* kv, char* key, char* val);
|
||||
int jblock_addbool(jblock_t* kv, char* key, bool val);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <massert.h>
|
||||
#include <jblock.h>
|
||||
|
||||
|
||||
void test01(void) {
|
||||
jblock_t jb;
|
||||
|
||||
jblock_init(&jb);
|
||||
jblock_addint(&jb, "id1", 12345);
|
||||
jblock_addstr(&jb, "id2", "qwerty");
|
||||
jblock_addbool(&jb, "b1", true);
|
||||
jblock_addbool(&jb, "b2", false);
|
||||
jblock_addfloat(&jb, "f1", (double)123e1);
|
||||
|
||||
char* jsonstr = NULL;
|
||||
jblock_outjson(&jb, &jsonstr);
|
||||
jblock_destroy(&jb);
|
||||
|
||||
printf("%s\n", jsonstr);
|
||||
free(jsonstr);
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
test01();
|
||||
return 0;
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rcache.h>
|
||||
#include <jlexer.h>
|
||||
|
||||
#define JLEXCONT_UNDEF 0
|
||||
#define JLEXCONT_WORD 1
|
||||
#define JLEXCONT_BLOCKB 2
|
||||
#define JLEXCONT_BLOCKE 3
|
||||
#define JLEXCONT_SEPAR 4
|
||||
#define JLEXCONT_NUM 5
|
||||
#define JLEXCONT_UNKNOW 6
|
||||
#define JLEXCONT_END 9
|
||||
|
||||
#define JLEXTYPE_UNDEF 0
|
||||
#define JLEXTYPE_BLOCKB 1
|
||||
#define JLEXTYPE_BLOCKE 2
|
||||
#define JLEXTYPE_WORDL 3
|
||||
#define JLEXTYPE_SPACE 4
|
||||
#define JLEXTYPE_SEPAR 5
|
||||
#define JLEXTYPE_NUM 6
|
||||
#define JLEXTYPE_COMMA 7
|
||||
#define JLEXTYPE_CHAR 8
|
||||
#define JLEXTYPE_EOF 9
|
||||
|
||||
|
||||
static int get_ltype(char letter) {
|
||||
switch (letter) {
|
||||
case EOF:
|
||||
return JLEXTYPE_EOF;
|
||||
case '{':
|
||||
return JLEXTYPE_BLOCKB;
|
||||
case '}':
|
||||
return JLEXTYPE_BLOCKE;
|
||||
case '"':
|
||||
return JLEXTYPE_WORDL;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
return JLEXTYPE_SPACE;
|
||||
case ':':
|
||||
return JLEXTYPE_SEPAR;
|
||||
case ',':
|
||||
return JLEXTYPE_COMMA;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '0':
|
||||
case '.':
|
||||
case 'E':
|
||||
case 'e':
|
||||
case '+':
|
||||
case '-':
|
||||
return JLEXTYPE_NUM;
|
||||
default:
|
||||
return JLEXTYPE_CHAR;
|
||||
}
|
||||
return JLEXTYPE_UNDEF;
|
||||
}
|
||||
|
||||
void jlexer_init(jlexer_t * lexer, rcache_t * cache) {
|
||||
lexer->cache = cache;
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
lexer->tokpos = 0;
|
||||
lexer->letter = EOF;
|
||||
lexer->rewind = false;
|
||||
}
|
||||
|
||||
int jlexer_gettoken(jlexer_t * lexer, char* token) {
|
||||
|
||||
while (true) {
|
||||
if (!lexer->rewind) {
|
||||
lexer->letter = rcache_getc(lexer->cache);
|
||||
}
|
||||
lexer->rewind = false;
|
||||
int type = get_ltype(lexer->letter);
|
||||
|
||||
switch (lexer->context) {
|
||||
case JLEXCONT_END:{
|
||||
lexer->context = JLEXCONT_END;
|
||||
lexer->tokpos = 0;
|
||||
//lexer->rewind = true;
|
||||
strcpy(token, "EOF");
|
||||
return JLEXTOK_END;
|
||||
}
|
||||
case JLEXCONT_UNDEF:{
|
||||
switch (type) {
|
||||
case JLEXTYPE_EOF:{
|
||||
lexer->context = JLEXCONT_END;
|
||||
lexer->rewind = true;
|
||||
break;
|
||||
}
|
||||
case JLEXTYPE_BLOCKB:{
|
||||
strcpy(token, "BLOCK BEGIN");
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_BLOCKB;
|
||||
}
|
||||
case JLEXTYPE_BLOCKE:{
|
||||
strcpy(token, "BLOCK END");
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_BLOCKE;
|
||||
}
|
||||
case JLEXTYPE_SEPAR:{
|
||||
strcpy(token, "IS");
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_SEPAR;
|
||||
}
|
||||
case JLEXTYPE_COMMA:{
|
||||
strcpy(token, "NEXT");
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_NEXT;
|
||||
}
|
||||
case JLEXTYPE_WORDL:{
|
||||
lexer->tokpos = 0;
|
||||
//char* prefix = "STRING ";
|
||||
//strcpy(token, prefix);
|
||||
//lexer->tokpos =+ strlen(prefix);
|
||||
lexer->context = JLEXCONT_WORD;
|
||||
break;
|
||||
}
|
||||
case JLEXTYPE_NUM:{
|
||||
lexer->tokpos = 0;
|
||||
//char* prefix = "NUMBER ";
|
||||
//strcpy(token, prefix);
|
||||
//lexer->tokpos =+ strlen(prefix);
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = JLEXCONT_NUM;
|
||||
break;
|
||||
}
|
||||
case JLEXTYPE_CHAR:{
|
||||
lexer->tokpos = 0;
|
||||
char* prefix = "WTF? ";
|
||||
|
||||
strcpy(token, prefix);
|
||||
lexer->tokpos = +strlen(prefix);
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
lexer->context = JLEXCONT_UNKNOW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JLEXCONT_WORD:{
|
||||
int newcontext = lexer->context;
|
||||
|
||||
switch (type) {
|
||||
case JLEXTYPE_EOF:
|
||||
case JLEXTYPE_WORDL:{
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_WORD;
|
||||
}
|
||||
}
|
||||
lexer->context = newcontext;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case JLEXCONT_NUM:{
|
||||
int newcontext = lexer->context;
|
||||
|
||||
switch (type) {
|
||||
case JLEXTYPE_NUM:
|
||||
break;
|
||||
case JLEXTYPE_EOF:
|
||||
default:
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->rewind = true;
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_NUMB;
|
||||
}
|
||||
lexer->context = newcontext;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
case JLEXCONT_UNKNOW:{
|
||||
int newcontext = lexer->context;
|
||||
|
||||
switch (type) {
|
||||
case JLEXTYPE_CHAR:
|
||||
case JLEXTYPE_NUM:
|
||||
break;
|
||||
case JLEXTYPE_EOF:
|
||||
default:{
|
||||
token[lexer->tokpos++] = '\0';
|
||||
lexer->rewind = true;
|
||||
lexer->context = JLEXCONT_UNDEF;
|
||||
return JLEXTOK_UNKNOW;
|
||||
}
|
||||
}
|
||||
lexer->context = newcontext;
|
||||
token[lexer->tokpos++] = lexer->letter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(token, "UNDEF");
|
||||
return JLEXTOK_UNDEF;
|
||||
}
|
||||
|
||||
void jlexer_destroy(jlexer_t * lexer) {
|
||||
(void)lexer;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
#ifndef JLEXER_H_QWERTY
|
||||
#define JLEXER_H_QWERTY
|
||||
|
||||
#include <rcache.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
rcache_t* cache;
|
||||
int fd;
|
||||
int context;
|
||||
char letter;
|
||||
int tokpos;
|
||||
bool rewind;
|
||||
} jlexer_t;
|
||||
|
||||
|
||||
|
||||
#define JLEXTOK_BLOCKB 1
|
||||
#define JLEXTOK_BLOCKE 2
|
||||
#define JLEXTOK_SPACE 4
|
||||
#define JLEXTOK_SEPAR 3
|
||||
#define JLEXTOK_UNDEF 4
|
||||
#define JLEXTOK_WORD 5
|
||||
#define JLEXTOK_NUMB 6
|
||||
#define JLEXTOK_UNKNOW 7
|
||||
#define JLEXTOK_NEXT 8
|
||||
#define JLEXTOK_END 9
|
||||
|
||||
|
||||
|
||||
void jlexer_init(jlexer_t * lexer, rcache_t * cache);
|
||||
int jlexer_gettoken(jlexer_t * lexer, char* token);
|
||||
void jlexer_destroy(jlexer_t * lexer);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <massert.h>
|
||||
#include <rcache.h>
|
||||
#include <jlexer.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
int fd = open("test.json", O_RDONLY);
|
||||
|
||||
MASSERT(fd > 0);
|
||||
|
||||
rcache_t cache;
|
||||
|
||||
rcache_init(&cache, fd);
|
||||
|
||||
jlexer_t lexer;
|
||||
|
||||
jlexer_init(&lexer, &cache);
|
||||
|
||||
char token[1024];
|
||||
int type = 0;
|
||||
|
||||
while ((type = jlexer_gettoken(&lexer, token)) != JLEXTOK_END) {
|
||||
printf("%d: %s\n", type, token);
|
||||
}
|
||||
printf("%d: %s\n", type, token);
|
||||
|
||||
rcache_destroy(&cache);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <logger.h>
|
||||
#include <jparser.h>
|
||||
|
||||
#define INIT_BSIZE 64
|
||||
|
||||
|
||||
static char* strcopy(char* src) {
|
||||
size_t srcsize = strlen(src) + 1;
|
||||
char* dst = malloc(srcsize);
|
||||
|
||||
memset(dst, '\0', srcsize);
|
||||
strcpy(dst, src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void jparser_init(jparser_t * parser, jlexer_t * lexer) {
|
||||
parser->lexer = lexer;
|
||||
parser->kvalarr = malloc(sizeof(jkval_t) * INIT_BSIZE);
|
||||
parser->kvalcapa = INIT_BSIZE;
|
||||
parser->kvalsize = 0;
|
||||
}
|
||||
|
||||
#define MAX_TOKEN_SIZE 1024
|
||||
|
||||
int jparser_parse(jparser_t * parser) {
|
||||
jlexer_t* lex = parser->lexer;
|
||||
char token[MAX_TOKEN_SIZE];
|
||||
int type = 0;
|
||||
|
||||
int pos = 0;
|
||||
char* key = "";
|
||||
|
||||
while ((type = jlexer_gettoken(lex, token)) != JLEXTOK_END) {
|
||||
//printf("pos %d %d: %s\n", pos, type, token);
|
||||
switch (pos) {
|
||||
// POS 0
|
||||
case 0:{
|
||||
if (type == JLEXTOK_END) {
|
||||
log_error("End token received in position %d", pos);
|
||||
return -1;
|
||||
}
|
||||
if (type != JLEXTOK_BLOCKB) {
|
||||
log_error("Wrong block token: %s", token);
|
||||
return -1;
|
||||
}
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
// POS 1
|
||||
case 1:{
|
||||
if (type == JLEXTOK_END) {
|
||||
log_error("End token received in position %d", pos);
|
||||
//return -1;
|
||||
}
|
||||
if (type == JLEXTOK_SPACE)
|
||||
continue;
|
||||
if (type == JLEXTOK_NEXT)
|
||||
continue;
|
||||
if (type == JLEXTOK_BLOCKE)
|
||||
return 0;
|
||||
if (type != JLEXTOK_WORD) {
|
||||
log_error("Wrong word token: %s", token);
|
||||
return -1;
|
||||
}
|
||||
key = strcopy(token);
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
// POS 2
|
||||
case 2:{
|
||||
if (type == JLEXTOK_END) {
|
||||
log_error("End token received in position %d", pos);
|
||||
return -1;
|
||||
}
|
||||
if (type == JLEXTOK_SPACE)
|
||||
continue;
|
||||
if (type != JLEXTOK_SEPAR) {
|
||||
log_error("Wrong delimeter token: %s", token);
|
||||
return -1;
|
||||
}
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
// POS 3
|
||||
case 3:{
|
||||
if (type == JLEXTOK_END) {
|
||||
log_error("End token received in position %d", pos);
|
||||
return -1;
|
||||
}
|
||||
if (type == JLEXTOK_SPACE)
|
||||
continue;
|
||||
if (type == JLEXTOK_BLOCKB) {
|
||||
pos = 1;
|
||||
continue;
|
||||
}
|
||||
if (type != JLEXTOK_WORD && type != JLEXTOK_NUMB) {
|
||||
log_error("Wrong value token: %s", token);
|
||||
return -1;
|
||||
}
|
||||
char* val = strcopy(token);
|
||||
|
||||
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
|
||||
|
||||
kv->key = key;
|
||||
if (type == JLEXTOK_NUMB) {
|
||||
kv->type = JVALTYPE_NUM;
|
||||
char* eptr = NULL;
|
||||
kv->num = (int64_t)strtol(val, &eptr, 10);;
|
||||
free(val);
|
||||
} else {
|
||||
kv->type = JVALTYPE_STR;
|
||||
kv->str = val;
|
||||
}
|
||||
free(key);
|
||||
parser->kvalsize++;
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
// POS 4
|
||||
case 4:{
|
||||
if (type == JLEXTOK_END) {
|
||||
log_error("End token received in position %d", pos);
|
||||
return -1;
|
||||
}
|
||||
if (type == JLEXTOK_SPACE) {
|
||||
continue;
|
||||
} else if (type == JLEXTOK_BLOCKE) {
|
||||
//log_debug("Block ended: %s", token);
|
||||
return 0;
|
||||
} else if (type != JLEXTOK_NEXT && type != JLEXTOK_BLOCKE) {
|
||||
log_error("Wrong next token: %s", token);
|
||||
return -1;
|
||||
}
|
||||
pos = 1;
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
log_error("Wrong parser stage: %s", token);
|
||||
if (type == JLEXTOK_END) {
|
||||
log_error("End token received in position %d", pos);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jparser_bind(jparser_t* parser, int type, char* key, void* ref) {
|
||||
for (int i = 0; i < parser->kvalsize; i++) {
|
||||
jkval_t* kv = &(parser->kvalarr[i]);
|
||||
|
||||
if (strcmp(kv->key, key) == 0) {
|
||||
if (kv->type == JVALTYPE_STR) {
|
||||
*(char**)(ref) = strcopy(kv->str);
|
||||
} else if (kv->type == JVALTYPE_NUM) {
|
||||
*(int*)(ref) = kv->num;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void jparser_destroy(jparser_t * parser) {
|
||||
for (int i = 0; i < parser->kvalsize; i++) {
|
||||
if (parser->kvalarr[i].type == JVALTYPE_STR) {
|
||||
free(parser->kvalarr[i].str);
|
||||
}
|
||||
}
|
||||
free(parser->kvalarr);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
#ifndef JPARSER_H_QWERTY
|
||||
#define JPARSER_H_QWERTY
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <jlexer.h>
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
char* key;
|
||||
union {
|
||||
char* str;
|
||||
int64_t num;
|
||||
bool flag;
|
||||
};
|
||||
} jkval_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
jkval_t* kvalarr;
|
||||
int kvalcapa;
|
||||
int kvalsize;
|
||||
jlexer_t* lexer;
|
||||
} jparser_t;
|
||||
|
||||
#define JVALTYPE_STR 1
|
||||
#define JVALTYPE_NUM 2
|
||||
#define JVALTYPE_BOOL 3
|
||||
|
||||
|
||||
void jparser_init(jparser_t* parser, jlexer_t* lexer);
|
||||
int jparser_bind(jparser_t* parser, int type, char* key, void* ref);
|
||||
int jparser_parse(jparser_t* parser);
|
||||
void jparser_destroy(jparser_t * parser);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <massert.h>
|
||||
#include <jlexer.h>
|
||||
#include <jparser.h>
|
||||
#include <logger.h>
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
int fd = open("test.json", O_RDONLY);
|
||||
|
||||
MASSERT(fd > 0);
|
||||
|
||||
|
||||
|
||||
rcache_t cache;
|
||||
jlexer_t lexer;
|
||||
jparser_t parser;
|
||||
|
||||
rcache_init(&cache, fd);
|
||||
jlexer_init(&lexer, &cache);
|
||||
jparser_init(&parser, &lexer);
|
||||
|
||||
if (jparser_parse(&parser) < 0) {
|
||||
log_error("cannot parse json\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int64_t id = 0;
|
||||
|
||||
if (jparser_bind(&parser, JVALTYPE_NUM, "id", (void *)&id) < 0) {
|
||||
log_error("cannot bind variable\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char* name = "";
|
||||
|
||||
if (jparser_bind(&parser, JVALTYPE_STR, "name", (void *)&name) < 0) {
|
||||
log_error("cannot bind variable\n");
|
||||
}
|
||||
|
||||
printf("id = %ld\n", id);
|
||||
printf("name = %s\n", name);
|
||||
|
||||
jparser_destroy(&parser);
|
||||
jlexer_destroy(&lexer);
|
||||
rcache_destroy(&cache);
|
||||
free(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#define CLOCK_SOURCE CLOCK_MONOTONIC
|
||||
#define MAX_TS_LEN 256
|
||||
|
||||
|
||||
static pthread_mutex_t logmutex = NULL;
|
||||
static pthread_mutexattr_t logmutex_attrs;
|
||||
|
||||
void log_init(void) {
|
||||
pthread_mutexattr_init(&logmutex_attrs);
|
||||
pthread_mutexattr_setpshared(&logmutex_attrs, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&logmutex, &logmutex_attrs);
|
||||
}
|
||||
|
||||
void log_destroy(void) {
|
||||
pthread_mutex_destroy(&logmutex);
|
||||
pthread_mutexattr_destroy(&logmutex_attrs);
|
||||
}
|
||||
|
||||
void static set_timestamp(char* buffer) {
|
||||
time_t now = time(NULL);
|
||||
if (now < 0) {
|
||||
return;
|
||||
}
|
||||
struct tm* ptm = localtime(&now);
|
||||
if (ptm == NULL) {
|
||||
return;
|
||||
}
|
||||
struct timespec tv;
|
||||
|
||||
clock_gettime(CLOCK_SOURCE, &tv);
|
||||
memset(buffer, '\0', MAX_TS_LEN);
|
||||
sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d.%ld+%s",
|
||||
ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour,
|
||||
ptm->tm_min, ptm->tm_sec, tv.tv_nsec, ptm->tm_zone);
|
||||
}
|
||||
|
||||
void log_error(const char* format, ...) {
|
||||
|
||||
char timestamp[MAX_TS_LEN];
|
||||
set_timestamp(timestamp);
|
||||
|
||||
pthread_mutex_lock(&logmutex);
|
||||
va_list args;
|
||||
fprintf(stderr, "%s error: ", timestamp);
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
pthread_mutex_unlock(&logmutex);
|
||||
}
|
||||
|
||||
void log_warning(const char* format, ...) {
|
||||
|
||||
char timestamp[MAX_TS_LEN];
|
||||
set_timestamp(timestamp);
|
||||
|
||||
pthread_mutex_lock(&logmutex);
|
||||
va_list args;
|
||||
fprintf(stderr, "%s warning: ", timestamp);
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
pthread_mutex_unlock(&logmutex);
|
||||
}
|
||||
|
||||
|
||||
void log_debug(const char* format, ...) {
|
||||
|
||||
char timestamp[MAX_TS_LEN];
|
||||
set_timestamp(timestamp);
|
||||
|
||||
pthread_mutex_lock(&logmutex);
|
||||
va_list args;
|
||||
fprintf(stderr, "%s debug: ", timestamp);
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
pthread_mutex_unlock(&logmutex);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef LOGGER_H_QWERTY
|
||||
#define LOGGER_H_QWERTY
|
||||
|
||||
void log_init(void);
|
||||
void log_destroy(void);
|
||||
|
||||
void log_error(const char* format, ... );
|
||||
void log_debug(const char* format, ... );
|
||||
void log_warning(const char* format, ... );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <massert.h>
|
||||
|
||||
void x__assert(char* path, int line, const char* func) {
|
||||
printf("%s:%d: assert error in %s\n", path, line, func);
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MASSERT_H_QWERTY
|
||||
#define MASSERT_H_QWERTY
|
||||
|
||||
#define massert(expr) if (!(expr)) \
|
||||
{ x__assert(__FILE__, __LINE__, (const char*)__func__); }
|
||||
|
||||
#define MASSERT(expr) if (!(expr)) \
|
||||
{ x__assert(__FILE__, __LINE__, (const char*)__func__); }
|
||||
|
||||
void x__assert(char* path, int line, const char* func);
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <rcache.h>
|
||||
|
||||
|
||||
#define CACHE_INITCAPA 512
|
||||
|
||||
rcache_t* rcache_init(rcache_t * cache, int fd) {
|
||||
cache->data = malloc(CACHE_INITCAPA);
|
||||
if (cache->data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cache->wpos = 0;
|
||||
cache->rpos = 0;
|
||||
cache->capa = CACHE_INITCAPA;
|
||||
cache->fd = fd;
|
||||
return cache;
|
||||
}
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
char rcache_getc(rcache_t * cache) {
|
||||
size_t unread = cache->wpos - cache->rpos;
|
||||
|
||||
if (unread == 0) {
|
||||
char* buffer[BUFFER_SIZE];
|
||||
ssize_t rsize = read(cache->fd, buffer, sizeof(buffer));
|
||||
if (rsize < 0) {
|
||||
return EOF;
|
||||
}
|
||||
if (rsize == 0) {
|
||||
return EOF;
|
||||
}
|
||||
if ((cache->wpos + rsize) > cache->capa) {
|
||||
size_t newcapa = cache->capa * 2 + rsize;
|
||||
uint8_t* newdata = realloc(cache->data, (size_t)newcapa);
|
||||
|
||||
if (newdata == NULL) {
|
||||
return (ssize_t) - 1;
|
||||
}
|
||||
cache->data = newdata;
|
||||
cache->capa = newcapa;
|
||||
}
|
||||
memcpy(&(cache->data[cache->wpos]), buffer, (size_t)rsize);
|
||||
cache->wpos += rsize;
|
||||
}
|
||||
//printf("[%c]", (char)cache->data[cache->rpos]);
|
||||
return (char)cache->data[cache->rpos++];
|
||||
}
|
||||
|
||||
|
||||
void rcache_destroy(rcache_t * cache) {
|
||||
if (cache != NULL) {
|
||||
free(cache->data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RCACHE_H_QWERTY
|
||||
#define RCACHE_H_QWERTY
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct {
|
||||
size_t rpos;
|
||||
size_t wpos;
|
||||
size_t capa;
|
||||
uint8_t* data;
|
||||
int fd;
|
||||
} rcache_t;
|
||||
|
||||
|
||||
rcache_t* rcache_init(rcache_t* cache, int fd);
|
||||
char rcache_getc(rcache_t* cache);
|
||||
void rcache_destroy(rcache_t* cache);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <rcache.h>
|
||||
#include <massert.h>
|
||||
|
||||
|
||||
void test_getnc(void) {
|
||||
|
||||
int fd = open("test.json", O_RDONLY);
|
||||
|
||||
MASSERT(fd > 0);
|
||||
|
||||
rcache_t stream;
|
||||
|
||||
rcache_init(&stream, fd);
|
||||
|
||||
char c = rcache_getc(&stream);
|
||||
|
||||
printf("%c\n", c);
|
||||
printf("%s", (char *)stream.data);
|
||||
|
||||
rcache_destroy(&stream);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
test_getnc();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
"id" = -123
|
||||
debug = true
|
||||
name = "qwerty\"567"
|
||||
foo = bar # bbbb
|
||||
"aaa
|
||||
# aaaa
|
||||
@@ -0,0 +1,3 @@
|
||||
qwerty
|
||||
qwerty
|
||||
qwerty
|
||||
@@ -0,0 +1 @@
|
||||
{"id":-123, "name" : "qwerty"}
|
||||
Reference in New Issue
Block a user