mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
Remove Miller-5 source/doc/manpage directories, along with C-build files (#731)
This commit is contained in:
parent
9eefc56487
commit
7578b789f6
1354 changed files with 2995 additions and 488407 deletions
89
.gitignore
vendored
89
.gitignore
vendored
|
|
@ -1,40 +1,4 @@
|
|||
autom4te.cache
|
||||
c/mlr
|
||||
go/mlr
|
||||
mlrd
|
||||
mlrg
|
||||
mlrp
|
||||
test-argparse
|
||||
test-byte-readers
|
||||
test-line-readers
|
||||
test-dsl-stack
|
||||
test-join-bucket-keeper
|
||||
test-json-parser
|
||||
test-lrec
|
||||
test-rval-evaluators
|
||||
test-mlhmmv
|
||||
test-mlrregex
|
||||
test-mlrutil
|
||||
test-multiple-containers
|
||||
test-parse-trie
|
||||
test-peek-file-reader
|
||||
test-string-builder
|
||||
test_rval_evaluators
|
||||
test_argparse
|
||||
test_byte_readers
|
||||
test_line_readers
|
||||
test_join_bucket_keeper
|
||||
test_json_parser
|
||||
test_lrec
|
||||
test_mlhmmv
|
||||
test_mlrregex
|
||||
test_mlrutil
|
||||
test_multiple_containers
|
||||
test_parse_trie
|
||||
test_peek_file_reader
|
||||
test_string_builder
|
||||
output-regtest
|
||||
termcvt
|
||||
a.out
|
||||
*.dSYM
|
||||
catc
|
||||
|
|
@ -45,74 +9,23 @@ gmon.out
|
|||
*.pyc
|
||||
.sw?
|
||||
.*.sw?
|
||||
c/parsing/lemon
|
||||
c/parsing/mlr_dsl_lexer.c
|
||||
c/parsing/mlr_dsl_lexer.h
|
||||
c/parsing/mlr_dsl_parse.c
|
||||
c/parsing/mlr_dsl_parse.h
|
||||
c/parsing/mlr_dsl_parse.out
|
||||
c/reg_test/output
|
||||
c/output/out
|
||||
tags
|
||||
*.la
|
||||
*.lo
|
||||
*.log
|
||||
*.trs
|
||||
*~
|
||||
.deps/
|
||||
.libs/
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
libtool
|
||||
stamp-h1
|
||||
ap
|
||||
getl
|
||||
lemon_prepared
|
||||
lrim
|
||||
mlr-[0-9.]*.tar.*
|
||||
c/jkopush
|
||||
c/run_mlr
|
||||
c/mlr_expect_fail
|
||||
c/run_mlr_for_auxents
|
||||
c/push2
|
||||
push2
|
||||
data/.gitignore
|
||||
|
||||
docs/_build
|
||||
docs6/_build
|
||||
|
||||
c/mlr.static
|
||||
miller-*.src.rpm
|
||||
mlr.exe
|
||||
mlr.linux.x86_64
|
||||
mlr.macosx
|
||||
msys-2.0.dll
|
||||
|
||||
data/big.*
|
||||
data/nmc?.*
|
||||
|
||||
/Makefile
|
||||
c/Makefile
|
||||
c/auxents/Makefile
|
||||
c/cli/Makefile
|
||||
c/containers/Makefile
|
||||
c/dsl/Makefile
|
||||
c/experimental/Makefile
|
||||
c/input/Makefile
|
||||
c/lib/Makefile
|
||||
c/mapping/Makefile
|
||||
c/output/Makefile
|
||||
c/parsing/Makefile
|
||||
c/reg_test/Makefile
|
||||
c/reg_test/expected/Makefile
|
||||
c/reg_test/input/Makefile
|
||||
c/reg_test/input/comments/Makefile
|
||||
c/reg_test/input/rfc-csv/Makefile
|
||||
c/stream/Makefile
|
||||
c/unit_test/Makefile
|
||||
man/Makefile
|
||||
|
||||
experiments/dsl-parser/one/src
|
||||
experiments/dsl-parser/one/main
|
||||
experiments/dsl-parser/two/src
|
||||
|
|
@ -120,4 +33,4 @@ experiments/dsl-parser/two/main
|
|||
experiments/cli-parser/cliparse
|
||||
experiments/cli-parser/cliparse.exe
|
||||
|
||||
docs6/site/
|
||||
docs/site/
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
# not GPL, thus no COPYING file
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
|
||||
EXTRA_DIST= LICENSE.txt README.md
|
||||
|
||||
SUBDIRS=c man
|
||||
823
Makefile.in
823
Makefile.in
|
|
@ -1,823 +0,0 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 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@
|
||||
subdir = .
|
||||
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 $(top_srcdir)/configure \
|
||||
$(am__configure_deps) $(am__DIST_COMMON)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
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 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||
install-data-recursive install-dvi-recursive \
|
||||
install-exec-recursive install-html-recursive \
|
||||
install-info-recursive install-pdf-recursive \
|
||||
install-ps-recursive install-recursive installcheck-recursive \
|
||||
installdirs-recursive pdf-recursive ps-recursive \
|
||||
tags-recursive uninstall-recursive
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
am__recursive_targets = \
|
||||
$(RECURSIVE_TARGETS) \
|
||||
$(RECURSIVE_CLEAN_TARGETS) \
|
||||
$(am__extra_recursive_targets)
|
||||
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||
cscope distdir dist dist-all distcheck
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
|
||||
$(LISP)config.h.in
|
||||
# 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
|
||||
CSCOPE = cscope
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/autotools/ar-lib $(top_srcdir)/autotools/compile \
|
||||
$(top_srcdir)/autotools/config.guess \
|
||||
$(top_srcdir)/autotools/config.sub \
|
||||
$(top_srcdir)/autotools/install-sh \
|
||||
$(top_srcdir)/autotools/ltmain.sh \
|
||||
$(top_srcdir)/autotools/missing autotools/ar-lib \
|
||||
autotools/compile autotools/config.guess autotools/config.sub \
|
||||
autotools/install-sh autotools/ltmain.sh autotools/missing
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
am__remove_distdir = \
|
||||
if test -d "$(distdir)"; then \
|
||||
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
&& rm -rf "$(distdir)" \
|
||||
|| { sleep 5 && rm -rf "$(distdir)"; }; \
|
||||
else :; fi
|
||||
am__post_remove_distdir = $(am__remove_distdir)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
DIST_ARCHIVES = $(distdir).tar.gz
|
||||
GZIP_ENV = --best
|
||||
DIST_TARGETS = dist-gzip
|
||||
distuninstallcheck_listfiles = find . -type f -print
|
||||
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
||||
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
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@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
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@
|
||||
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@
|
||||
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@
|
||||
|
||||
# not GPL, thus no COPYING file
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
EXTRA_DIST = LICENSE.txt README.md
|
||||
SUBDIRS = c man
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
am--refresh: Makefile
|
||||
@:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
|
||||
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
config.h: stamp-h1
|
||||
@test -f $@ || rm -f stamp-h1
|
||||
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
|
||||
|
||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||
$(srcdir)/config.h.in: $(am__configure_deps)
|
||||
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool config.lt
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run 'make' without going through this Makefile.
|
||||
# To change the values of 'make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in 'config.status', edit 'config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run 'make');
|
||||
# (2) otherwise, pass the desired values on the 'make' command line.
|
||||
$(am__recursive_targets):
|
||||
@fail=; \
|
||||
if $(am__make_keepgoing); then \
|
||||
failcom='fail=yes'; \
|
||||
else \
|
||||
failcom='exit 1'; \
|
||||
fi; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-recursive
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
$(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-recursive
|
||||
|
||||
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"
|
||||
cscope: cscope.files
|
||||
test ! -s cscope.files \
|
||||
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
|
||||
clean-cscope:
|
||||
-rm -f cscope.files
|
||||
cscope.files: clean-cscope cscopelist
|
||||
cscopelist: cscopelist-recursive
|
||||
|
||||
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
|
||||
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||
@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
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
$(am__make_dryrun) \
|
||||
|| test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
-test -n "$(am__skip_mode_fix)" \
|
||||
|| find "$(distdir)" -type d ! -perm -755 \
|
||||
-exec chmod u+rwx,go+rx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r "$(distdir)"
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-bzip2: distdir
|
||||
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-lzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-xz: distdir
|
||||
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
@echo WARNING: "Support for distribution archives compressed with" \
|
||||
"legacy program 'compress' is deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-shar: distdir
|
||||
@echo WARNING: "Support for shar distribution archives is" \
|
||||
"deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist dist-all:
|
||||
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lz*) \
|
||||
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
|
||||
*.tar.xz*) \
|
||||
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir)
|
||||
chmod u+w $(distdir)
|
||||
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
|
||||
chmod a-w $(distdir)
|
||||
test -d $(distdir)/_build || exit 0; \
|
||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||
&& am__cwd=`pwd` \
|
||||
&& $(am__cd) $(distdir)/_build/sub \
|
||||
&& ../../configure \
|
||||
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
|
||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||
--srcdir=../.. --prefix="$$dc_install_base" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||
distuninstallcheck \
|
||||
&& chmod -R a-w "$$dc_install_base" \
|
||||
&& ({ \
|
||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||
&& rm -rf "$$dc_destdir" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||
&& rm -rf $(DIST_ARCHIVES) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||
&& cd "$$am__cwd" \
|
||||
|| exit 1
|
||||
$(am__post_remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@test -n '$(distuninstallcheck_dir)' || { \
|
||||
echo 'ERROR: trying to run $@ with an empty' \
|
||||
'$$(distuninstallcheck_dir)' >&2; \
|
||||
exit 1; \
|
||||
}; \
|
||||
$(am__cd) '$(distuninstallcheck_dir)' || { \
|
||||
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
|
||||
exit 1; \
|
||||
}; \
|
||||
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left after uninstall:" ; \
|
||||
if test -n "$(DESTDIR)"; then \
|
||||
echo " (check DESTDIR support)"; \
|
||||
fi ; \
|
||||
$(distuninstallcheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
distcleancheck: distclean
|
||||
@if test '$(srcdir)' = . ; then \
|
||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||
$(distcleancheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
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-recursive
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-hdr \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(am__recursive_targets) all install-am install-strip
|
||||
|
||||
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
|
||||
am--refresh check check-am clean clean-cscope clean-generic \
|
||||
clean-libtool cscope cscopelist-am ctags ctags-am dist \
|
||||
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
|
||||
dist-xz dist-zip distcheck distclean distclean-generic \
|
||||
distclean-hdr distclean-libtool distclean-tags distcleancheck \
|
||||
distdir distuninstallcheck 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-info install-info-am \
|
||||
install-man install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs installdirs-am maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# 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:
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# ================================================================
|
||||
# NOTE: This makefile is not intended to be used in a packaging system --
|
||||
# rather, Miller uses autconfig for that. This makefile is intended for users
|
||||
# who prefer (for whatever reason) to bypass autoconfig. Please also see
|
||||
# http://johnkerl.org/miller/doc/build.html#Without_using_autoconfig
|
||||
# ================================================================
|
||||
|
||||
MANDIR ?= /usr/share/man
|
||||
DESTDIR ?=
|
||||
|
||||
all: c manpage
|
||||
devall: c install docs
|
||||
# TODO: the install target exists to put most-recent mlr executable in the
|
||||
# path to be picked up by the mlr-execs in the docs dir. better would be to
|
||||
# export PATH here with ./c at its head.
|
||||
c: .always
|
||||
make -C c -f Makefile.no-autoconfig top
|
||||
docs: .always
|
||||
cd docs && make html
|
||||
install: .always
|
||||
make -C c -f Makefile.no-autoconfig install
|
||||
install -d -m 0755 $(DESTDIR)/$(MANDIR)
|
||||
install -m 0644 docs/miller.1 $(DESTDIR)/$(MANDIR)
|
||||
clean: .always
|
||||
make -C c -f Makefile.no-autoconfig clean
|
||||
.PHONY: manpage
|
||||
# OSX:
|
||||
# * brew install asciidoc
|
||||
# * export XML_CATALOG_FILES=/usr/local/etc/xml/catalog
|
||||
manpage: .always
|
||||
make -C man manpage
|
||||
.always:
|
||||
@true
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# Status as of May 2021
|
||||
|
||||
## Go port
|
||||
|
||||
GitHub actions are fine for Linux/MacOS/Windows at https://github.com/johnkerl/miller/actions.
|
||||
|
||||
## C implementation
|
||||
|
||||
### Travis CI for non-Windows
|
||||
|
||||
* Travis was in place for years now
|
||||
* As of May 2021 `travis-ci.org` is moving to `travis-ci.com`
|
||||
* I am getting 404s in the Webhook setup on the GitHub side but builds are trigger on the Travis side which is baffling
|
||||
* This is chewing through credits at a furious rate regardless
|
||||
* Also, almost all commits these days are on the Go code so trigger a build of the C code on each commit is not a good use of resources
|
||||
* In summary: Travis CI is not currently working, and isn't worth fixing
|
||||
|
||||
### GitHub actions for non-Windows
|
||||
|
||||
* Incompatible with `autoconf` as described at https://www.preining.info/blog/2018/12/git-and-autotools-a-hate-relation/
|
||||
* In summary `autoconf` does not work with GitHub Actions, and this does not appear to be a forward path
|
||||
|
||||
### Conclusion for non-Windows
|
||||
|
||||
* For those rare commits which do involve C code -- until the Go port is complete -- I'll runs C makes manually.
|
||||
* For releases, I'll run them manually -- which is the current process [as defined here](https://miller.readthedocs.io/en/latest/build.html#creating-a-new-release-for-developers).
|
||||
|
||||
### Windows builds
|
||||
|
||||
This used:
|
||||
|
||||
* [appveyor.yml](appveyor.yml)
|
||||
* https://ci.appveyor.com/project/johnkerl/miller
|
||||
* https://github.com/johnkerl/miller/settings/hooks
|
||||
|
||||
Unfortunately, I understand next to nothing about what I'm doing here -- whenever the AppVeyor build breaks (and the Travis build doesn't) I end up googling for various things in the https://ci.appveyor.com/project/johnkerl/miller build-log output, then iteratively updating `appveyor.yml` until I can get a build again.
|
||||
|
||||
As of May 2021 I've disabled Appveyor builds. Moving forward, for the C implementation I'll build Windows executables on a personal laptop and upload `mlr.exe` when I cut a release.
|
||||
1235
aclocal.m4
vendored
1235
aclocal.m4
vendored
File diff suppressed because it is too large
Load diff
34
appveyor.yml
34
appveyor.yml
|
|
@ -1,34 +0,0 @@
|
|||
# No longer used -- see README-autobuild.md
|
||||
install:
|
||||
- set PATH=C:\msys64\usr\bin;%PATH%
|
||||
- bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
||||
- bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
||||
- bash -lc "pacman-key --init"
|
||||
- bash -lc "pacman-key --populate msys2"
|
||||
- bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
||||
- bash -lc "pacman --ask 20 -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
||||
- ps: Get-Process | Where-Object {$_.path -like 'C:\msys64*'} | Stop-Process
|
||||
- bash -lc "pacman --needed --ask 20 -Syu"
|
||||
- bash -lc "pacman --needed --ask 20 -Sy"
|
||||
- bash -lc "pacman --noconfirm -S base-devel"
|
||||
- bash -lc "pacman --noconfirm -S msys2-devel"
|
||||
- bash -lc "pacman --noconfirm -S mingw-w64-x86_64-toolchain"
|
||||
- bash -lc "pacman --noconfirm -S mingw-w64-x86_64-pcre"
|
||||
- bash -lc "pacman --noconfirm -S msys2-runtime"
|
||||
- bash -lc "pacman --noconfirm -S isl"
|
||||
|
||||
build_script:
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; pwd"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; ls -l"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; which gcc"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; gcc --version"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; pacman -Q"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; cat msys2-build.sh"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; bash -x msys2-build.sh || (cat config.log && exit 1)"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER; cp /usr/bin/msys-2.0.dll ."
|
||||
|
||||
artifacts:
|
||||
- path: ./c/mlr.exe
|
||||
name: Miller executable
|
||||
- path: ./msys-2.0.dll
|
||||
name: MSYS2 DLL
|
||||
270
autotools/ar-lib
270
autotools/ar-lib
|
|
@ -1,270 +0,0 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for Microsoft lib.exe
|
||||
|
||||
me=ar-lib
|
||||
scriptversion=2012-03-01.08; # UTC
|
||||
|
||||
# Copyright (C) 2010-2017 Free Software Foundation, Inc.
|
||||
# Written by Peter Rosin <peda@lysator.liu.se>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
|
||||
# func_error message
|
||||
func_error ()
|
||||
{
|
||||
echo "$me: $1" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv in
|
||||
mingw)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_at_file at_file operation archive
|
||||
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
|
||||
# for each of them.
|
||||
# When interpreting the content of the @FILE, do NOT use func_file_conv,
|
||||
# since the user would need to supply preconverted file names to
|
||||
# binutils ar, at least for MinGW.
|
||||
func_at_file ()
|
||||
{
|
||||
operation=$2
|
||||
archive=$3
|
||||
at_file_contents=`cat "$1"`
|
||||
eval set x "$at_file_contents"
|
||||
shift
|
||||
|
||||
for member
|
||||
do
|
||||
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
|
||||
done
|
||||
}
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
func_error "no command. Try '$0 --help' for more information."
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<EOF
|
||||
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
|
||||
|
||||
Members may be specified in a file named with @FILE.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "$me, version $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test $# -lt 3; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
|
||||
AR=$1
|
||||
shift
|
||||
while :
|
||||
do
|
||||
if test $# -lt 2; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
case $1 in
|
||||
-lib | -LIB \
|
||||
| -ltcg | -LTCG \
|
||||
| -machine* | -MACHINE* \
|
||||
| -subsystem* | -SUBSYSTEM* \
|
||||
| -verbose | -VERBOSE \
|
||||
| -wx* | -WX* )
|
||||
AR="$AR $1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
action=$1
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
orig_archive=$1
|
||||
shift
|
||||
func_file_conv "$orig_archive"
|
||||
archive=$file
|
||||
|
||||
# strip leading dash in $action
|
||||
action=${action#-}
|
||||
|
||||
delete=
|
||||
extract=
|
||||
list=
|
||||
quick=
|
||||
replace=
|
||||
index=
|
||||
create=
|
||||
|
||||
while test -n "$action"
|
||||
do
|
||||
case $action in
|
||||
d*) delete=yes ;;
|
||||
x*) extract=yes ;;
|
||||
t*) list=yes ;;
|
||||
q*) quick=yes ;;
|
||||
r*) replace=yes ;;
|
||||
s*) index=yes ;;
|
||||
S*) ;; # the index is always updated implicitly
|
||||
c*) create=yes ;;
|
||||
u*) ;; # TODO: don't ignore the update modifier
|
||||
v*) ;; # TODO: don't ignore the verbose modifier
|
||||
*)
|
||||
func_error "unknown action specified"
|
||||
;;
|
||||
esac
|
||||
action=${action#?}
|
||||
done
|
||||
|
||||
case $delete$extract$list$quick$replace,$index in
|
||||
yes,* | ,yes)
|
||||
;;
|
||||
yesyes*)
|
||||
func_error "more than one action specified"
|
||||
;;
|
||||
*)
|
||||
func_error "no action specified"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -n "$delete"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -REMOVE "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
elif test -n "$extract"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
if test $# -gt 0; then
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -EXTRACT "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
|
||||
do
|
||||
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
|
||||
done
|
||||
fi
|
||||
|
||||
elif test -n "$quick$replace"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
if test -z "$create"; then
|
||||
echo "$me: creating $orig_archive"
|
||||
fi
|
||||
orig_archive=
|
||||
else
|
||||
orig_archive=$archive
|
||||
fi
|
||||
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_file_conv "${1#@}"
|
||||
set x "$@" "@$file"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
set x "$@" "$file"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
shift
|
||||
done
|
||||
|
||||
if test -n "$orig_archive"; then
|
||||
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
|
||||
else
|
||||
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
|
||||
fi
|
||||
|
||||
elif test -n "$list"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
$AR -NOLOGO -LIST "$archive" || exit $?
|
||||
fi
|
||||
|
|
@ -1,347 +0,0 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
1480
autotools/config.guess
vendored
1480
autotools/config.guess
vendored
File diff suppressed because it is too large
Load diff
1801
autotools/config.sub
vendored
1801
autotools/config.sub
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,791 +0,0 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2016-01-11.22; # UTC
|
||||
|
||||
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
|
@ -1,508 +0,0 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2014-09-12.12; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
tab=' '
|
||||
nl='
|
||||
'
|
||||
IFS=" $tab$nl"
|
||||
|
||||
# Set DOITPROG to "echo" to test this script.
|
||||
|
||||
doit=${DOITPROG-}
|
||||
doit_exec=${doit:-exec}
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
is_target_a_directory=possibly
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t)
|
||||
is_target_a_directory=always
|
||||
dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) is_target_a_directory=never;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# We allow the use of options -d and -T together, by making -d
|
||||
# take the precedence; this is for compatibility with GNU install.
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
echo "$0: target directory not allowed when installing a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||
if test ! -d "$dst_arg"; then
|
||||
echo "$0: $dst_arg: Is not a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
# $RANDOM is not portable (e.g. dash); use it when possible to
|
||||
# lower collision chance
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
# As "mkdir -p" follows symlinks and we work in /tmp possibly; so
|
||||
# create the $tmpdir first (and fail if unsuccessful) to make sure
|
||||
# that nobody tries to guess the $tmpdir name.
|
||||
if (umask $mkdir_umask &&
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
set +f &&
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
11156
autotools/ltmain.sh
11156
autotools/ltmain.sh
File diff suppressed because it is too large
Load diff
|
|
@ -1,215 +0,0 @@
|
|||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2013-10-28.13; # UTC
|
||||
|
||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal autoconf autoheader autom4te automake makeinfo
|
||||
bison yacc flex lex help2man
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=http://www.perl.org/
|
||||
flex_URL=http://flex.sourceforge.net/
|
||||
gnu_software_URL=http://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
case $normalized_program in
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified 'configure.ac',"
|
||||
echo "or m4 files included by it."
|
||||
program_details 'autoconf'
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified 'acconfig.h' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'autoheader'
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified 'Makefile.am' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'automake'
|
||||
;;
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'aclocal'
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
program_details 'autom4te'
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
#! /bin/sh
|
||||
# test-driver - basic testsuite driver script.
|
||||
|
||||
scriptversion=2013-07-13.22; # UTC
|
||||
|
||||
# Copyright (C) 2011-2014 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
# Make unconditional expansion of undefined variables an error. This
|
||||
# helps a lot in preventing typo-related bugs.
|
||||
set -u
|
||||
|
||||
usage_error ()
|
||||
{
|
||||
echo "$0: $*" >&2
|
||||
print_usage >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
print_usage ()
|
||||
{
|
||||
cat <<END
|
||||
Usage:
|
||||
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
|
||||
[--expect-failure={yes|no}] [--color-tests={yes|no}]
|
||||
[--enable-hard-errors={yes|no}] [--]
|
||||
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
|
||||
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
|
||||
END
|
||||
}
|
||||
|
||||
test_name= # Used for reporting.
|
||||
log_file= # Where to save the output of the test script.
|
||||
trs_file= # Where to save the metadata of the test run.
|
||||
expect_failure=no
|
||||
color_tests=no
|
||||
enable_hard_errors=yes
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--help) print_usage; exit $?;;
|
||||
--version) echo "test-driver $scriptversion"; exit $?;;
|
||||
--test-name) test_name=$2; shift;;
|
||||
--log-file) log_file=$2; shift;;
|
||||
--trs-file) trs_file=$2; shift;;
|
||||
--color-tests) color_tests=$2; shift;;
|
||||
--expect-failure) expect_failure=$2; shift;;
|
||||
--enable-hard-errors) enable_hard_errors=$2; shift;;
|
||||
--) shift; break;;
|
||||
-*) usage_error "invalid option: '$1'";;
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
missing_opts=
|
||||
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
|
||||
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
|
||||
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
|
||||
if test x"$missing_opts" != x; then
|
||||
usage_error "the following mandatory options are missing:$missing_opts"
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
usage_error "missing argument"
|
||||
fi
|
||||
|
||||
if test $color_tests = yes; then
|
||||
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
|
||||
red='[0;31m' # Red.
|
||||
grn='[0;32m' # Green.
|
||||
lgn='[1;32m' # Light green.
|
||||
blu='[1;34m' # Blue.
|
||||
mgn='[0;35m' # Magenta.
|
||||
std='[m' # No color.
|
||||
else
|
||||
red= grn= lgn= blu= mgn= std=
|
||||
fi
|
||||
|
||||
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
|
||||
trap "st=129; $do_exit" 1
|
||||
trap "st=130; $do_exit" 2
|
||||
trap "st=141; $do_exit" 13
|
||||
trap "st=143; $do_exit" 15
|
||||
|
||||
# Test script is run here.
|
||||
"$@" >$log_file 2>&1
|
||||
estatus=$?
|
||||
|
||||
if test $enable_hard_errors = no && test $estatus -eq 99; then
|
||||
tweaked_estatus=1
|
||||
else
|
||||
tweaked_estatus=$estatus
|
||||
fi
|
||||
|
||||
case $tweaked_estatus:$expect_failure in
|
||||
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
|
||||
0:*) col=$grn res=PASS recheck=no gcopy=no;;
|
||||
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
|
||||
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
|
||||
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
|
||||
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
|
||||
esac
|
||||
|
||||
# Report the test outcome and exit status in the logs, so that one can
|
||||
# know whether the test passed or failed simply by looking at the '.log'
|
||||
# file, without the need of also peaking into the corresponding '.trs'
|
||||
# file (automake bug#11814).
|
||||
echo "$res $test_name (exit status: $estatus)" >>$log_file
|
||||
|
||||
# Report outcome to console.
|
||||
echo "${col}${res}${std}: $test_name"
|
||||
|
||||
# Register the test result, and other relevant metadata.
|
||||
echo ":test-result: $res" > $trs_file
|
||||
echo ":global-test-result: $res" >> $trs_file
|
||||
echo ":recheck: $recheck" >> $trs_file
|
||||
echo ":copy-in-global-log: $gcopy" >> $trs_file
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
|
@ -4,11 +4,11 @@
|
|||
# go:
|
||||
# go build
|
||||
# go test
|
||||
# man6:
|
||||
# man:
|
||||
# creates manpage mlr.1 and manpage.txt using mlr from the $PATH
|
||||
# copies the latter to docs6/src
|
||||
# also copies it out-of-tree to ~/man/man1, but only if that exists
|
||||
# docs6:
|
||||
# docs:
|
||||
# turn *.md.in into *.md (live code samples), using mlr from the $PATH
|
||||
# turn *.md into docs6/site HTML and CSS files
|
||||
|
||||
|
|
@ -21,10 +21,10 @@ go fmt ./...
|
|||
gofmt -s -w $(find . -name \*.go | grep -v src/parsing)
|
||||
./build
|
||||
|
||||
cd ../man6
|
||||
cd ../man
|
||||
make maybeinstallhome
|
||||
|
||||
cd ../docs6
|
||||
cd ../docs
|
||||
./regen.sh
|
||||
|
||||
echo
|
||||
|
|
|
|||
15
c/.gitignore
vendored
15
c/.gitignore
vendored
|
|
@ -1,15 +0,0 @@
|
|||
x
|
||||
y
|
||||
s
|
||||
tt
|
||||
tt-000-3.1.0
|
||||
tt-001-rslls
|
||||
tti
|
||||
gcm.txt
|
||||
reg_test/runex
|
||||
reg_test/runv
|
||||
timings.txt
|
||||
tbin-1
|
||||
tbin-2
|
||||
tbin-3
|
||||
stars.txt
|
||||
5
c/.vimrc
5
c/.vimrc
|
|
@ -1,5 +0,0 @@
|
|||
map \r :w<C-m>:!bake install<C-m>
|
||||
map \f :w<C-m>:!bake<C-m>
|
||||
map \v :w<C-m>:!bake mlr<C-m>
|
||||
set tw=120
|
||||
set ts=4
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
SUBDIRS= lib cli stream input dsl mapping containers output parsing auxents experimental . unit_test reg_test
|
||||
|
||||
AM_CPPFLAGS= -I${srcdir}
|
||||
AM_CFLAGS= -Wall -std=gnu99
|
||||
bin_PROGRAMS= mlr
|
||||
noinst_PROGRAMS= mlrg
|
||||
|
||||
mlr_SOURCES= mlrmain.c
|
||||
|
||||
mlr_LDFLAGS= -static
|
||||
|
||||
mlr_LDADD= \
|
||||
cli/libcli.la \
|
||||
containers/libcontainers.la \
|
||||
stream/libstream.la \
|
||||
input/libinput.la \
|
||||
dsl/libdsl.la \
|
||||
mapping/libmapping.la \
|
||||
output/liboutput.la \
|
||||
lib/libmlr.la \
|
||||
parsing/libdsl.la \
|
||||
auxents/libauxents.la \
|
||||
-lm
|
||||
|
||||
# Resulting link line:
|
||||
# /bin/sh ../libtool --tag=CC --mode=link
|
||||
# gcc
|
||||
# -Wall -std=gnu99
|
||||
# -g -O2
|
||||
# <<<LDFLAGS GO HERE>>> <-------------------------------------
|
||||
# -o mlr
|
||||
# mlrmain.o
|
||||
# cli/libcli.la
|
||||
# containers/libcontainers.la
|
||||
# stream/libstream.la
|
||||
# input/libinput.la
|
||||
# dsl/libdsl.la
|
||||
# mapping/libmapping.la
|
||||
# output/liboutput.la
|
||||
# lib/libmlr.la
|
||||
# parsing/libdsl.la
|
||||
# auxents/libauxents.la
|
||||
# <<<LDADD GOES HERE>>> <-------------------------------------
|
||||
|
||||
# Other executable variants
|
||||
|
||||
# Debug version:
|
||||
mlrg_CFLAGS= -g ${AM_CFLAGS}
|
||||
mlrg_LDFLAGS= ${mlr_LDFLAGS}
|
||||
mlrg_LDADD= ${mlr_LDADD}
|
||||
mlrg_SOURCES= ${mlr_SOURCES}
|
||||
|
||||
# Profile version. Usage:
|
||||
# * make mlrp
|
||||
# * mlrp {arguments>
|
||||
# * gprof mlrp gmon.out > myfile.txt
|
||||
# Note: works on Linux; not on OSX. On FreeBSD it sounds like it'll need an
|
||||
# extra -lc on the link line.
|
||||
#mlrp_CFLAGS= -g -pg ${AM_CFLAGS}
|
||||
#mlrp_LDFLAGS= ${mlr_LDFLAGS}
|
||||
#mlrp_LDADD= ${mlr_LDADD}
|
||||
#mlrp_SOURCES= ${mlr_SOURCES}
|
||||
|
||||
# ================================================================
|
||||
# Run this after unit-test expected output has changed, and is verified to be
|
||||
# OK. (Example: after adding new test cases in test/run.)
|
||||
regtest-copy:
|
||||
cp output/out reg_test/expected
|
||||
|
||||
# ================================================================
|
||||
perfclean profclean:
|
||||
@rm -vf gmon.out perf.data perf.data.old
|
||||
858
c/Makefile.in
858
c/Makefile.in
|
|
@ -1,858 +0,0 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 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@
|
||||
bin_PROGRAMS = mlr$(EXEEXT)
|
||||
noinst_PROGRAMS = mlrg$(EXEEXT)
|
||||
subdir = c
|
||||
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 $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
|
||||
am_mlr_OBJECTS = mlrmain.$(OBJEXT)
|
||||
mlr_OBJECTS = $(am_mlr_OBJECTS)
|
||||
mlr_DEPENDENCIES = cli/libcli.la containers/libcontainers.la \
|
||||
stream/libstream.la input/libinput.la dsl/libdsl.la \
|
||||
mapping/libmapping.la output/liboutput.la lib/libmlr.la \
|
||||
parsing/libdsl.la auxents/libauxents.la
|
||||
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 =
|
||||
mlr_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(mlr_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am__objects_1 = mlrg-mlrmain.$(OBJEXT)
|
||||
am_mlrg_OBJECTS = $(am__objects_1)
|
||||
mlrg_OBJECTS = $(am_mlrg_OBJECTS)
|
||||
am__DEPENDENCIES_1 = cli/libcli.la containers/libcontainers.la \
|
||||
stream/libstream.la input/libinput.la dsl/libdsl.la \
|
||||
mapping/libmapping.la output/liboutput.la lib/libmlr.la \
|
||||
parsing/libdsl.la auxents/libauxents.la
|
||||
mlrg_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
mlrg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(mlrg_CFLAGS) $(CFLAGS) \
|
||||
$(mlrg_LDFLAGS) $(LDFLAGS) -o $@
|
||||
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 = $(SHELL) $(top_srcdir)/autotools/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
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 = $(mlr_SOURCES) $(mlrg_SOURCES)
|
||||
DIST_SOURCES = $(mlr_SOURCES) $(mlrg_SOURCES)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||
install-data-recursive install-dvi-recursive \
|
||||
install-exec-recursive install-html-recursive \
|
||||
install-info-recursive install-pdf-recursive \
|
||||
install-ps-recursive install-recursive installcheck-recursive \
|
||||
installdirs-recursive pdf-recursive ps-recursive \
|
||||
tags-recursive uninstall-recursive
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
am__recursive_targets = \
|
||||
$(RECURSIVE_TARGETS) \
|
||||
$(RECURSIVE_CLEAN_TARGETS) \
|
||||
$(am__extra_recursive_targets)
|
||||
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||
distdir
|
||||
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
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in \
|
||||
$(top_srcdir)/autotools/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
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@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
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@
|
||||
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@
|
||||
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@
|
||||
SUBDIRS = lib cli stream input dsl mapping containers output parsing auxents experimental . unit_test reg_test
|
||||
AM_CPPFLAGS = -I${srcdir}
|
||||
AM_CFLAGS = -Wall -std=gnu99
|
||||
mlr_SOURCES = mlrmain.c
|
||||
mlr_LDFLAGS = -static
|
||||
mlr_LDADD = \
|
||||
cli/libcli.la \
|
||||
containers/libcontainers.la \
|
||||
stream/libstream.la \
|
||||
input/libinput.la \
|
||||
dsl/libdsl.la \
|
||||
mapping/libmapping.la \
|
||||
output/liboutput.la \
|
||||
lib/libmlr.la \
|
||||
parsing/libdsl.la \
|
||||
auxents/libauxents.la \
|
||||
-lm
|
||||
|
||||
|
||||
# Resulting link line:
|
||||
# /bin/sh ../libtool --tag=CC --mode=link
|
||||
# gcc
|
||||
# -Wall -std=gnu99
|
||||
# -g -O2
|
||||
# <<<LDFLAGS GO HERE>>> <-------------------------------------
|
||||
# -o mlr
|
||||
# mlrmain.o
|
||||
# cli/libcli.la
|
||||
# containers/libcontainers.la
|
||||
# stream/libstream.la
|
||||
# input/libinput.la
|
||||
# dsl/libdsl.la
|
||||
# mapping/libmapping.la
|
||||
# output/liboutput.la
|
||||
# lib/libmlr.la
|
||||
# parsing/libdsl.la
|
||||
# auxents/libauxents.la
|
||||
# <<<LDADD GOES HERE>>> <-------------------------------------
|
||||
|
||||
# Other executable variants
|
||||
|
||||
# Debug version:
|
||||
mlrg_CFLAGS = -g ${AM_CFLAGS}
|
||||
mlrg_LDFLAGS = ${mlr_LDFLAGS}
|
||||
mlrg_LDADD = ${mlr_LDADD}
|
||||
mlrg_SOURCES = ${mlr_SOURCES}
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .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) --gnu c/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu c/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__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
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):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
|| test -f $$p1 \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
@list='$(bin_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-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
|
||||
|
||||
mlr$(EXEEXT): $(mlr_OBJECTS) $(mlr_DEPENDENCIES) $(EXTRA_mlr_DEPENDENCIES)
|
||||
@rm -f mlr$(EXEEXT)
|
||||
$(AM_V_CCLD)$(mlr_LINK) $(mlr_OBJECTS) $(mlr_LDADD) $(LIBS)
|
||||
|
||||
mlrg$(EXEEXT): $(mlrg_OBJECTS) $(mlrg_DEPENDENCIES) $(EXTRA_mlrg_DEPENDENCIES)
|
||||
@rm -f mlrg$(EXEEXT)
|
||||
$(AM_V_CCLD)$(mlrg_LINK) $(mlrg_OBJECTS) $(mlrg_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mlrg-mlrmain.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mlrmain.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mlrg-mlrmain.o: mlrmain.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mlrg_CFLAGS) $(CFLAGS) -MT mlrg-mlrmain.o -MD -MP -MF $(DEPDIR)/mlrg-mlrmain.Tpo -c -o mlrg-mlrmain.o `test -f 'mlrmain.c' || echo '$(srcdir)/'`mlrmain.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mlrg-mlrmain.Tpo $(DEPDIR)/mlrg-mlrmain.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mlrmain.c' object='mlrg-mlrmain.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mlrg_CFLAGS) $(CFLAGS) -c -o mlrg-mlrmain.o `test -f 'mlrmain.c' || echo '$(srcdir)/'`mlrmain.c
|
||||
|
||||
mlrg-mlrmain.obj: mlrmain.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mlrg_CFLAGS) $(CFLAGS) -MT mlrg-mlrmain.obj -MD -MP -MF $(DEPDIR)/mlrg-mlrmain.Tpo -c -o mlrg-mlrmain.obj `if test -f 'mlrmain.c'; then $(CYGPATH_W) 'mlrmain.c'; else $(CYGPATH_W) '$(srcdir)/mlrmain.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mlrg-mlrmain.Tpo $(DEPDIR)/mlrg-mlrmain.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mlrmain.c' object='mlrg-mlrmain.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mlrg_CFLAGS) $(CFLAGS) -c -o mlrg-mlrmain.obj `if test -f 'mlrmain.c'; then $(CYGPATH_W) 'mlrmain.c'; else $(CYGPATH_W) '$(srcdir)/mlrmain.c'; fi`
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run 'make' without going through this Makefile.
|
||||
# To change the values of 'make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in 'config.status', edit 'config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run 'make');
|
||||
# (2) otherwise, pass the desired values on the 'make' command line.
|
||||
$(am__recursive_targets):
|
||||
@fail=; \
|
||||
if $(am__make_keepgoing); then \
|
||||
failcom='fail=yes'; \
|
||||
else \
|
||||
failcom='exit 1'; \
|
||||
fi; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-recursive
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
$(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-recursive
|
||||
|
||||
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-recursive
|
||||
|
||||
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: $(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
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
$(am__make_dryrun) \
|
||||
|| test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
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-recursive
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic clean-libtool \
|
||||
clean-noinstPROGRAMS mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: $(am__recursive_targets) install-am install-strip
|
||||
|
||||
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
|
||||
check-am clean clean-binPROGRAMS clean-generic clean-libtool \
|
||||
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-binPROGRAMS install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs installdirs-am 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-binPROGRAMS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Profile version. Usage:
|
||||
# * make mlrp
|
||||
# * mlrp {arguments>
|
||||
# * gprof mlrp gmon.out > myfile.txt
|
||||
# Note: works on Linux; not on OSX. On FreeBSD it sounds like it'll need an
|
||||
# extra -lc on the link line.
|
||||
#mlrp_CFLAGS= -g -pg ${AM_CFLAGS}
|
||||
#mlrp_LDFLAGS= ${mlr_LDFLAGS}
|
||||
#mlrp_LDADD= ${mlr_LDADD}
|
||||
#mlrp_SOURCES= ${mlr_SOURCES}
|
||||
|
||||
# ================================================================
|
||||
# Run this after unit-test expected output has changed, and is verified to be
|
||||
# OK. (Example: after adding new test cases in test/run.)
|
||||
regtest-copy:
|
||||
cp output/out reg_test/expected
|
||||
|
||||
# ================================================================
|
||||
perfclean profclean:
|
||||
@rm -vf gmon.out perf.data perf.data.old
|
||||
|
||||
# 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:
|
||||
|
|
@ -1,543 +0,0 @@
|
|||
# ================================================================
|
||||
# NOTE: This makefile is not intended to be used in a packaging system --
|
||||
# rather, Miller uses autconfig for that. This makefile is intended for users
|
||||
# who prefer (for whatever reason) to bypass autoconfig. Please also see
|
||||
# http://johnkerl.org/miller/doc/build.html#Without_using_autoconfig
|
||||
# ================================================================
|
||||
|
||||
# ================================================================
|
||||
# Travis does "export CC=gcc", "export CC=clang" so we can pick those up via
|
||||
# "make -e" in ../.travis.yml. Note that "CC?=gcc", without make -e, results
|
||||
# in CC being expanded to cc on my OSX laptop, which is not OK. Hence make -e.
|
||||
CC=gcc
|
||||
CFLAGS=-std=gnu99
|
||||
IFLAGS=-I. -I..
|
||||
|
||||
WFLAGS=-Wall -Werror
|
||||
# Worth exploring ... but needs handling for unused parameters in functions which comply with interfaces.
|
||||
# Best option I'm aware of is to replace "void foo(int bar) {...}" with "void foo(int) {...}" throughout.
|
||||
# WFLAGS=-Wall -Wextra -Werror
|
||||
# WFLAGS=-Wall -Wextra -pedantic-errors -Werror
|
||||
# WFLAGS=-Wall -Wextra -pedantic-errors -Werror=unused-variable
|
||||
|
||||
LFLAGS=-lm
|
||||
|
||||
# You can do make -e INSTALLDIR=/path/to/somewhere/else/bin
|
||||
INSTALLDIR=/usr/local/bin
|
||||
|
||||
CCOPT=$(CC) $(CFLAGS) $(IFLAGS) $(WFLAGS) -O3
|
||||
CCDEBUG=$(CC) -g $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
CCASAN=clang -fsanitize=address -g $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
|
||||
# clang ASAN. Use -O1 for debug mode to (among other things) disable inlining.
|
||||
#CCOPT=clang -fsanitize=address -fno-omit-frame-pointer $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
#CCDEBUG=clang -g -fsanitize=address -fno-omit-frame-pointer $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Miller source except DSL
|
||||
NON_DSL_SRCS = \
|
||||
*.c \
|
||||
cli/*.c \
|
||||
lib/*.c \
|
||||
containers/*.c \
|
||||
auxents/*.c \
|
||||
stream/*.c \
|
||||
input/*.c \
|
||||
dsl/*.c \
|
||||
mapping/*.c \
|
||||
output/*.c
|
||||
|
||||
# DSL
|
||||
DSL_OBJS = \
|
||||
./parsing/mlr_dsl_parse.o \
|
||||
./parsing/mlr_dsl_lexer.o \
|
||||
./parsing/mlr_dsl_wrapper.o
|
||||
|
||||
# Unit-test code
|
||||
TEST_ARGPARSE_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
cli/argparse.c \
|
||||
containers/slls.c \
|
||||
containers/sllv.c \
|
||||
lib/string_array.c \
|
||||
unit_test/test_argparse.c
|
||||
|
||||
TEST_BYTE_READERS_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlr_test_util.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
input/string_byte_reader.c \
|
||||
input/stdio_byte_reader.c \
|
||||
unit_test/test_byte_readers.c
|
||||
|
||||
TEST_LINE_READERS_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrescape.c \
|
||||
lib/context.c \
|
||||
lib/mlr_test_util.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
input/line_readers.c \
|
||||
unit_test/test_line_readers.c
|
||||
|
||||
TEST_PEEK_FILE_READER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlr_test_util.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
input/string_byte_reader.c \
|
||||
input/peek_file_reader.c \
|
||||
unit_test/test_peek_file_reader.c
|
||||
|
||||
TEST_LREC_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/context.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
lib/mlrval.c \
|
||||
lib/mvfuncs.c \
|
||||
containers/hss.c \
|
||||
containers/lrec.c \
|
||||
containers/header_keeper.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/rslls.c \
|
||||
containers/lhmsv.c \
|
||||
containers/lhmslv.c \
|
||||
containers/sllmv.c \
|
||||
containers/mlhmmv.c \
|
||||
input/line_readers.c \
|
||||
input/file_reader_stdio.c \
|
||||
input/file_ingestor_stdio.c \
|
||||
input/lrec_reader_stdio_csvlite.c \
|
||||
input/lrec_reader_stdio_dkvp.c \
|
||||
input/lrec_reader_stdio_nidx.c \
|
||||
input/lrec_reader_stdio_xtab.c \
|
||||
input/lrec_reader_stdio_json.c \
|
||||
input/mlr_json_adapter.c \
|
||||
input/json_parser.c \
|
||||
unit_test/test_lrec.c
|
||||
|
||||
TEST_MULTIPLE_CONTAINERS_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/context.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
containers/lrec.c \
|
||||
containers/header_keeper.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/rslls.c \
|
||||
lib/string_array.c \
|
||||
containers/hss.c \
|
||||
lib/mlrval.c \
|
||||
lib/mvfuncs.c \
|
||||
containers/lhmsi.c \
|
||||
containers/lhmsll.c \
|
||||
containers/lhmss.c \
|
||||
containers/lhmsv.c \
|
||||
containers/lhms2v.c \
|
||||
containers/lhmslv.c \
|
||||
containers/lhmsmv.c \
|
||||
containers/loop_stack.c \
|
||||
containers/percentile_keeper.c \
|
||||
containers/top_keeper.c \
|
||||
containers/dheap.c \
|
||||
input/line_readers.c \
|
||||
input/file_reader_stdio.c \
|
||||
input/file_ingestor_stdio.c \
|
||||
input/lrec_reader_stdio_csvlite.c \
|
||||
input/lrec_reader_stdio_dkvp.c \
|
||||
input/lrec_reader_stdio_nidx.c \
|
||||
input/lrec_reader_stdio_xtab.c \
|
||||
input/lrec_reader_stdio_json.c \
|
||||
input/mlr_json_adapter.c \
|
||||
input/json_parser.c \
|
||||
unit_test/test_multiple_containers.c
|
||||
|
||||
TEST_MLHMMV_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrval.c \
|
||||
lib/mvfuncs.c \
|
||||
containers/hss.c \
|
||||
containers/mlhmmv.c \
|
||||
containers/sllmv.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/lrec.c \
|
||||
unit_test/test_mlhmmv.c
|
||||
|
||||
TEST_MLRUTIL_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/string_builder.c \
|
||||
unit_test/test_mlrutil.c
|
||||
|
||||
TEST_MLRREGEX_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrregex.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
unit_test/test_mlrregex.c
|
||||
|
||||
TEST_STRING_BUILDER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
unit_test/test_string_builder.c
|
||||
|
||||
TEST_PARSE_TRIE_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
containers/parse_trie.c \
|
||||
unit_test/test_parse_trie.c
|
||||
|
||||
TEST_RVAL_EVALUATORS_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlrmath.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
lib/mlrval.c \
|
||||
lib/mvfuncs.c \
|
||||
containers/xvfuncs.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/sllmv.c \
|
||||
containers/lrec.c \
|
||||
containers/lhmsv.c \
|
||||
containers/lhmsi.c \
|
||||
containers/lhmsll.c \
|
||||
containers/mlhmmv.c \
|
||||
containers/lhmsmv.c \
|
||||
containers/lhmss.c \
|
||||
containers/hss.c \
|
||||
containers/mixutil.c \
|
||||
containers/loop_stack.c \
|
||||
containers/local_stack.c \
|
||||
containers/type_decl.c \
|
||||
dsl/mlr_dsl_ast.c \
|
||||
dsl/function_manager.c \
|
||||
dsl/keylist_evaluators.c \
|
||||
dsl/rval_expr_evaluators.c \
|
||||
dsl/rxval_expr_evaluators.c \
|
||||
dsl/rval_func_evaluators.c \
|
||||
dsl/rxval_func_evaluators.c \
|
||||
dsl/rval_list_evaluators.c \
|
||||
dsl/mlr_dsl_stack_allocate.c \
|
||||
dsl/mlr_dsl_blocked_ast.c \
|
||||
dsl/mlr_dsl_cst.c \
|
||||
dsl/mlr_dsl_cst_condish_statements.c \
|
||||
dsl/mlr_dsl_cst_for_map_statements.c \
|
||||
dsl/mlr_dsl_cst_for_srec_statements.c \
|
||||
dsl/mlr_dsl_cst_func_subr.c \
|
||||
dsl/mlr_dsl_cst_keywords.c \
|
||||
dsl/mlr_dsl_cst_loop_control_statements.c \
|
||||
dsl/mlr_dsl_cst_map_assignment_statements.c \
|
||||
dsl/mlr_dsl_cst_output_statements.c \
|
||||
dsl/mlr_dsl_cst_return_statements.c \
|
||||
dsl/mlr_dsl_cst_scalar_assignment_statements.c \
|
||||
dsl/mlr_dsl_cst_statements.c \
|
||||
dsl/mlr_dsl_cst_triple_for_statements.c \
|
||||
dsl/mlr_dsl_cst_unset_statements.c \
|
||||
output/lrec_writer_csv.c \
|
||||
output/lrec_writer_csvlite.c \
|
||||
output/lrec_writer_dkvp.c \
|
||||
output/lrec_writer_json.c \
|
||||
output/lrec_writer_markdown.c \
|
||||
output/lrec_writer_nidx.c \
|
||||
output/lrec_writer_pprint.c \
|
||||
output/lrec_writer_xtab.c \
|
||||
output/lrec_writers.c \
|
||||
output/multi_lrec_writer.c \
|
||||
output/multi_out.c \
|
||||
unit_test/test_rval_evaluators.c
|
||||
|
||||
TEST_JOIN_BUCKET_KEEPER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
lib/mlrregex.c \
|
||||
lib/context.c \
|
||||
lib/string_array.c \
|
||||
containers/parse_trie.c \
|
||||
containers/lrec.c \
|
||||
containers/sllv.c \
|
||||
containers/rslls.c \
|
||||
containers/slls.c \
|
||||
containers/lhmslv.c \
|
||||
containers/lhmss.c \
|
||||
containers/hss.c \
|
||||
containers/mixutil.c \
|
||||
containers/header_keeper.c \
|
||||
containers/join_bucket_keeper.c \
|
||||
input/stdio_byte_reader.c \
|
||||
input/line_readers.c \
|
||||
input/lrec_reader_gen.c \
|
||||
input/lrec_reader_in_memory.c \
|
||||
input/lrec_readers.c \
|
||||
input/lrec_reader_stdio_csv.c \
|
||||
input/lrec_reader_stdio_csvlite.c \
|
||||
input/lrec_reader_stdio_dkvp.c \
|
||||
input/lrec_reader_stdio_nidx.c \
|
||||
input/lrec_reader_stdio_xtab.c \
|
||||
input/lrec_reader_stdio_json.c \
|
||||
input/mlr_json_adapter.c \
|
||||
input/json_parser.c \
|
||||
input/file_reader_stdio.c \
|
||||
input/file_ingestor_stdio.c \
|
||||
input/peek_file_reader.c \
|
||||
unit_test/test_join_bucket_keeper.c
|
||||
|
||||
EXPERIMENTAL_READER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
lib/context.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_array.c \
|
||||
lib/string_builder.c \
|
||||
input/stdio_byte_reader.c \
|
||||
input/line_readers.c \
|
||||
containers/parse_trie.c \
|
||||
experimental/getlines.c
|
||||
|
||||
EXPERIMENTAL_JSON_VG_MEM_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/nlnet_timegm.c \
|
||||
lib/netbsd_strptime.c \
|
||||
lib/mtrand.c \
|
||||
input/json_parser.c \
|
||||
experimental/json_vg_mem.c
|
||||
|
||||
# ================================================================
|
||||
# User-make: creates the executable and runs unit & regression tests
|
||||
# This is the default target for anyone pulling the repo and trying to
|
||||
# build it to be able to use it. It just needs flex and the C compiler.
|
||||
#top: mlr tests
|
||||
# xxx temp:
|
||||
top: mlr mlrg tests
|
||||
|
||||
install: mlr tests
|
||||
mkdir -p $(INSTALLDIR)
|
||||
cp mlr $(INSTALLDIR)
|
||||
installhome: mlr tests
|
||||
mkdir -p $(HOME)/bin
|
||||
cp mlr $(HOME)/bin
|
||||
|
||||
# ================================================================
|
||||
tags: .always
|
||||
ctags -R .
|
||||
|
||||
mlr: .always parsing
|
||||
$(CCOPT) $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlr
|
||||
# On x86_64/Centos I had to first do
|
||||
# sudo yum install glibc-devel glibc-static
|
||||
mlr.static: .always parsing
|
||||
$(CCOPT) -static $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlr.static
|
||||
|
||||
parsing: .always
|
||||
make -C parsing -f Makefile.no-autoconfig mlr_dsl_parse.o
|
||||
make -C parsing -f Makefile.no-autoconfig mlr_dsl_lexer.o
|
||||
make -C parsing -f Makefile.no-autoconfig mlr_dsl_wrapper.o
|
||||
|
||||
two: mlr mlrg
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Other executable variants
|
||||
|
||||
# Debug version
|
||||
mlrg: .always parsing
|
||||
$(CCDEBUG) $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlrg
|
||||
|
||||
# Debug version with local-stack verbosity
|
||||
mlrt: .always parsing
|
||||
$(CCDEBUG) -DLOCAL_STACK_TRACE_ENABLE -DLOCAL_STACK_BOUNDS_CHECK_ENABLE \
|
||||
$(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlrt
|
||||
|
||||
# Profile version. Usage:
|
||||
# * make mlrp
|
||||
# * mlrp {arguments>
|
||||
# * gprof mlrp gmon.out > myfile.txt
|
||||
# Note: works on Linux; not on OSX.
|
||||
mlrp: .always parsing
|
||||
$(CCDEBUG) -g -pg $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlrp
|
||||
|
||||
# ASAN version
|
||||
mlra: .always parsing
|
||||
$(CCASAN) $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlra
|
||||
|
||||
# ================================================================
|
||||
tests: unit-test reg-test
|
||||
|
||||
unit-test: test-mlrutil test-mlrregex test-argparse test-line-readers test-byte-readers test-peek-file-reader test-parse-trie test-lrec test-multiple-containers test-mlhmmv test-string-builder test-rval-evaluators test-join-bucket-keeper
|
||||
./test-mlrutil
|
||||
./test-mlrregex
|
||||
./test-argparse
|
||||
./test-line-readers
|
||||
./test-byte-readers
|
||||
./test-peek-file-reader
|
||||
./test-parse-trie
|
||||
./test-lrec
|
||||
./test-multiple-containers
|
||||
./test-mlhmmv
|
||||
./test-string-builder
|
||||
./test-rval-evaluators
|
||||
./test-join-bucket-keeper
|
||||
@echo
|
||||
@echo DONE
|
||||
|
||||
reg-test:
|
||||
./reg_test/run
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Run this after unit-test expected output has changed, and is verified to be
|
||||
# OK. (Example: after adding new test cases in test/run.)
|
||||
regtest-copy taters:
|
||||
cp output-regtest/out reg_test/expected
|
||||
regtest-copy-dev:
|
||||
cp output-regtest/out-dev reg_test/expected
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Unit-test executables
|
||||
|
||||
test-argparse: .always
|
||||
$(CCDEBUG) $(TEST_ARGPARSE_SRCS) $(LFLAGS) -o test-argparse
|
||||
|
||||
test-byte-readers: .always
|
||||
$(CCDEBUG) $(TEST_BYTE_READERS_SRCS) $(LFLAGS) -o test-byte-readers
|
||||
|
||||
test-line-readers: .always
|
||||
$(CCDEBUG) $(TEST_LINE_READERS_SRCS) $(LFLAGS) -o test-line-readers
|
||||
|
||||
test-peek-file-reader: .always
|
||||
$(CCDEBUG) $(TEST_PEEK_FILE_READER_SRCS) $(LFLAGS) -o test-peek-file-reader
|
||||
|
||||
test-lrec: .always
|
||||
$(CCDEBUG) $(TEST_LREC_SRCS) $(LFLAGS) -o test-lrec -lm
|
||||
|
||||
test-multiple-containers: .always
|
||||
$(CCDEBUG) $(TEST_MULTIPLE_CONTAINERS_SRCS) $(LFLAGS) -o test-multiple-containers -lm
|
||||
|
||||
test-mlhmmv: .always
|
||||
$(CCDEBUG) $(TEST_MLHMMV_SRCS) $(LFLAGS) -o test-mlhmmv -lm
|
||||
|
||||
test-mlrutil: .always
|
||||
$(CCDEBUG) $(TEST_MLRUTIL_SRCS) $(LFLAGS) -o test-mlrutil -lm
|
||||
|
||||
test-mlrregex: .always
|
||||
$(CCDEBUG) $(TEST_MLRREGEX_SRCS) $(LFLAGS) -o test-mlrregex
|
||||
|
||||
test-string-builder: .always
|
||||
$(CCDEBUG) $(TEST_STRING_BUILDER_SRCS) $(LFLAGS) -o test-string-builder
|
||||
|
||||
test-parse-trie: .always
|
||||
$(CCDEBUG) $(TEST_PARSE_TRIE_SRCS) $(LFLAGS) -o test-parse-trie
|
||||
|
||||
test-rval-evaluators: .always
|
||||
$(CCDEBUG) $(TEST_RVAL_EVALUATORS_SRCS) $(LFLAGS) -o test-rval-evaluators -lm
|
||||
|
||||
test-join-bucket-keeper: .always
|
||||
$(CCDEBUG) $(TEST_JOIN_BUCKET_KEEPER_SRCS) $(LFLAGS) -o test-join-bucket-keeper -lm
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Standalone mains
|
||||
|
||||
getl: .always
|
||||
$(CCOPT) $(EXPERIMENTAL_READER_SRCS) $(LFLAGS) -o getl
|
||||
|
||||
json-vg-mem: .always
|
||||
$(CCDEBUG) $(EXPERIMENTAL_JSON_VG_MEM_SRCS) $(LFLAGS) -o json-vg-mem
|
||||
|
||||
# ================================================================
|
||||
# BSD can't handle rm -v, alas
|
||||
clean:
|
||||
@rm -f mlr mlrd mlrg mlrp tester
|
||||
@make -C parsing -f Makefile.no-autoconfig clean
|
||||
|
||||
perfclean profclean:
|
||||
@rm -f gmon.out perf.data perf.data.old
|
||||
|
||||
.always:
|
||||
@true
|
||||
|
|
@ -1,499 +0,0 @@
|
|||
# ================================================================
|
||||
# NOTE: This makefile is not intended to be used in a packaging system --
|
||||
# rather, Miller uses autconfig for that. This makefile is intended for users
|
||||
# who prefer (for whatever reason) to bypass autoconfig. Please also see
|
||||
# http://johnkerl.org/miller/doc/build.html#Without_using_autoconfig
|
||||
# ================================================================
|
||||
|
||||
# ================================================================
|
||||
# Travis does "export CC=gcc", "export CC=clang" so we can pick those up via
|
||||
# "make -e" in ../.travis.yml. Note that "CC?=gcc", without make -e, results
|
||||
# in CC being expanded to cc on my OSX laptop, which is not OK. Hence make -e.
|
||||
CC=gcc
|
||||
CFLAGS=-std=gnu99
|
||||
IFLAGS=-I. -I..
|
||||
|
||||
WFLAGS=-Wall
|
||||
# Worth exploring ... but needs handling for unused parameters in functions which comply with interfaces.
|
||||
# Best option I'm aware of is to replace "void foo(int bar) {...}" with "void foo(int) {...}" throughout.
|
||||
# WFLAGS=-Wall -Wextra -Werror
|
||||
# WFLAGS=-Wall -Wextra -pedantic-errors -Werror
|
||||
# WFLAGS=-Wall -Wextra -pedantic-errors -Werror=unused-variable
|
||||
|
||||
LFLAGS=-lm -lpcreposix
|
||||
|
||||
# You can do make -e INSTALLDIR=/path/to/somewhere/else/bin
|
||||
INSTALLDIR=/usr/local/bin
|
||||
|
||||
CCOPT=$(CC) $(CFLAGS) $(IFLAGS) $(WFLAGS) -O3
|
||||
CCDEBUG=$(CC) -g $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
|
||||
# clang ASAN. Use -O1 for debug mode to (among other things) disable inlining.
|
||||
#CCOPT=clang -fsanitize=address -fno-omit-frame-pointer $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
#CCDEBUG=clang -g -fsanitize=address -fno-omit-frame-pointer $(CFLAGS) $(IFLAGS) $(WFLAGS)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Miller source except DSL
|
||||
NON_DSL_SRCS = \
|
||||
*.c \
|
||||
cli/*.c \
|
||||
lib/*.c \
|
||||
containers/*.c \
|
||||
aux/*.c \
|
||||
stream/*.c \
|
||||
input/*.c \
|
||||
dsl/*.c \
|
||||
mapping/*.c \
|
||||
output/*.c
|
||||
|
||||
# DSL
|
||||
DSL_OBJS = \
|
||||
./parsing/mlr_dsl_parse.o \
|
||||
./parsing/mlr_dsl_lexer.o \
|
||||
./parsing/mlr_dsl_wrapper.o
|
||||
|
||||
# Unit-test code
|
||||
TEST_ARGPARSE_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
cli/argparse.c \
|
||||
containers/slls.c \
|
||||
containers/sllv.c \
|
||||
lib/string_array.c \
|
||||
unit_test/test_argparse.c
|
||||
|
||||
TEST_BYTE_READERS_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlr_test_util.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
input/string_byte_reader.c \
|
||||
input/stdio_byte_reader.c \
|
||||
unit_test/test_byte_readers.c
|
||||
|
||||
TEST_LINE_READERS_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrescape.c \
|
||||
lib/context.c \
|
||||
lib/mlr_test_util.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
input/line_readers.c \
|
||||
unit_test/test_line_readers.c
|
||||
|
||||
TEST_PEEK_FILE_READER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlr_test_util.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
input/string_byte_reader.c \
|
||||
input/peek_file_reader.c \
|
||||
unit_test/test_peek_file_reader.c
|
||||
|
||||
TEST_LREC_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/context.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
containers/mlrval.c \
|
||||
containers/mvfuncs.c \
|
||||
containers/lrec.c \
|
||||
containers/header_keeper.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/rslls.c \
|
||||
containers/lhmsv.c \
|
||||
containers/lhmslv.c \
|
||||
containers/sllmv.c \
|
||||
containers/mlhmmv.c \
|
||||
input/line_readers.c \
|
||||
input/file_reader_stdio.c \
|
||||
input/file_ingestor_stdio.c \
|
||||
input/lrec_reader_stdio_csvlite.c \
|
||||
input/lrec_reader_stdio_dkvp.c \
|
||||
input/lrec_reader_stdio_nidx.c \
|
||||
input/lrec_reader_stdio_xtab.c \
|
||||
input/lrec_reader_stdio_json.c \
|
||||
input/mlr_json_adapter.c \
|
||||
input/json_parser.c \
|
||||
unit_test/test_lrec.c
|
||||
|
||||
TEST_MULTIPLE_CONTAINERS_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/context.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
containers/lrec.c \
|
||||
containers/header_keeper.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/rslls.c \
|
||||
lib/string_array.c \
|
||||
containers/hss.c \
|
||||
containers/mlrval.c \
|
||||
containers/mvfuncs.c \
|
||||
containers/lhmsi.c \
|
||||
containers/lhmsll.c \
|
||||
containers/lhmss.c \
|
||||
containers/lhmsv.c \
|
||||
containers/lhms2v.c \
|
||||
containers/lhmslv.c \
|
||||
containers/lhmsmv.c \
|
||||
containers/loop_stack.c \
|
||||
containers/percentile_keeper.c \
|
||||
containers/top_keeper.c \
|
||||
containers/dheap.c \
|
||||
input/line_readers.c \
|
||||
input/file_reader_stdio.c \
|
||||
input/file_ingestor_stdio.c \
|
||||
input/lrec_reader_stdio_csvlite.c \
|
||||
input/lrec_reader_stdio_dkvp.c \
|
||||
input/lrec_reader_stdio_nidx.c \
|
||||
input/lrec_reader_stdio_xtab.c \
|
||||
input/lrec_reader_stdio_json.c \
|
||||
input/mlr_json_adapter.c \
|
||||
input/json_parser.c \
|
||||
unit_test/test_multiple_containers.c
|
||||
|
||||
TEST_MLHMMV_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
containers/mlrval.c \
|
||||
containers/mvfuncs.c \
|
||||
containers/mlhmmv.c \
|
||||
containers/sllmv.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/lrec.c \
|
||||
unit_test/test_mlhmmv.c
|
||||
|
||||
TEST_MLRUTIL_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/string_builder.c \
|
||||
unit_test/test_mlrutil.c
|
||||
|
||||
TEST_MLRREGEX_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrregex.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
unit_test/test_mlrregex.c
|
||||
|
||||
TEST_STRING_BUILDER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
unit_test/test_string_builder.c
|
||||
|
||||
TEST_PARSE_TRIE_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
containers/parse_trie.c \
|
||||
unit_test/test_parse_trie.c
|
||||
|
||||
TEST_RVAL_EVALUATORS_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlrmath.c \
|
||||
lib/string_builder.c \
|
||||
lib/string_array.c \
|
||||
containers/mlrval.c \
|
||||
containers/mvfuncs.c \
|
||||
containers/xvfuncs.c \
|
||||
containers/sllv.c \
|
||||
containers/slls.c \
|
||||
containers/sllmv.c \
|
||||
containers/lrec.c \
|
||||
containers/lhmsv.c \
|
||||
containers/lhmsi.c \
|
||||
containers/lhmsll.c \
|
||||
containers/mlhmmv.c \
|
||||
containers/lhmsmv.c \
|
||||
containers/hss.c \
|
||||
containers/mixutil.c \
|
||||
containers/loop_stack.c \
|
||||
containers/local_stack.c \
|
||||
containers/type_decl.c \
|
||||
dsl/mlr_dsl_ast.c \
|
||||
dsl/function_manager.c \
|
||||
dsl/keylist_evaluators.c \
|
||||
dsl/rval_expr_evaluators.c \
|
||||
dsl/rxval_expr_evaluators.c \
|
||||
dsl/rval_func_evaluators.c \
|
||||
dsl/rxval_func_evaluators.c \
|
||||
dsl/rval_list_evaluators.c \
|
||||
dsl/mlr_dsl_stack_allocate.c \
|
||||
dsl/mlr_dsl_blocked_ast.c \
|
||||
dsl/mlr_dsl_cst.c \
|
||||
dsl/mlr_dsl_cst_condish_statements.c \
|
||||
dsl/mlr_dsl_cst_for_map_statements.c \
|
||||
dsl/mlr_dsl_cst_for_srec_statements.c \
|
||||
dsl/mlr_dsl_cst_func_subr.c \
|
||||
dsl/mlr_dsl_cst_keywords.c \
|
||||
dsl/mlr_dsl_cst_loop_control_statements.c \
|
||||
dsl/mlr_dsl_cst_map_assignment_statements.c \
|
||||
dsl/mlr_dsl_cst_output_statements.c \
|
||||
dsl/mlr_dsl_cst_return_statements.c \
|
||||
dsl/mlr_dsl_cst_scalar_assignment_statements.c \
|
||||
dsl/mlr_dsl_cst_statements.c \
|
||||
dsl/mlr_dsl_cst_triple_for_statements.c \
|
||||
dsl/mlr_dsl_cst_unset_statements.c \
|
||||
output/lrec_writer_csv.c \
|
||||
output/lrec_writer_csvlite.c \
|
||||
output/lrec_writer_dkvp.c \
|
||||
output/lrec_writer_json.c \
|
||||
output/lrec_writer_markdown.c \
|
||||
output/lrec_writer_nidx.c \
|
||||
output/lrec_writer_pprint.c \
|
||||
output/lrec_writer_xtab.c \
|
||||
output/lrec_writers.c \
|
||||
output/multi_lrec_writer.c \
|
||||
output/multi_out.c \
|
||||
unit_test/test_rval_evaluators.c
|
||||
|
||||
TEST_JOIN_BUCKET_KEEPER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_builder.c \
|
||||
lib/context.c \
|
||||
containers/parse_trie.c \
|
||||
containers/lrec.c \
|
||||
containers/sllv.c \
|
||||
containers/rslls.c \
|
||||
containers/slls.c \
|
||||
containers/lhmslv.c \
|
||||
containers/hss.c \
|
||||
containers/mixutil.c \
|
||||
containers/header_keeper.c \
|
||||
containers/join_bucket_keeper.c \
|
||||
input/stdio_byte_reader.c \
|
||||
input/line_readers.c \
|
||||
input/lrec_reader_in_memory.c \
|
||||
input/lrec_readers.c \
|
||||
input/lrec_reader_stdio_csv.c \
|
||||
input/lrec_reader_stdio_csvlite.c \
|
||||
input/lrec_reader_stdio_dkvp.c \
|
||||
input/lrec_reader_stdio_nidx.c \
|
||||
input/lrec_reader_stdio_xtab.c \
|
||||
input/lrec_reader_stdio_json.c \
|
||||
input/mlr_json_adapter.c \
|
||||
input/json_parser.c \
|
||||
input/file_reader_stdio.c \
|
||||
input/file_ingestor_stdio.c \
|
||||
input/peek_file_reader.c \
|
||||
unit_test/test_join_bucket_keeper.c
|
||||
|
||||
EXPERIMENTAL_READER_SRCS = \
|
||||
lib/mlrutil.c \
|
||||
lib/mlrdatetime.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
lib/context.c \
|
||||
lib/mlrescape.c \
|
||||
lib/mlrregex.c \
|
||||
lib/mlr_globals.c \
|
||||
lib/string_array.c \
|
||||
lib/string_builder.c \
|
||||
input/stdio_byte_reader.c \
|
||||
input/line_readers.c \
|
||||
containers/parse_trie.c \
|
||||
experimental/getlines.c
|
||||
|
||||
EXPERIMENTAL_JSON_VG_MEM_SRCS = \
|
||||
lib/mlr_globals.c \
|
||||
lib/mlrutil.c \
|
||||
lib/mlr_arch.c \
|
||||
lib/mtrand.c \
|
||||
input/json_parser.c \
|
||||
experimental/json_vg_mem.c
|
||||
|
||||
# ================================================================
|
||||
# User-make: creates the executable and runs unit & regression tests
|
||||
# This is the default target for anyone pulling the repo and trying to
|
||||
# build it to be able to use it. It just needs flex and the C compiler.
|
||||
#top: mlr tests
|
||||
# xxx temp:
|
||||
top: mlr mlrg tests
|
||||
|
||||
install: mlr tests
|
||||
cp mlr $(INSTALLDIR)
|
||||
installhome: mlr tests
|
||||
cp mlr $(HOME)/bin
|
||||
|
||||
# ================================================================
|
||||
tags: .always
|
||||
ctags -R .
|
||||
|
||||
mlr: .always parsing
|
||||
$(CCOPT) $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlr
|
||||
# On x86_64/Centos I had to first do
|
||||
# sudo yum install glibc-devel glibc-static
|
||||
mlr.static: .always parsing
|
||||
$(CCOPT) -static $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlr.static
|
||||
|
||||
parsing: .always
|
||||
make -C parsing -f Makefile.no-autoconfig mlr_dsl_parse.o
|
||||
make -C parsing -f Makefile.no-autoconfig mlr_dsl_lexer.o
|
||||
make -C parsing -f Makefile.no-autoconfig mlr_dsl_wrapper.o
|
||||
|
||||
two: mlr mlrg
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Other executable variants
|
||||
|
||||
# Debug version
|
||||
mlrg: .always parsing
|
||||
$(CCDEBUG) $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlrg
|
||||
|
||||
# Debug version with local-stack verbosity
|
||||
mlrt: .always parsing
|
||||
$(CCDEBUG) -DLOCAL_STACK_TRACE_ENABLE -DLOCAL_STACK_BOUNDS_CHECK_ENABLE \
|
||||
$(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlrt
|
||||
|
||||
# Profile version. Usage:
|
||||
# * make mlrp
|
||||
# * mlrp {arguments>
|
||||
# * gprof mlrp gmon.out > myfile.txt
|
||||
# Note: works on Linux; not on OSX.
|
||||
mlrp: .always parsing
|
||||
$(CCDEBUG) -g -pg $(NON_DSL_SRCS) $(DSL_OBJS) $(LFLAGS) -o mlrp
|
||||
|
||||
# ================================================================
|
||||
tests: unit-test reg-test
|
||||
|
||||
unit-test: test-mlrutil test-mlrregex test-argparse test-line-readers test-byte-readers test-peek-file-reader test-parse-trie test-lrec test-multiple-containers test-mlhmmv test-string-builder test-rval-evaluators test-join-bucket-keeper
|
||||
./test-mlrutil
|
||||
./test-mlrregex
|
||||
./test-argparse
|
||||
./test-line-readers
|
||||
./test-byte-readers
|
||||
./test-peek-file-reader
|
||||
./test-parse-trie
|
||||
./test-lrec
|
||||
./test-multiple-containers
|
||||
./test-mlhmmv
|
||||
./test-string-builder
|
||||
./test-rval-evaluators
|
||||
./test-join-bucket-keeper
|
||||
@echo
|
||||
@echo DONE
|
||||
|
||||
reg-test:
|
||||
./reg_test/run
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Run this after unit-test expected output has changed, and is verified to be
|
||||
# OK. (Example: after adding new test cases in test/run.)
|
||||
regtest-copy taters:
|
||||
cp output-regtest/out reg_test/expected
|
||||
regtest-copy-dev:
|
||||
cp output-regtest/out-dev reg_test/expected
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Unit-test executables
|
||||
|
||||
test-argparse: .always
|
||||
$(CCDEBUG) $(TEST_ARGPARSE_SRCS) $(LFLAGS) -o test-argparse
|
||||
|
||||
test-byte-readers: .always
|
||||
$(CCDEBUG) $(TEST_BYTE_READERS_SRCS) $(LFLAGS) -o test-byte-readers
|
||||
|
||||
test-line-readers: .always
|
||||
$(CCDEBUG) $(TEST_LINE_READERS_SRCS) $(LFLAGS) -o test-line-readers
|
||||
|
||||
test-peek-file-reader: .always
|
||||
$(CCDEBUG) $(TEST_PEEK_FILE_READER_SRCS) $(LFLAGS) -o test-peek-file-reader
|
||||
|
||||
test-lrec: .always
|
||||
$(CCDEBUG) $(TEST_LREC_SRCS) $(LFLAGS) -o test-lrec -lm
|
||||
|
||||
test-multiple-containers: .always
|
||||
$(CCDEBUG) $(TEST_MULTIPLE_CONTAINERS_SRCS) $(LFLAGS) -o test-multiple-containers -lm
|
||||
|
||||
test-mlhmmv: .always
|
||||
$(CCDEBUG) $(TEST_MLHMMV_SRCS) $(LFLAGS) -o test-mlhmmv -lm
|
||||
|
||||
test-mlrutil: .always
|
||||
$(CCDEBUG) $(TEST_MLRUTIL_SRCS) $(LFLAGS) -o test-mlrutil -lm
|
||||
|
||||
test-mlrregex: .always
|
||||
$(CCDEBUG) $(TEST_MLRREGEX_SRCS) $(LFLAGS) -o test-mlrregex
|
||||
|
||||
test-string-builder: .always
|
||||
$(CCDEBUG) $(TEST_STRING_BUILDER_SRCS) $(LFLAGS) -o test-string-builder
|
||||
|
||||
test-parse-trie: .always
|
||||
$(CCDEBUG) $(TEST_PARSE_TRIE_SRCS) $(LFLAGS) -o test-parse-trie
|
||||
|
||||
test-rval-evaluators: .always
|
||||
$(CCDEBUG) $(TEST_RVAL_EVALUATORS_SRCS) $(LFLAGS) -o test-rval-evaluators -lm
|
||||
|
||||
test-join-bucket-keeper: .always
|
||||
$(CCDEBUG) $(TEST_JOIN_BUCKET_KEEPER_SRCS) $(LFLAGS) -o test-join-bucket-keeper -lm
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Standalone mains
|
||||
|
||||
getl: .always
|
||||
$(CCOPT) $(EXPERIMENTAL_READER_SRCS) $(LFLAGS) -o getl
|
||||
|
||||
json-vg-mem: .always
|
||||
$(CCDEBUG) $(EXPERIMENTAL_JSON_VG_MEM_SRCS) $(LFLAGS) -o json-vg-mem
|
||||
|
||||
# ================================================================
|
||||
# BSD can't handle rm -v, alas
|
||||
clean:
|
||||
@rm -f mlr mlrd mlrg mlrp tester
|
||||
@make -C parsing -f Makefile.no-autoconfig clean
|
||||
|
||||
perfclean profclean:
|
||||
@rm -f gmon.out perf.data perf.data.old
|
||||
|
||||
.always:
|
||||
@true
|
||||
100
c/README.md
100
c/README.md
|
|
@ -1,100 +0,0 @@
|
|||
# Data flow
|
||||
|
||||
Miller data flow is records produced by a record-reader in `input/`, followed
|
||||
by one or more mappers in `mapping/`, written by a record-writer in `output/`,
|
||||
controlled by logic in `stream/`. Argument parsing for initial stream setup is
|
||||
in `cli/`.
|
||||
|
||||
# Container names
|
||||
|
||||
The user-visible concept of *stream record* (or *srec*) is implemented in the
|
||||
`lrec_t` (*linked-record type*) data structure. The user-visible concept of
|
||||
*out-of-stream variables* is implemented using the `mlhmmv_t` (multi-level
|
||||
hashmap of mlrvals) structure. Source-code comments and names within the code
|
||||
refer to `srec`/`lrec` and `oosvar`/`mlhmmv` depending on the context.
|
||||
|
||||
While those two data structures contain user-visible data structures, others
|
||||
are used in Miller's implementation: `slls` and `sllv` are singly-linked lists
|
||||
of string and void-star respectively; `lhmss` is a linked hashmap from string
|
||||
to string; `lhmsi` is a linked hashmap from string to int; and so on.
|
||||
|
||||
# Memory management
|
||||
|
||||
Miller is streaming and as near stateless as possible. For most Miller
|
||||
functions, you can ingest a 20GB file with 4GB RAM, no problem. For example,
|
||||
`mlr cat` of a DKVP file retains no data in memory from one line to another;
|
||||
`mlr cat` of a CSV file retains only the field names from the header line. The
|
||||
`stats1` and `stats2` commands retain only aggregation state (e.g. count and
|
||||
sum over specified fields needed to compute mean of specified fields). The `mlr
|
||||
tac` and `mlr sort` commands, obviously, need to consume and retain all input
|
||||
records before emitting any output records.
|
||||
|
||||
Miller classes are in general modular, following a constructor/destructor model
|
||||
with minimal dependencies between classes. As a general rule, void-star
|
||||
payloads (`sllv`, `lhmslv`) must be freed by the callee (which has access to
|
||||
the data type) whereas non-void-star payloads (`slls`, `hss`) are freed by the
|
||||
container class.
|
||||
|
||||
One complication is for free-flags in `lrec` and `slls`: the idea is that an
|
||||
entire line is mallocked and presented by the record reader; then individual
|
||||
fields are split out and populated into linked list or records. To reduce the
|
||||
amount of strduping there, free-flags are used to track which fields should be
|
||||
freed by the destructor and which are freed elsewhere.
|
||||
|
||||
The `header_keeper` object is an elaboration on this theme: suppose there is a
|
||||
CSV file with header line `a,b,c` and data lines `1,2,3`, then `4,5,6`, then
|
||||
`7,8,9`. Then the keys `a`, `b`, and `c` are shared between all three records;
|
||||
they are retained in a single `header_keeper` object.
|
||||
|
||||
A bigger complication to the otherwise modular nature of Miller is its
|
||||
*baton-passing memory-management model*. Namely, one class may be responsible
|
||||
for freeing memory allocated by another class.
|
||||
|
||||
For example, using `mlr cat`: The record-reader produces records and returns
|
||||
pointers to them. The record-mapper is just a pass-through; it returns the
|
||||
record-pointers it receives. The record-writer formats the records to stdout
|
||||
and does not return them, so it is responsible for freeing them.
|
||||
|
||||
Similarly, `mlr cut -x` and any other mappers which modify record objects
|
||||
without creating new ones. By contrast,`stats1` et al. produce their own
|
||||
records; they free what they do not pass on.
|
||||
|
||||
# Null-lrec conventions
|
||||
|
||||
Record-readers return a null lrec-pointer to signify end of input stream.
|
||||
|
||||
Each mapper takes an lrec-pointer as input and returns a linked list of
|
||||
lrec-pointer.
|
||||
|
||||
Null-lrec is input to mappers to signify end of stream: e.g. `sort` or `tac`
|
||||
should use this as a signal to deliver the sorted/reversed list of rows.
|
||||
|
||||
When a mapper has no output before end of stream (e.g. `sort` or `tac` while
|
||||
accumulating inputs) it returns a null lrec-pointer which is treated as
|
||||
synonymous with returning an empty list.
|
||||
|
||||
At end of stream, a mapper returns a linked list of records ending in a null
|
||||
lrec-pointer.
|
||||
|
||||
A null lrec-pointer at end of stream is passed to lrec writers so that they may
|
||||
produce final output (e.g. pretty-print which produces no output until end of
|
||||
stream).
|
||||
|
||||
# Performance optimizations
|
||||
|
||||
The initial implementation of Miller used `lhmss`
|
||||
(insertion-ordered string-to-string hash map) for record objects.
|
||||
Keys and values were strduped out of file-input lines. Each of the following
|
||||
produced from 5 to 30 percent performance gains:
|
||||
* The `lrec` object is a hashless map suited to low access-to-creation ratio.
|
||||
See detailed comments in
|
||||
https://github.com/johnkerl/miller/blob/master/c/containers/lrec.h.
|
||||
* Free-flags as discussed above removed additional occurrences of string copies.
|
||||
* Using `mmap` to read files gets rid of double passes on record parsing
|
||||
(one to find end of line, and another to separate fields) as well as most use
|
||||
of `malloc`. Note however that standard input cannot be mmapped, so both
|
||||
record-reader options are retained.
|
||||
|
||||
# Source-code indexing
|
||||
|
||||
Please see https://sourcegraph.com/github.com/johnkerl/miller
|
||||
4
c/asanmk
4
c/asanmk
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
export CC='clang -fsanitize=address'
|
||||
make -ef Makefile.no-autoconfig "$@"
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
noinst_LTLIBRARIES= libauxents.la
|
||||
libauxents_la_SOURCES= aux_entries.c \
|
||||
aux_entries.h
|
||||
|
||||
libauxents_la_LIBADD= ../lib/libmlr.la
|
||||
|
||||
AM_CPPFLAGS= -I${srcdir}/../
|
||||
AM_CFLAGS= -std=gnu99
|
||||
|
|
@ -1,592 +0,0 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 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@
|
||||
subdir = c/auxents
|
||||
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 $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libauxents_la_DEPENDENCIES = ../lib/libmlr.la
|
||||
am_libauxents_la_OBJECTS = aux_entries.lo
|
||||
libauxents_la_OBJECTS = $(am_libauxents_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_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 = $(SHELL) $(top_srcdir)/autotools/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
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 = $(libauxents_la_SOURCES)
|
||||
DIST_SOURCES = $(libauxents_la_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
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 \
|
||||
$(top_srcdir)/autotools/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
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@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
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@
|
||||
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@
|
||||
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@
|
||||
noinst_LTLIBRARIES = libauxents.la
|
||||
libauxents_la_SOURCES = aux_entries.c \
|
||||
aux_entries.h
|
||||
|
||||
libauxents_la_LIBADD = ../lib/libmlr.la
|
||||
AM_CPPFLAGS = -I${srcdir}/../
|
||||
AM_CFLAGS = -std=gnu99
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .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) --gnu c/auxents/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu c/auxents/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__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
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-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}; \
|
||||
}
|
||||
|
||||
libauxents.la: $(libauxents_la_OBJECTS) $(libauxents_la_DEPENDENCIES) $(EXTRA_libauxents_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(libauxents_la_OBJECTS) $(libauxents_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aux_entries.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
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: $(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 $(LTLIBRARIES)
|
||||
installdirs:
|
||||
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-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-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-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 -rf ./$(DEPDIR)
|
||||
-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:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLTLIBRARIES 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-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
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# 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:
|
||||
|
|
@ -1,529 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlr_arch.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "lib/netbsd_strptime.h"
|
||||
#include "input/line_readers.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int aux_list_main(int argc, char** argv);
|
||||
static int lecat_main(int argc, char** argv);
|
||||
static int termcvt_main(int argc, char** argv);
|
||||
static int hex_main(int argc, char** argv);
|
||||
static int unhex_main(int argc, char** argv);
|
||||
static int netbsd_strptime_main(int argc, char** argv);
|
||||
|
||||
static int lecat_stream(FILE* input_stream, int do_color);
|
||||
static void hex_dump_fp(FILE *in_fp, FILE *out_fp, int do_raw);
|
||||
static void unhex_fp(FILE *in_fp, FILE *out_fp);
|
||||
|
||||
static void aux_list_usage(char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
static void lecat_usage(char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
static void termcvt_usage(char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
static void hex_usage(char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
static void unhex_usage(char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
static void netbsd_strptime_usage(char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef int aux_main_t(int argc, char**argv);
|
||||
typedef void aux_usage_t( char* argv0, char* argv1, FILE* o, int exit_code);
|
||||
typedef struct _aux_lookup_entry_t {
|
||||
char* name;
|
||||
aux_main_t* pmain;
|
||||
aux_usage_t* pusage;
|
||||
} aux_lookup_entry_t;
|
||||
|
||||
static aux_lookup_entry_t aux_lookup_table[] = {
|
||||
|
||||
{ "aux-list", aux_list_main, aux_list_usage },
|
||||
{ "lecat", lecat_main, lecat_usage },
|
||||
{ "termcvt", termcvt_main, termcvt_usage },
|
||||
{ "hex", hex_main, hex_usage },
|
||||
{ "unhex", unhex_main, unhex_usage },
|
||||
{ "netbsd-strptime", netbsd_strptime_main, netbsd_strptime_usage },
|
||||
|
||||
};
|
||||
|
||||
static int aux_lookup_table_size = sizeof(aux_lookup_table) / sizeof(aux_lookup_table[0]);
|
||||
|
||||
// ================================================================
|
||||
void do_aux_entries(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < aux_lookup_table_size; i++) {
|
||||
if (streq(argv[1], aux_lookup_table[i].name)) {
|
||||
exit(aux_lookup_table[i].pmain(argc, argv));
|
||||
}
|
||||
}
|
||||
// else return to mlrmain for the rest of Miller.
|
||||
}
|
||||
|
||||
void show_aux_entries(FILE* fp) {
|
||||
fprintf(fp, "Available subcommands:\n");
|
||||
for (int i = 0; i < aux_lookup_table_size; i++) {
|
||||
fprintf(fp, " %s\n", aux_lookup_table[i].name);
|
||||
}
|
||||
fprintf(fp, "For more information, please invoke %s {subcommand} --help\n", MLR_GLOBALS.bargv0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void aux_list_usage(char* argv0, char* argv1, FILE* o, int exit_code) {
|
||||
fprintf(o, "Usage: %s %s [options]\n", argv0, argv1);
|
||||
fprintf(o, "Options:\n");
|
||||
fprintf(o, "-h or --help: print this message\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
int aux_list_main(int argc, char** argv) {
|
||||
show_aux_entries(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lecat_usage(char* argv0, char* argv1, FILE* o, int exit_code) {
|
||||
fprintf(o, "Usage: %s %s [options] {zero or more file names}\n", argv0, argv1);
|
||||
fprintf(o, "Simply echoes input, but flags CR characters in red and LF characters in green.\n");
|
||||
fprintf(o, "If zero file names are supplied, standard input is read.\n");
|
||||
fprintf(o, "Options:\n");
|
||||
fprintf(o, "--mono: don't try to colorize the output\n");
|
||||
fprintf(o, "-h or --help: print this message\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static int lecat_main(int argc, char** argv) {
|
||||
int ok = 1;
|
||||
int do_color = TRUE;
|
||||
|
||||
if (argc >= 3) {
|
||||
if (streq(argv[2], "-h") || streq(argv[2], "--help")) {
|
||||
lecat_usage(argv[0], argv[1], stdout, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// 'mlr' and 'lecat' are already argv[0] and argv[1].
|
||||
int argb = 2;
|
||||
if (argc >= 3 && argv[argb][0] == '-') {
|
||||
if (streq(argv[argb], "--mono")) {
|
||||
do_color = FALSE;
|
||||
argb++;
|
||||
} else {
|
||||
fprintf(stderr, "%s %s: unrecognized option \"%s\".\n",
|
||||
argv[0], argv[1], argv[argb]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (argb == argc) {
|
||||
ok = ok && lecat_stream(stdin, do_color);
|
||||
} else {
|
||||
for (int argi = argb; argi < argc; argi++) {
|
||||
char* file_name = argv[argi];
|
||||
FILE* input_stream = fopen(file_name, "r");
|
||||
if (input_stream == NULL) {
|
||||
perror(file_name);
|
||||
exit(1);
|
||||
}
|
||||
ok = lecat_stream(input_stream, do_color);
|
||||
fclose(input_stream);
|
||||
}
|
||||
}
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
static int lecat_stream(FILE* input_stream, int do_color) {
|
||||
while (1) {
|
||||
int c = fgetc(input_stream);
|
||||
if (c == EOF)
|
||||
break;
|
||||
if (c == '\r') {
|
||||
if (do_color)
|
||||
printf("\033[31;01m"); // xterm red
|
||||
printf("[CR]");
|
||||
if (do_color)
|
||||
printf("\033[0m");
|
||||
} else if (c == '\n') {
|
||||
if (do_color)
|
||||
printf("\033[32;01m"); // xterm green
|
||||
printf("[LF]\n");
|
||||
if (do_color)
|
||||
printf("\033[0m");
|
||||
} else {
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
static int termcvt_stream(FILE* input_stream, FILE* output_stream, char* inend, char* outend) {
|
||||
size_t line_length = MLR_ALLOC_READ_LINE_INITIAL_SIZE;
|
||||
int inend_length = strlen(inend);
|
||||
while (1) {
|
||||
char* line = mlr_alloc_read_line_multiple_delimiter(input_stream, inend, inend_length, &line_length);
|
||||
if (line == NULL) {
|
||||
break;
|
||||
}
|
||||
fputs(line, output_stream);
|
||||
fputs(outend, output_stream);
|
||||
free(line);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void termcvt_usage(char* argv0, char* argv1, FILE* o, int exit_code) {
|
||||
fprintf(o, "Usage: %s %s [option] {zero or more file names}\n", argv0, argv1);
|
||||
fprintf(o, "Option (exactly one is required):\n");
|
||||
fprintf(o, "--cr2crlf\n");
|
||||
fprintf(o, "--lf2crlf\n");
|
||||
fprintf(o, "--crlf2cr\n");
|
||||
fprintf(o, "--crlf2lf\n");
|
||||
fprintf(o, "--cr2lf\n");
|
||||
fprintf(o, "--lf2cr\n");
|
||||
fprintf(o, "-I in-place processing (default is to write to stdout)\n");
|
||||
fprintf(o, "-h or --help: print this message\n");
|
||||
fprintf(o, "Zero file names means read from standard input.\n");
|
||||
fprintf(o, "Output is always to standard output; files are not written in-place.\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int termcvt_main(int argc, char** argv) {
|
||||
int ok = 1;
|
||||
char* inend = "\n";
|
||||
char* outend = "\n";
|
||||
int do_in_place = FALSE;
|
||||
|
||||
// argv[0] is 'mlr'
|
||||
// argv[1] is 'termcvt'
|
||||
// argv[2] is '--some-option'
|
||||
// argv[3] and above are filenames
|
||||
if (argc < 2)
|
||||
termcvt_usage(argv[0], argv[1], stderr, 1);
|
||||
int argi;
|
||||
for (argi = 2; argi < argc; argi++) {
|
||||
char* opt = argv[argi];
|
||||
|
||||
if (opt[0] != '-')
|
||||
break;
|
||||
|
||||
if (streq(opt, "-h") || streq(opt, "--help")) {
|
||||
termcvt_usage(argv[0], argv[1], stdout, 0);
|
||||
} else if (streq(opt, "-I")) {
|
||||
do_in_place = TRUE;
|
||||
} else if (streq(opt, "--cr2crlf")) {
|
||||
inend = "\r";
|
||||
outend = "\r\n";
|
||||
} else if (streq(opt, "--lf2crlf")) {
|
||||
inend = "\n";
|
||||
outend = "\r\n";
|
||||
} else if (streq(opt, "--crlf2cr")) {
|
||||
inend = "\r\n";
|
||||
outend = "\r";
|
||||
} else if (streq(opt, "--lf2cr")) {
|
||||
inend = "\n";
|
||||
outend = "\r";
|
||||
} else if (streq(opt, "--crlf2lf")) {
|
||||
inend = "\r\n";
|
||||
outend = "\n";
|
||||
} else if (streq(opt, "--cr2lf")) {
|
||||
inend = "\r";
|
||||
outend = "\n";
|
||||
} else {
|
||||
termcvt_usage(argv[0], argv[1], stdout, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int nfiles = argc - argi;
|
||||
if (nfiles == 0) {
|
||||
ok = ok && termcvt_stream(stdin, stdout, inend, outend);
|
||||
|
||||
} else if (do_in_place) {
|
||||
for (; argi < argc; argi++) {
|
||||
char* file_name = argv[argi];
|
||||
char* temp_name = alloc_suffixed_temp_file_name(file_name);
|
||||
FILE* input_stream = fopen(file_name, "r");
|
||||
FILE* output_stream = fopen(temp_name, "wb");
|
||||
|
||||
if (input_stream == NULL) {
|
||||
perror("fopen");
|
||||
fprintf(stderr, "%s: Could not open \"%s\" for read.\n",
|
||||
MLR_GLOBALS.bargv0, file_name);
|
||||
exit(1);
|
||||
}
|
||||
if (output_stream == NULL) {
|
||||
perror("fopen");
|
||||
fprintf(stderr, "%s: Could not open \"%s\" for write.\n",
|
||||
MLR_GLOBALS.bargv0, temp_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ok = termcvt_stream(input_stream, output_stream, inend, outend);
|
||||
|
||||
fclose(input_stream);
|
||||
fclose(output_stream);
|
||||
|
||||
int rc = rename(temp_name, file_name);
|
||||
if (rc != 0) {
|
||||
perror("rename");
|
||||
fprintf(stderr, "%s: Could not rename \"%s\" to \"%s\".\n",
|
||||
MLR_GLOBALS.bargv0, temp_name, file_name);
|
||||
exit(1);
|
||||
}
|
||||
free(temp_name);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (; argi < argc; argi++) {
|
||||
char* file_name = argv[argi];
|
||||
FILE* input_stream = fopen(file_name, "r");
|
||||
if (input_stream == NULL) {
|
||||
perror(file_name);
|
||||
exit(1);
|
||||
}
|
||||
ok = termcvt_stream(input_stream, stdout, inend, outend);
|
||||
fclose(input_stream);
|
||||
}
|
||||
|
||||
}
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Copyright (c) 1998 John Kerl.
|
||||
// ================================================================
|
||||
// This is a simple hex dump with hex offsets to the left, hex data in the
|
||||
// middle, and ASCII at the right. This is a subset of the functionality of
|
||||
// Unix od; I wrote it in my NT days.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// $ d2h $(jot 0 128) | unhex | hex
|
||||
// 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
|
||||
// 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
|
||||
// 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./|
|
||||
// 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?|
|
||||
// 00000040: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO|
|
||||
// 00000050: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_|
|
||||
// 00000060: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno|
|
||||
// 00000070: 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|
|
||||
// ================================================================
|
||||
|
||||
#define LINE_LENGTH_MAX 8192
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void hex_usage(char* argv0, char* argv1, FILE* o, int exit_code) {
|
||||
fprintf(o, "Usage: %s %s [options] {zero or more file names}\n", argv0, argv1);
|
||||
fprintf(o, "Simple hex-dump.\n");
|
||||
fprintf(o, "If zero file names are supplied, standard input is read.\n");
|
||||
fprintf(o, "Options:\n");
|
||||
fprintf(o, "-r: print only raw hex without leading offset indicators or trailing ASCII dump.\n");
|
||||
fprintf(o, "-h or --help: print this message\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 'mlr' and 'hex' are already argv[0] and argv[1].
|
||||
static int hex_main(int argc, char **argv) {
|
||||
char * filename;
|
||||
FILE * in_fp;
|
||||
FILE * out_fp;
|
||||
int do_raw = 0;
|
||||
int argi = 2;
|
||||
|
||||
if (argc >= 3) {
|
||||
if (streq(argv[2], "-r")) {
|
||||
do_raw = 1;
|
||||
argi++;
|
||||
} else if (streq(argv[2], "-h") || streq(argv[2], "--help")) {
|
||||
hex_usage(argv[0], argv[1], stdout, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int num_file_names = argc - argi;
|
||||
|
||||
if (num_file_names == 0) {
|
||||
#ifdef WINDOWS
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
#endif //WINDOWS
|
||||
hex_dump_fp(stdin, stdout, do_raw);
|
||||
} else {
|
||||
for ( ; argi < argc; argi++) {
|
||||
if (!do_raw) {
|
||||
if (num_file_names > 1)
|
||||
printf("%s:\n", argv[argi]);
|
||||
}
|
||||
filename = argv[argi];
|
||||
in_fp = fopen(filename, "rb");
|
||||
out_fp = stdout;
|
||||
if (in_fp == NULL) {
|
||||
fprintf(stderr, "Couldn't open \"%s\"; skipping.\n",
|
||||
filename);
|
||||
}
|
||||
else {
|
||||
hex_dump_fp(in_fp, out_fp, do_raw);
|
||||
fclose(in_fp);
|
||||
if (out_fp != stdout)
|
||||
fclose(out_fp);
|
||||
|
||||
}
|
||||
if (!do_raw) {
|
||||
if (num_file_names > 1)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void hex_dump_fp(FILE *in_fp, FILE *out_fp, int do_raw) {
|
||||
const int bytes_per_clump = 4;
|
||||
const int clumps_per_line = 4;
|
||||
const int buffer_size = bytes_per_clump * clumps_per_line;
|
||||
unsigned char buf[buffer_size];
|
||||
long num_bytes_read;
|
||||
long num_bytes_total = 0;
|
||||
int byteno;
|
||||
|
||||
while ((num_bytes_read=fread(buf, sizeof(unsigned char),
|
||||
buffer_size, in_fp)) > 0)
|
||||
{
|
||||
if (!do_raw) {
|
||||
printf("%08lx: ", num_bytes_total);
|
||||
}
|
||||
|
||||
for (byteno = 0; byteno < num_bytes_read; byteno++) {
|
||||
unsigned int temp = buf[byteno];
|
||||
printf("%02x ", temp);
|
||||
if ((byteno % bytes_per_clump) ==
|
||||
(bytes_per_clump - 1))
|
||||
{
|
||||
if ((byteno > 0) && (byteno < buffer_size-1))
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
for (byteno = num_bytes_read; byteno < buffer_size; byteno++) {
|
||||
printf(" ");
|
||||
if ((byteno % bytes_per_clump) ==
|
||||
(bytes_per_clump - 1))
|
||||
{
|
||||
if ((byteno > 0) && (byteno < buffer_size-1))
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
if (!do_raw) {
|
||||
printf("|");
|
||||
for (byteno = 0; byteno < num_bytes_read; byteno++) {
|
||||
unsigned char temp = buf[byteno];
|
||||
if (!isprint(temp))
|
||||
temp = '.';
|
||||
printf("%c", temp);
|
||||
}
|
||||
|
||||
printf("|");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
num_bytes_total += num_bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void unhex_usage(char* argv0, char* argv1, FILE* o, int exit_code) {
|
||||
fprintf(o, "Usage: %s %s [option] {zero or more file names}\n", argv0, argv1);
|
||||
fprintf(o, "Options:\n");
|
||||
fprintf(o, "-h or --help: print this message\n");
|
||||
fprintf(o, "Zero file names means read from standard input.\n");
|
||||
fprintf(o, "Output is always to standard output; files are not written in-place.\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int unhex_main(int argc, char ** argv) {
|
||||
// 'mlr' and 'unhex' are already argv[0] and argv[1].
|
||||
if (argc >= 3) {
|
||||
if (streq(argv[2], "-h") || streq(argv[2], "--help")) {
|
||||
unhex_usage(argv[0], argv[1], stdout, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int exit_code = 0;
|
||||
if (argc == 2) {
|
||||
unhex_fp(stdin, stdout);
|
||||
} else {
|
||||
for (int argi = 2; argi < argc; argi++) {
|
||||
char* filename = argv[argi];
|
||||
FILE* infp = fopen(filename, "rb");
|
||||
if (infp == NULL) {
|
||||
fprintf(stderr, "%s %s: Couldn't open \"%s\"; skipping.\n",
|
||||
argv[0], argv[1], filename);
|
||||
exit_code = 1;
|
||||
} else {
|
||||
unhex_fp(infp, stdout);
|
||||
fclose(infp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void unhex_fp(FILE *infp, FILE *outfp) {
|
||||
unsigned char byte;
|
||||
unsigned temp;
|
||||
int count;
|
||||
while ((count=fscanf(infp, "%x", &temp)) > 0) {
|
||||
byte = temp;
|
||||
fwrite (&byte, sizeof(byte), 1, outfp);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
static void netbsd_strptime_usage(char* argv0, char* argv1, FILE* o, int exit_code) {
|
||||
fprintf(o, "Usage: %s %s {string value} {format}\n", argv0, argv1);
|
||||
fprintf(o, "Standalone driver for replacement strptime for MSYS2.\n");
|
||||
fprintf(o, "Example string value: 2012-03-04T05:06:07Z\n");
|
||||
fprintf(o, "Example format: %%Y-%%m-%%dT%%H:%%M:%%SZ\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
#define MYBUFLEN 256
|
||||
static int netbsd_strptime_main(int argc, char **argv) {
|
||||
// 'mlr' and 'netbsd_strptime' are already argv[0] and argv[1].
|
||||
if (streq(argv[2], "-h") || streq(argv[2], "--help") || (argc != 4)) {
|
||||
netbsd_strptime_usage(argv[0], argv[1], stdout, 0);
|
||||
}
|
||||
|
||||
struct tm tm;
|
||||
char* strptime_input = argv[2];
|
||||
char* format = argv[3];
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
char* strptime_output = netbsd_strptime(strptime_input, format, &tm);
|
||||
if (strptime_output == NULL) {
|
||||
printf("Could not strptime(\"%s\", \"%s\").\n", strptime_input, format);
|
||||
} else {
|
||||
printf("strptime: %s ->\n", strptime_input);
|
||||
printf(" tm_sec = %d\n", tm.tm_sec);
|
||||
printf(" tm_min = %d\n", tm.tm_min);
|
||||
printf(" tm_hour = %d\n", tm.tm_hour);
|
||||
printf(" tm_mday = %d\n", tm.tm_mday);
|
||||
printf(" tm_mon = %d\n", tm.tm_mon);
|
||||
printf(" tm_year = %d\n", tm.tm_year);
|
||||
printf(" tm_wday = %d\n", tm.tm_wday);
|
||||
printf(" tm_yday = %d\n", tm.tm_yday);
|
||||
printf(" tm_isdst = %d\n", tm.tm_isdst);
|
||||
printf(" remainder = \"%s\"\n", strptime_output);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef AUX_ENTRIES_H
|
||||
#define AUX_ENTRIES_H
|
||||
|
||||
// Handles 'mlr lecat' and any other one-off tool things which don't go through the record-streaming logic.
|
||||
// If the argument after the basename (i.e. argv[1]) is recognized then this function doesn't return,
|
||||
// invoking the code for that argument instead and exiting.
|
||||
void do_aux_entries(int argc, char** argv);
|
||||
void show_aux_entries(FILE* fp);
|
||||
|
||||
#endif // AUX_ENTRIES_H
|
||||
11
c/camake
11
c/camake
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
export CCOPT="clang -fsanitize=address -std=gnu99 -I. -I.. -Wall -Werror -O3 -lm"
|
||||
export CCDEBUG="clang -fsanitize=address -std=gnu99 -I. -I.. -Wall -Werror -g -lm"
|
||||
|
||||
export DSLCC="clang"
|
||||
export DSLCFLAGS="-I.. -Wall -O2 -fsanitize=address"
|
||||
|
||||
make -e -f Makefile.no-autoconfig -C parsing clean
|
||||
make -e -f Makefile.no-autoconfig mlr mlrg
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
noinst_LTLIBRARIES= libcli.la
|
||||
libcli_la_SOURCES= \
|
||||
argparse.c \
|
||||
argparse.h \
|
||||
comment_handling.h \
|
||||
json_array_ingest.h \
|
||||
mlrcli.c \
|
||||
mlrcli.h \
|
||||
quoting.h
|
||||
|
||||
# TODO: causes circular dependency
|
||||
#noinst_PROGRAMS= ap
|
||||
#ap_CPPFLAGS= -D__AP_MAIN__ ${AM_CPPFLAGS}
|
||||
#ap_LDADD= ../containers/libcontainers.la ../lib/libmlr.la
|
||||
#ap_SOURCES= argparse.c
|
||||
|
||||
AM_CPPFLAGS= -I${srcdir}/../
|
||||
AM_CFLAGS= -std=gnu99
|
||||
|
|
@ -1,604 +0,0 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 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@
|
||||
subdir = c/cli
|
||||
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 $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libcli_la_LIBADD =
|
||||
am_libcli_la_OBJECTS = argparse.lo mlrcli.lo
|
||||
libcli_la_OBJECTS = $(am_libcli_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_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 = $(SHELL) $(top_srcdir)/autotools/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
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 = $(libcli_la_SOURCES)
|
||||
DIST_SOURCES = $(libcli_la_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
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 \
|
||||
$(top_srcdir)/autotools/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
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@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
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@
|
||||
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@
|
||||
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@
|
||||
noinst_LTLIBRARIES = libcli.la
|
||||
libcli_la_SOURCES = \
|
||||
argparse.c \
|
||||
argparse.h \
|
||||
comment_handling.h \
|
||||
json_array_ingest.h \
|
||||
mlrcli.c \
|
||||
mlrcli.h \
|
||||
quoting.h
|
||||
|
||||
|
||||
# TODO: causes circular dependency
|
||||
#noinst_PROGRAMS= ap
|
||||
#ap_CPPFLAGS= -D__AP_MAIN__ ${AM_CPPFLAGS}
|
||||
#ap_LDADD= ../containers/libcontainers.la ../lib/libmlr.la
|
||||
#ap_SOURCES= argparse.c
|
||||
AM_CPPFLAGS = -I${srcdir}/../
|
||||
AM_CFLAGS = -std=gnu99
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .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) --gnu c/cli/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu c/cli/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__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
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-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}; \
|
||||
}
|
||||
|
||||
libcli.la: $(libcli_la_OBJECTS) $(libcli_la_DEPENDENCIES) $(EXTRA_libcli_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(libcli_la_OBJECTS) $(libcli_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argparse.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mlrcli.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
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: $(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 $(LTLIBRARIES)
|
||||
installdirs:
|
||||
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-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-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-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 -rf ./$(DEPDIR)
|
||||
-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:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLTLIBRARIES 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-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
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# 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:
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Miller command-line interface
|
||||
|
||||
mlrcli.h/c bags up all command-line options
|
||||
|
||||
I use argparse.h/c in place of getopt in order not to depend on GNU-isms, yet,
|
||||
elsewhere in Miller I readily depend on GNU-isms such as getdelim().
|
||||
213
c/cli/argparse.c
213
c/cli/argparse.c
|
|
@ -1,213 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "cli/argparse.h"
|
||||
|
||||
// ================================================================
|
||||
typedef enum _ap_flag_t {
|
||||
AP_INT_VALUE_FLAG,
|
||||
AP_INT_FLAG,
|
||||
AP_LONG_LONG_FLAG,
|
||||
AP_DOUBLE_FLAG,
|
||||
AP_STRING_FLAG,
|
||||
AP_STRING_BUILD_LIST_FLAG,
|
||||
AP_STRING_LIST_FLAG,
|
||||
AP_STRING_ARRAY_FLAG
|
||||
} ap_flag_t;
|
||||
|
||||
typedef struct _ap_flag_def_t {
|
||||
char* flag_name;
|
||||
ap_flag_t type;
|
||||
int intval;
|
||||
void* pval;
|
||||
int count; // 1 for bool flags; 2 for the rest
|
||||
} ap_flag_def_t;
|
||||
|
||||
static ap_flag_def_t* ap_find(ap_state_t* pstate, char* flag_name) {
|
||||
for (sllve_t* pe = pstate->pflag_defs->phead; pe != NULL; pe = pe->pnext) {
|
||||
ap_flag_def_t* pdef = pe->pvvalue;
|
||||
if (streq(pdef->flag_name, flag_name))
|
||||
return pdef;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ap_flag_def_t* ap_flag_def_alloc(char* flag_name, ap_flag_t ap_type, int intval, void* pval, int count) {
|
||||
ap_flag_def_t* pdef = mlr_malloc_or_die(sizeof(ap_flag_def_t));
|
||||
pdef->flag_name = flag_name;
|
||||
pdef->type = ap_type;
|
||||
pdef->intval = intval;
|
||||
pdef->pval = pval;
|
||||
pdef->count = count;
|
||||
return pdef;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
ap_state_t* ap_alloc() {
|
||||
ap_state_t* pstate = mlr_malloc_or_die(sizeof(ap_state_t));
|
||||
pstate->pflag_defs = sllv_alloc();
|
||||
|
||||
return pstate;
|
||||
}
|
||||
|
||||
void ap_free(ap_state_t* pstate) {
|
||||
if (pstate == NULL)
|
||||
return;
|
||||
|
||||
for (sllve_t* pe = pstate->pflag_defs->phead; pe != NULL; pe = pe->pnext) {
|
||||
ap_flag_def_t* pdef = pe->pvvalue;
|
||||
|
||||
// Linked-lists are pointed to by mappers and freed by their free
|
||||
// methods. If any mappers miss on that contract, we can find out by
|
||||
// using valgrind --leak-check=full (e.g. reg_test/run --valgrind).
|
||||
//
|
||||
//if (pdef->type == AP_STRING_LIST_FLAG && pdef->pval != NULL) {
|
||||
// slls_t** pplist = pdef->pval;
|
||||
// slls_free(*pplist);
|
||||
//}
|
||||
|
||||
free(pdef);
|
||||
}
|
||||
sllv_free(pstate->pflag_defs);
|
||||
|
||||
free(pstate);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void ap_define_true_flag(ap_state_t* pstate, char* flag_name, int* pintval) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_VALUE_FLAG, TRUE, pintval, 1));
|
||||
}
|
||||
|
||||
void ap_define_false_flag(ap_state_t* pstate, char* flag_name, int* pintval) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_VALUE_FLAG, FALSE, pintval, 1));
|
||||
}
|
||||
|
||||
void ap_define_int_value_flag(ap_state_t* pstate, char* flag_name, int intval, int* pintval) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_VALUE_FLAG, intval, pintval, 1));
|
||||
}
|
||||
|
||||
void ap_define_int_flag(ap_state_t* pstate, char* flag_name, int* pintval) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_FLAG, 0, pintval, 2));
|
||||
}
|
||||
void ap_define_long_long_flag(ap_state_t* pstate, char* flag_name, long long* pintval) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_LONG_LONG_FLAG, 0, pintval, 2));
|
||||
}
|
||||
|
||||
void ap_define_float_flag(ap_state_t* pstate, char* flag_name, double* pdoubleval) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_DOUBLE_FLAG, 0, pdoubleval, 2));
|
||||
}
|
||||
|
||||
void ap_define_string_flag(ap_state_t* pstate, char* flag_name, char** pstring) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_FLAG, 0, pstring, 2));
|
||||
}
|
||||
|
||||
void ap_define_string_build_list_flag(ap_state_t* pstate, char* flag_name, slls_t** pplist) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_BUILD_LIST_FLAG, 0, pplist, 2));
|
||||
}
|
||||
|
||||
void ap_define_string_list_flag(ap_state_t* pstate, char* flag_name, slls_t** pplist) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_LIST_FLAG, 0, pplist, 2));
|
||||
}
|
||||
|
||||
void ap_define_string_array_flag(ap_state_t* pstate, char* flag_name, string_array_t** pparray) {
|
||||
sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_ARRAY_FLAG, 0, pparray, 2));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int ap_parse(ap_state_t* pstate, char* verb, int* pargi, int argc, char** argv) {
|
||||
return ap_parse_aux(pstate, verb, pargi, argc, argv, TRUE);
|
||||
}
|
||||
|
||||
int ap_parse_aux(ap_state_t* pstate, char* verb, int* pargi, int argc, char** argv,
|
||||
int error_on_unrecognized)
|
||||
{
|
||||
int argi = *pargi;
|
||||
int ok = TRUE;
|
||||
|
||||
while (argi < argc) {
|
||||
if (argv[argi][0] != '-' && argv[argi][0] != '+') {
|
||||
break;
|
||||
}
|
||||
if (streq(argv[argi], "-h") || streq(argv[argi], "--help")) {
|
||||
ok = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
ap_flag_def_t* pdef = ap_find(pstate, argv[argi]);
|
||||
if (pdef == NULL) {
|
||||
if (error_on_unrecognized)
|
||||
ok = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((argc-argi) < pdef->count) {
|
||||
fprintf(stderr, "%s %s: option %s requires an argument.\n",
|
||||
argv[0], verb, argv[argi]);
|
||||
fprintf(stderr, "\n");
|
||||
ok = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pdef->type == AP_INT_VALUE_FLAG) {
|
||||
*(int *)pdef->pval = pdef->intval;
|
||||
|
||||
} else if (pdef->type == AP_INT_FLAG) {
|
||||
if (sscanf(argv[argi+1], "%d", (int *)pdef->pval) != 1) {
|
||||
fprintf(stderr, "%s %s: couldn't parse \"%s\" after \"%s\" as integer.\n",
|
||||
argv[0], verb, argv[argi+1], argv[argi]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
} else if (pdef->type == AP_LONG_LONG_FLAG) {
|
||||
if (sscanf(argv[argi+1], "%lld", (long long *)pdef->pval) != 1) {
|
||||
fprintf(stderr, "%s %s: couldn't parse \"%s\" after \"%s\" as integer.\n",
|
||||
argv[0], verb, argv[argi+1], argv[argi]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
} else if (pdef->type == AP_DOUBLE_FLAG) {
|
||||
if (!mlr_try_float_from_string(argv[argi+1], (double *)pdef->pval)) {
|
||||
fprintf(stderr, "%s %s: couldn't parse \"%s\" after \"%s\" as double.\n",
|
||||
argv[0], verb, argv[argi+1], argv[argi]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
} else if (pdef->type == AP_STRING_FLAG) {
|
||||
char** pstring = pdef->pval;
|
||||
*pstring = argv[argi+1];
|
||||
pdef->pval = pstring;
|
||||
|
||||
} else if (pdef->type == AP_STRING_BUILD_LIST_FLAG) {
|
||||
slls_t** pplist = pdef->pval;
|
||||
if (*pplist == NULL) {
|
||||
*pplist = slls_alloc();
|
||||
}
|
||||
slls_append_no_free(*pplist, argv[argi+1]);
|
||||
pdef->pval = pplist;
|
||||
|
||||
} else if (pdef->type == AP_STRING_LIST_FLAG) {
|
||||
slls_t** pplist = pdef->pval;
|
||||
if (*pplist != NULL)
|
||||
slls_free(*pplist);
|
||||
*pplist = slls_from_line(argv[argi+1], ',', FALSE);
|
||||
pdef->pval = pplist;
|
||||
|
||||
} else if (pdef->type == AP_STRING_ARRAY_FLAG) {
|
||||
string_array_t** pparray = pdef->pval;
|
||||
if (*pparray != NULL)
|
||||
string_array_free(*pparray);
|
||||
*pparray = string_array_from_line(argv[argi+1], ',');
|
||||
pdef->pval = pparray;
|
||||
|
||||
} else {
|
||||
ok = FALSE;
|
||||
fprintf(stderr, "argparse.c: internal coding error: flag-def type %x not recognized.\n", pdef->type);
|
||||
fprintf(stderr, "\n");
|
||||
break;
|
||||
}
|
||||
|
||||
argi += pdef->count;
|
||||
}
|
||||
|
||||
*pargi = argi;
|
||||
return ok;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// ================================================================
|
||||
// Argument-parsing library, with non-getopt semantics.
|
||||
// ================================================================
|
||||
|
||||
#ifndef ARGPARSE_H
|
||||
#define ARGPARSE_H
|
||||
#include "containers/slls.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "lib/string_array.h"
|
||||
|
||||
typedef struct _ap_state_t {
|
||||
sllv_t* pflag_defs;
|
||||
} ap_state_t;
|
||||
|
||||
ap_state_t* ap_alloc();
|
||||
void ap_free(ap_state_t* pstate);
|
||||
|
||||
void ap_define_true_flag(ap_state_t* pstate, char* flag_name, int* pintval);
|
||||
void ap_define_false_flag(ap_state_t* pstate, char* flag_name, int* pintval);
|
||||
void ap_define_int_value_flag(ap_state_t* pstate, char* flag_name, int value, int* pintval);
|
||||
void ap_define_int_flag(ap_state_t* pstate, char* flag_name, int* pintval);
|
||||
void ap_define_long_long_flag(ap_state_t* pstate, char* flag_name, long long* pintval);
|
||||
void ap_define_float_flag(ap_state_t* pstate, char* flag_name, double* pdoubleval);
|
||||
void ap_define_string_flag(ap_state_t* pstate, char* flag_name, char** pstring);
|
||||
void ap_define_string_build_list_flag(ap_state_t* pstate, char* flag_name, slls_t** pplist);
|
||||
void ap_define_string_list_flag(ap_state_t* pstate, char* flag_name, slls_t** pplist);
|
||||
void ap_define_string_array_flag(ap_state_t* pstate, char* flag_name, string_array_t** pparray);
|
||||
|
||||
int ap_parse(ap_state_t* pstate, char* verb, int* pargi, int argc, char** argv);
|
||||
int ap_parse_aux(ap_state_t* pstate, char* verb, int* pargi, int argc, char** argv,
|
||||
int error_on_unrecognized);
|
||||
|
||||
#endif // ARGPARSE_H
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef COMMENT_HANDLING_H
|
||||
#define COMMENT_HANDLING_H
|
||||
|
||||
typedef enum _comment_handling_t {
|
||||
PASS_COMMENTS,
|
||||
SKIP_COMMENTS,
|
||||
COMMENTS_ARE_DATA,
|
||||
} comment_handling_t;
|
||||
|
||||
#endif // COMMENT_HANDLING_H
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef JSON_ARRAY_INGEST_H
|
||||
#define JSON_ARRAY_INGEST_H
|
||||
|
||||
typedef enum _json_array_ingest_t {
|
||||
JSON_ARRAY_INGEST_UNSPECIFIED,
|
||||
JSON_ARRAY_INGEST_FATAL,
|
||||
JSON_ARRAY_INGEST_SKIP,
|
||||
JSON_ARRAY_INGEST_AS_MAP,
|
||||
} json_array_ingest_t;
|
||||
|
||||
#endif // JSON_ARRAY_INGEST_H
|
||||
2480
c/cli/mlrcli.c
2480
c/cli/mlrcli.c
File diff suppressed because it is too large
Load diff
139
c/cli/mlrcli.h
139
c/cli/mlrcli.h
|
|
@ -1,139 +0,0 @@
|
|||
// ================================================================
|
||||
// Miller command-line parsing
|
||||
// ================================================================
|
||||
|
||||
#ifndef MLRCLI_H
|
||||
#define MLRCLI_H
|
||||
|
||||
#include "lib/context.h"
|
||||
#include "containers/slls.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "cli/quoting.h"
|
||||
#include "cli/comment_handling.h"
|
||||
#include "cli/json_array_ingest.h"
|
||||
#include "containers/lhmsll.h"
|
||||
#include "containers/lhmss.h"
|
||||
#include <unistd.h>
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _generator_opts_t {
|
||||
char* field_name;
|
||||
// xxx to do: convert to mv_t
|
||||
long long start;
|
||||
long long stop;
|
||||
long long step;
|
||||
} generator_opts_t;
|
||||
|
||||
typedef struct _cli_reader_opts_t {
|
||||
|
||||
char* ifile_fmt;
|
||||
char* irs;
|
||||
char* ifs;
|
||||
char* ips;
|
||||
char* input_json_flatten_separator;
|
||||
json_array_ingest_t json_array_ingest;
|
||||
|
||||
int allow_repeat_ifs;
|
||||
int allow_repeat_ips;
|
||||
int use_implicit_csv_header;
|
||||
int allow_ragged_csv_input;
|
||||
|
||||
// Command for popen on input, e.g. "zcat -cf <". Can be null in which case
|
||||
// files are read directly rather than through a pipe.
|
||||
char* prepipe;
|
||||
|
||||
comment_handling_t comment_handling;
|
||||
char* comment_string;
|
||||
|
||||
// Fake internal-data-generator 'reader'
|
||||
generator_opts_t generator_opts;
|
||||
|
||||
} cli_reader_opts_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _cli_writer_opts_t {
|
||||
|
||||
char* ofile_fmt;
|
||||
char* ors;
|
||||
char* ofs;
|
||||
char* ops;
|
||||
|
||||
int headerless_csv_output;
|
||||
int right_justify_xtab_value;
|
||||
int right_align_pprint;
|
||||
int pprint_barred;
|
||||
int stack_json_output_vertically;
|
||||
int wrap_json_output_in_outer_list;
|
||||
int json_quote_int_keys;
|
||||
int json_quote_non_string_values;
|
||||
char* output_json_flatten_separator;
|
||||
char* oosvar_flatten_separator;
|
||||
|
||||
quoting_t oquoting;
|
||||
|
||||
} cli_writer_opts_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _cli_opts_t {
|
||||
cli_reader_opts_t reader_opts;
|
||||
cli_writer_opts_t writer_opts;
|
||||
|
||||
// These are used to construct the mapper list. In particular, for in-place mode
|
||||
// they're reconstructed for each file. We make copies since each pass through a
|
||||
// CLI-parser operates destructively, principally by running strtok over
|
||||
// comma-delimited field-name lists.
|
||||
|
||||
char** original_argv;
|
||||
char** non_in_place_argv;
|
||||
int argc;
|
||||
int mapper_argb;
|
||||
|
||||
slls_t* filenames;
|
||||
|
||||
char* ofmt;
|
||||
long long nr_progress_mod;
|
||||
|
||||
int do_in_place;
|
||||
|
||||
int no_input;
|
||||
int have_rand_seed;
|
||||
unsigned rand_seed;
|
||||
|
||||
} cli_opts_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
cli_opts_t* parse_command_line(int argc, char** argv, sllv_t** ppmapper_list);
|
||||
|
||||
// See stream.c. The idea is that the mapper-chain is constructed once for normal stream-over-all-files
|
||||
// mode, but per-file for in-place mode.
|
||||
sllv_t* cli_parse_mappers(char** argv, int* pargi, int argc, cli_opts_t* popts);
|
||||
|
||||
int cli_handle_reader_options(char** argv, int argc, int *pargi, cli_reader_opts_t* preader_opts);
|
||||
int cli_handle_writer_options(char** argv, int argc, int *pargi, cli_writer_opts_t* pwriter_opts);
|
||||
int cli_handle_reader_writer_options(char** argv, int argc, int *pargi,
|
||||
cli_reader_opts_t* preader_opts, cli_writer_opts_t* pwriter_opts);
|
||||
|
||||
void cli_opts_init(cli_opts_t* popts);
|
||||
void cli_reader_opts_init(cli_reader_opts_t* preader_opts);
|
||||
void cli_writer_opts_init(cli_writer_opts_t* pwriter_opts);
|
||||
|
||||
void cli_apply_defaults(cli_opts_t* popts);
|
||||
void cli_apply_reader_defaults(cli_reader_opts_t* preader_opts);
|
||||
void cli_apply_writer_defaults(cli_writer_opts_t* pwriter_opts);
|
||||
|
||||
// For mapper join which has its separate input-format overrides:
|
||||
void cli_merge_reader_opts(cli_reader_opts_t* pfunc_opts, cli_reader_opts_t* pmain_opts);
|
||||
|
||||
// For mapper tee & mapper put which have their separate output-format overrides:
|
||||
void cli_merge_writer_opts(cli_writer_opts_t* pfunc_opts, cli_writer_opts_t* pmain_opts);
|
||||
|
||||
// Stream context is for lrec-writer drain on tee et al. when using aggregated
|
||||
// output. E.g. pretty-print output has column widths which are only computable
|
||||
// after all output records have been retained. The free methods are used as
|
||||
// drain triggers.
|
||||
void cli_opts_free(cli_opts_t* popts);
|
||||
|
||||
// The caller can unconditionally free the return value
|
||||
char* cli_sep_from_arg(char* arg);
|
||||
|
||||
#endif // MLRCLI_H
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef QUOTING_H
|
||||
#define QUOTING_H
|
||||
|
||||
typedef enum _quoting_t {
|
||||
QUOTE_ALL,
|
||||
QUOTE_NONE,
|
||||
QUOTE_MINIMAL,
|
||||
QUOTE_NUMERIC,
|
||||
QUOTE_ORIGINAL,
|
||||
QUOTE_UNSPECIFIED,
|
||||
} quoting_t;
|
||||
|
||||
#endif // QUOTING_H
|
||||
12
c/cmake
12
c/cmake
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
export CCOPT="clang -std=gnu99 -I. -I.. -Wall -Werror -O3 -lm"
|
||||
export CCDEBUG="clang -std=gnu99 -I. -I.. -Wall -Werror -g -lm"
|
||||
|
||||
export DSLCC="clang"
|
||||
#export DSLCFLAGS="-I.. -Wall -O2"
|
||||
export DSLCFLAGS="-I.. -Wall -O2 -g"
|
||||
|
||||
make -e -f Makefile.no-autoconfig -C parsing clean
|
||||
make -e -f Makefile.no-autoconfig mlr mlrg
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
noinst_LTLIBRARIES= libcontainers.la
|
||||
libcontainers_la_SOURCES= \
|
||||
boxed_xval.h \
|
||||
dheap.c \
|
||||
dheap.h \
|
||||
dvector.c \
|
||||
dvector.h \
|
||||
header_keeper.c \
|
||||
header_keeper.h \
|
||||
hss.c \
|
||||
hss.h \
|
||||
join_bucket_keeper.c \
|
||||
join_bucket_keeper.h \
|
||||
lhms2v.c \
|
||||
lhms2v.h \
|
||||
lhmsi.c \
|
||||
lhmsi.h \
|
||||
lhmsll.c \
|
||||
lhmsll.h \
|
||||
lhmslv.c \
|
||||
lhmslv.h \
|
||||
lhmsmv.c \
|
||||
lhmsmv.h \
|
||||
lhmss.c \
|
||||
lhmss.h \
|
||||
lhmsv.c \
|
||||
lhmsv.h \
|
||||
local_stack.c \
|
||||
local_stack.h \
|
||||
loop_stack.c \
|
||||
loop_stack.h \
|
||||
lrec.c \
|
||||
lrec.h \
|
||||
mixutil.c \
|
||||
mixutil.h \
|
||||
mlhmmv.c \
|
||||
mlhmmv.h \
|
||||
parse_trie.c \
|
||||
parse_trie.h \
|
||||
percentile_keeper.c \
|
||||
percentile_keeper.h \
|
||||
rslls.c \
|
||||
rslls.h \
|
||||
sllmv.c \
|
||||
sllmv.h \
|
||||
slls.c \
|
||||
slls.h \
|
||||
sllv.c \
|
||||
sllv.h \
|
||||
top_keeper.c \
|
||||
top_keeper.h \
|
||||
type_decl.c \
|
||||
type_decl.h \
|
||||
xvfuncs.c \
|
||||
xvfuncs.h
|
||||
|
||||
libcontainers_la_LIBADD= \
|
||||
../lib/libmlr.la \
|
||||
../mapping/libmapping.la
|
||||
|
||||
AM_CPPFLAGS= -I${srcdir}/../
|
||||
AM_CFLAGS= -std=gnu99
|
||||
|
|
@ -1,678 +0,0 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 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@
|
||||
subdir = c/containers
|
||||
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 $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libcontainers_la_DEPENDENCIES = ../lib/libmlr.la \
|
||||
../mapping/libmapping.la
|
||||
am_libcontainers_la_OBJECTS = dheap.lo dvector.lo header_keeper.lo \
|
||||
hss.lo join_bucket_keeper.lo lhms2v.lo lhmsi.lo lhmsll.lo \
|
||||
lhmslv.lo lhmsmv.lo lhmss.lo lhmsv.lo local_stack.lo \
|
||||
loop_stack.lo lrec.lo mixutil.lo mlhmmv.lo parse_trie.lo \
|
||||
percentile_keeper.lo rslls.lo sllmv.lo slls.lo sllv.lo \
|
||||
top_keeper.lo type_decl.lo xvfuncs.lo
|
||||
libcontainers_la_OBJECTS = $(am_libcontainers_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_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 = $(SHELL) $(top_srcdir)/autotools/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
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 = $(libcontainers_la_SOURCES)
|
||||
DIST_SOURCES = $(libcontainers_la_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
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 \
|
||||
$(top_srcdir)/autotools/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
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@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
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@
|
||||
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@
|
||||
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@
|
||||
noinst_LTLIBRARIES = libcontainers.la
|
||||
libcontainers_la_SOURCES = \
|
||||
boxed_xval.h \
|
||||
dheap.c \
|
||||
dheap.h \
|
||||
dvector.c \
|
||||
dvector.h \
|
||||
header_keeper.c \
|
||||
header_keeper.h \
|
||||
hss.c \
|
||||
hss.h \
|
||||
join_bucket_keeper.c \
|
||||
join_bucket_keeper.h \
|
||||
lhms2v.c \
|
||||
lhms2v.h \
|
||||
lhmsi.c \
|
||||
lhmsi.h \
|
||||
lhmsll.c \
|
||||
lhmsll.h \
|
||||
lhmslv.c \
|
||||
lhmslv.h \
|
||||
lhmsmv.c \
|
||||
lhmsmv.h \
|
||||
lhmss.c \
|
||||
lhmss.h \
|
||||
lhmsv.c \
|
||||
lhmsv.h \
|
||||
local_stack.c \
|
||||
local_stack.h \
|
||||
loop_stack.c \
|
||||
loop_stack.h \
|
||||
lrec.c \
|
||||
lrec.h \
|
||||
mixutil.c \
|
||||
mixutil.h \
|
||||
mlhmmv.c \
|
||||
mlhmmv.h \
|
||||
parse_trie.c \
|
||||
parse_trie.h \
|
||||
percentile_keeper.c \
|
||||
percentile_keeper.h \
|
||||
rslls.c \
|
||||
rslls.h \
|
||||
sllmv.c \
|
||||
sllmv.h \
|
||||
slls.c \
|
||||
slls.h \
|
||||
sllv.c \
|
||||
sllv.h \
|
||||
top_keeper.c \
|
||||
top_keeper.h \
|
||||
type_decl.c \
|
||||
type_decl.h \
|
||||
xvfuncs.c \
|
||||
xvfuncs.h
|
||||
|
||||
libcontainers_la_LIBADD = \
|
||||
../lib/libmlr.la \
|
||||
../mapping/libmapping.la
|
||||
|
||||
AM_CPPFLAGS = -I${srcdir}/../
|
||||
AM_CFLAGS = -std=gnu99
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .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) --gnu c/containers/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu c/containers/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__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
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-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}; \
|
||||
}
|
||||
|
||||
libcontainers.la: $(libcontainers_la_OBJECTS) $(libcontainers_la_DEPENDENCIES) $(EXTRA_libcontainers_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(libcontainers_la_OBJECTS) $(libcontainers_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dheap.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvector.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header_keeper.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hss.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/join_bucket_keeper.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhms2v.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhmsi.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhmsll.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhmslv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhmsmv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhmss.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lhmsv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_stack.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_stack.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lrec.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixutil.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mlhmmv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_trie.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/percentile_keeper.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rslls.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sllmv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slls.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sllv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/top_keeper.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/type_decl.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvfuncs.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
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: $(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 $(LTLIBRARIES)
|
||||
installdirs:
|
||||
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-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-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-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 -rf ./$(DEPDIR)
|
||||
-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:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLTLIBRARIES 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-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
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# 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:
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Miller containers
|
||||
|
||||
These are generally very standard and simple programming-exercise kinds of
|
||||
things. There is some duplication of simple hash-map logic by key and value
|
||||
types: this is plain C with no templates or generics and I didn't want to do
|
||||
preprocessor tricks to reduce line count at the expense of code clarity.
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// ================================================================
|
||||
// This is for map-valued contexts: LHS/RHS of assignments,
|
||||
// UDF/subroutine arguments, and UDF return values.
|
||||
|
||||
// The is_ephemeral flag is TRUE for map-literals, function return values, and
|
||||
// data copied out of srecs. It is FALSE when the pointer is into an existing
|
||||
// data structure's memory (e.g. oosvars or locals).
|
||||
// ================================================================
|
||||
|
||||
#ifndef BOXED_XVAL_H
|
||||
#define BOXED_XVAL_H
|
||||
|
||||
#include "../lib/mlrval.h"
|
||||
#include "../containers/mlhmmv.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _boxed_xval_t {
|
||||
mlhmmv_xvalue_t xval;
|
||||
char is_ephemeral;
|
||||
} boxed_xval_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline boxed_xval_t box_ephemeral_val(mv_t val) {
|
||||
return (boxed_xval_t) {
|
||||
.xval = mlhmmv_xvalue_wrap_terminal(val),
|
||||
.is_ephemeral = TRUE,
|
||||
};
|
||||
}
|
||||
|
||||
static inline boxed_xval_t box_non_ephemeral_val(mv_t val) {
|
||||
return (boxed_xval_t) {
|
||||
.xval = mlhmmv_xvalue_wrap_terminal(val),
|
||||
.is_ephemeral = FALSE,
|
||||
};
|
||||
}
|
||||
|
||||
static inline boxed_xval_t box_ephemeral_xval(mlhmmv_xvalue_t xval) {
|
||||
return (boxed_xval_t) {
|
||||
.xval = xval,
|
||||
.is_ephemeral = TRUE,
|
||||
};
|
||||
}
|
||||
|
||||
static inline boxed_xval_t box_non_ephemeral_xval(mlhmmv_xvalue_t xval) {
|
||||
return (boxed_xval_t) {
|
||||
.xval = xval,
|
||||
.is_ephemeral = FALSE,
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BOXED_XVAL_H
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
// ================================================================
|
||||
// Zero-indexed max-heap of double.
|
||||
// John Kerl
|
||||
// 2012-06-02
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "containers/dheap.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 1-up: left child 2*i
|
||||
// right child 2*i+1
|
||||
// parent i/2
|
||||
// 0-up: left child 2*i+1
|
||||
// right child 2*i+2
|
||||
// parent (i-1)/2
|
||||
// Why: Example of 1-up i=10 l=20 r=21; 0-up i=9 l=19 r=20.
|
||||
// Or: 0-up i |-> 1-up i+1 |-> 1-up 2*i+2 |-> 0-up 2*i+1.
|
||||
// And likewise for right child & parent.
|
||||
|
||||
static inline int dheap_left_child_index(int i, int n)
|
||||
{
|
||||
int li = 2*i+1;
|
||||
if (li >= n)
|
||||
return -1;
|
||||
else
|
||||
return li;
|
||||
}
|
||||
|
||||
static inline int dheap_right_child_index(int i, int n)
|
||||
{
|
||||
int ri = 2*i+2;
|
||||
if (ri >= n)
|
||||
return -1;
|
||||
else
|
||||
return ri;
|
||||
}
|
||||
|
||||
static inline int dheap_parent_index(int i, int n)
|
||||
{
|
||||
if (i == 0)
|
||||
return -1;
|
||||
else
|
||||
return (i-1)/2;
|
||||
}
|
||||
|
||||
static inline void ptr_swap(double *pa, double *pb)
|
||||
{
|
||||
double temp = *pa;
|
||||
*pa = *pb;
|
||||
*pb = temp;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
dheap_t *dheap_alloc()
|
||||
{
|
||||
dheap_t *pdheap = mlr_malloc_or_die(sizeof(dheap_t));
|
||||
pdheap->n = 0;
|
||||
pdheap->alloc_size = DHEAP_INIT_ALLOC_SIZE;
|
||||
pdheap->elements = mlr_malloc_or_die(pdheap->alloc_size*sizeof(double));
|
||||
pdheap->is_malloced = 1;
|
||||
return pdheap;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
dheap_t *dheap_from_array(double *array, int n)
|
||||
{
|
||||
dheap_t *pdheap = mlr_malloc_or_die(sizeof(dheap_t));
|
||||
pdheap->n = 0;
|
||||
pdheap->alloc_size = n;
|
||||
pdheap->elements = array;
|
||||
pdheap->is_malloced = 0;
|
||||
return pdheap;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void dheap_free(dheap_t *pdheap)
|
||||
{
|
||||
if (pdheap == NULL)
|
||||
return;
|
||||
if (pdheap->elements != NULL)
|
||||
if (pdheap->is_malloced)
|
||||
free(pdheap->elements);
|
||||
pdheap->n = 0;
|
||||
pdheap->alloc_size = 0;
|
||||
pdheap->elements = NULL;
|
||||
free(pdheap);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
static void dheap_print_aux(dheap_t *pdheap, int i, int depth)
|
||||
{
|
||||
if (i >= pdheap->n)
|
||||
return;
|
||||
int w;
|
||||
printf("[%04d] ", i);
|
||||
for (w = 0; w < depth; w++)
|
||||
printf(" ");
|
||||
printf("%.8lf\n", pdheap->elements[i]);
|
||||
int li = dheap_left_child_index (i, pdheap->n);
|
||||
int ri = dheap_right_child_index(i, pdheap->n);
|
||||
if (li != -1)
|
||||
dheap_print_aux(pdheap, li, depth+1);
|
||||
if (ri != -1)
|
||||
dheap_print_aux(pdheap, ri, depth+1);
|
||||
}
|
||||
|
||||
void dheap_print(dheap_t *pdheap)
|
||||
{
|
||||
printf("BEGIN DHEAP (n=%d):\n", pdheap->n);
|
||||
dheap_print_aux(pdheap, 0, 0);
|
||||
printf("END DHEAP\n");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 1
|
||||
// 2 3
|
||||
// 4 5 6 7
|
||||
// 8 9 10 11 12 13 14 15
|
||||
|
||||
static int dheap_check_aux(dheap_t *pdheap, int i, char *file, int line)
|
||||
{
|
||||
int n = pdheap->n;
|
||||
double *pe = pdheap->elements;
|
||||
|
||||
if (i >= n)
|
||||
return TRUE;
|
||||
int li = dheap_left_child_index (i, pdheap->n);
|
||||
int ri = dheap_right_child_index(i, pdheap->n);
|
||||
if (li != -1) {
|
||||
if (pe[i] < pe[li]) {
|
||||
fprintf(stderr, "dheap check fail %s:%d pe[%d]=%lf < pe[%d]=%lf\n",
|
||||
file, line, i, pe[i], li, pe[li]);
|
||||
return FALSE;
|
||||
}
|
||||
dheap_check_aux(pdheap, li, file, line);
|
||||
}
|
||||
if (ri != -1) {
|
||||
if (pe[i] < pe[ri]) {
|
||||
fprintf(stderr, "dheap check fail %s:%d pe[%d]=%lf < pe[%d]=%lf\n",
|
||||
file, line, i, pe[i], ri, pe[ri]);
|
||||
return FALSE;
|
||||
}
|
||||
dheap_check_aux(pdheap, ri, file, line);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int dheap_check(dheap_t *pdheap, char *file, int line)
|
||||
{
|
||||
return dheap_check_aux(pdheap, 1, file, line);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void dheap_bubble_up(dheap_t *pdheap, int i)
|
||||
{
|
||||
int pi = dheap_parent_index(i, pdheap->n);
|
||||
if (pi == -1)
|
||||
return;
|
||||
double *pe = pdheap->elements;
|
||||
if (pe[pi] < pe[i]) {
|
||||
ptr_swap(&pe[pi], &pe[i]);
|
||||
dheap_bubble_up(pdheap, pi);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 1
|
||||
// 2 3
|
||||
// 4 5 6 7
|
||||
// 8 9 10 11 12 (n=13)
|
||||
|
||||
void dheap_add(dheap_t *pdheap, double v)
|
||||
{
|
||||
if (pdheap->n >= pdheap->alloc_size) {
|
||||
if (!pdheap->is_malloced) {
|
||||
fprintf(stderr, "extension of non-malloced dheap!\n");
|
||||
exit(1);
|
||||
}
|
||||
pdheap->alloc_size *= 2;
|
||||
pdheap->elements = (double *)mlr_realloc_or_die(pdheap->elements,
|
||||
pdheap->alloc_size*sizeof(double));
|
||||
}
|
||||
|
||||
pdheap->elements[pdheap->n++] = v;
|
||||
dheap_bubble_up(pdheap, pdheap->n-1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 1. Replace the root of the dheap with the last element on the last level.
|
||||
// 2. Compare the new root with its children; if they are in the correct order,
|
||||
// stop.
|
||||
// 3. If not, swap the element with one of its children and return to the
|
||||
// previous step. (Swap with its smaller child in a min-dheap and its larger
|
||||
// child in a max-dheap.)
|
||||
|
||||
static void dheap_bubble_down(dheap_t *pdheap, int i)
|
||||
{
|
||||
int li = dheap_left_child_index(i, pdheap->n);
|
||||
|
||||
if (li == -1) {
|
||||
// We add left to right, so this means left and right are both nil.
|
||||
return;
|
||||
}
|
||||
|
||||
int ri = dheap_right_child_index(i, pdheap->n);
|
||||
double *pe = pdheap->elements;
|
||||
|
||||
if (ri == -1) {
|
||||
// Right is nil, left is non-nil.
|
||||
if (pe[li] > pe[i]) {
|
||||
ptr_swap(&pe[li], &pe[i]);
|
||||
dheap_bubble_down(pdheap, li);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Now left and right are both non-nil.
|
||||
//
|
||||
// P 3
|
||||
// L R 9 7
|
||||
// a b c d 1 2 4 6
|
||||
//
|
||||
// Cases:
|
||||
double *L = &pe[li];
|
||||
double *P = &pe[i];
|
||||
double *R = &pe[ri];
|
||||
|
||||
if (*L <= *P) {
|
||||
if (*R <= *P) {
|
||||
// 1. L <= R <= P: done.
|
||||
// 2. R <= L <= P: done.
|
||||
return;
|
||||
}
|
||||
else if (*P <= *R) {
|
||||
// 3. L <= P <= R: swap P&R; bubble down R.
|
||||
ptr_swap(R, P);
|
||||
dheap_bubble_down(pdheap, ri);
|
||||
}
|
||||
}
|
||||
|
||||
else if (*R <= *P && *P <= *L) {
|
||||
// 4. R <= P <= L: swap P&L; bubble down L.
|
||||
ptr_swap(L, P);
|
||||
dheap_bubble_down(pdheap, li);
|
||||
}
|
||||
else if (*P <= *R && *R <= *L) {
|
||||
// 5. P <= R <= L: swap P&L; bubble down L.
|
||||
ptr_swap(L, P);
|
||||
dheap_bubble_down(pdheap, li);
|
||||
}
|
||||
else if (P <= L && L <= R) {
|
||||
// 6. P <= L <= R: swap P&R; bubble down R.
|
||||
ptr_swap(R, P);
|
||||
dheap_bubble_down(pdheap, ri);
|
||||
}
|
||||
}
|
||||
|
||||
double dheap_remove(dheap_t *pdheap)
|
||||
{
|
||||
if (pdheap->n <= 0) {
|
||||
fprintf(stderr, "remove from empty dheap!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
double rv = pdheap->elements[0];
|
||||
|
||||
pdheap->elements[0] = pdheap->elements[pdheap->n-1];
|
||||
pdheap->n--;
|
||||
dheap_bubble_down(pdheap, 0);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void dheap_sort(double *array, int n)
|
||||
{
|
||||
dheap_t *pdheap = dheap_from_array(array, n);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dheap_add(pdheap, pdheap->elements[i]);
|
||||
|
||||
for (i = n-1; i >= 0; i--)
|
||||
pdheap->elements[i] = dheap_remove(pdheap);
|
||||
|
||||
dheap_free(pdheap);
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// ================================================================
|
||||
// Zero-indexed max-heap of doubles.
|
||||
// John Kerl
|
||||
// 2012-06-02
|
||||
// ================================================================
|
||||
|
||||
#ifndef DHEAP_H
|
||||
#define DHEAP_H
|
||||
|
||||
#define DHEAP_INIT_ALLOC_SIZE 1024 // Power of two
|
||||
typedef struct _dheap_t {
|
||||
int n;
|
||||
int alloc_size;
|
||||
char is_malloced;
|
||||
double *elements;
|
||||
} dheap_t;
|
||||
|
||||
dheap_t *dheap_alloc();
|
||||
dheap_t *dheap_from_array(double *array, int n);
|
||||
void dheap_free(dheap_t *pheap);
|
||||
|
||||
void dheap_add(dheap_t *pdheap, double v);
|
||||
double dheap_remove(dheap_t *pdheap);
|
||||
|
||||
// For debug
|
||||
void dheap_print(dheap_t *pdheap);
|
||||
// For unit test
|
||||
int dheap_check(dheap_t *pdheap, char *file, int line);
|
||||
|
||||
#endif // DHEAP_H
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/dvector.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
dvector_t* dvector_alloc(unsigned long long initial_capacity) {
|
||||
unsigned long long capacity = initial_capacity;
|
||||
dvector_t* pdvector = mlr_malloc_or_die(sizeof(dvector_t));
|
||||
pdvector->data = mlr_malloc_or_die(capacity*sizeof(double));
|
||||
pdvector->size = 0;
|
||||
pdvector->capacity = capacity;
|
||||
return pdvector;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void dvector_free(dvector_t* pdvector) {
|
||||
if (pdvector == NULL)
|
||||
return;
|
||||
free(pdvector->data);
|
||||
pdvector->data = NULL;
|
||||
pdvector->size = 0;
|
||||
pdvector->capacity = 0;
|
||||
free(pdvector);
|
||||
}
|
||||
|
||||
void dvector_append(dvector_t* pdvector, double value) {
|
||||
if (pdvector->size >= pdvector->capacity) {
|
||||
pdvector->capacity = (unsigned long long)(pdvector->capacity * 2);
|
||||
pdvector->data = (double*)mlr_realloc_or_die(pdvector->data,
|
||||
pdvector->capacity*sizeof(double));
|
||||
}
|
||||
pdvector->data[pdvector->size++] = value;
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef DVECTOR_H
|
||||
#define DVECTOR_H
|
||||
|
||||
typedef struct _dvector_t {
|
||||
double* data;
|
||||
unsigned long long size;
|
||||
unsigned long long capacity;
|
||||
} dvector_t;
|
||||
|
||||
dvector_t* dvector_alloc(unsigned long long initial_capacity);
|
||||
void dvector_free(dvector_t* pdvector);
|
||||
void dvector_append(dvector_t* pdvector, double value);
|
||||
|
||||
#endif // DVECTOR_H
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/header_keeper.h"
|
||||
|
||||
header_keeper_t* header_keeper_alloc(char* line, slls_t* pkeys) {
|
||||
header_keeper_t* pheader_keeper = mlr_malloc_or_die(sizeof(header_keeper_t));
|
||||
pheader_keeper->line = line;
|
||||
pheader_keeper->pkeys = pkeys;
|
||||
|
||||
return pheader_keeper;
|
||||
}
|
||||
|
||||
void header_keeper_free(header_keeper_t* pheader_keeper) {
|
||||
if (pheader_keeper == NULL)
|
||||
return;
|
||||
free(pheader_keeper->line);
|
||||
slls_free(pheader_keeper->pkeys);
|
||||
free(pheader_keeper);
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// ================================================================
|
||||
// Retains field names from CSV header lines across record reads.
|
||||
// See also c/README.md.
|
||||
// ================================================================
|
||||
|
||||
#ifndef HEADER_KEEPER_H
|
||||
#define HEADER_KEEPER_H
|
||||
|
||||
#include "containers/slls.h"
|
||||
|
||||
typedef struct _header_keeper_t {
|
||||
char* line;
|
||||
slls_t* pkeys;
|
||||
} header_keeper_t;
|
||||
|
||||
header_keeper_t* header_keeper_alloc(char* line, slls_t* pkeys);
|
||||
void header_keeper_free(header_keeper_t* pheader_keeper);
|
||||
|
||||
#endif // HEADER_KEEPER_H
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-valued hash set with linear probing for
|
||||
// collisions.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/hss.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define INITIAL_ARRAY_LENGTH 128
|
||||
#define LOAD_FACTOR 0.7
|
||||
|
||||
#define OCCUPIED 444
|
||||
#define DELETED 555
|
||||
#define EMPTY 666
|
||||
|
||||
// ================================================================
|
||||
static void hsse_clear(hsse_t *pentry) {
|
||||
pentry->key = NULL;
|
||||
pentry->state = EMPTY;
|
||||
pentry->ideal_index = -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static hsse_t* hss_make_alloc_array(int length) {
|
||||
hsse_t* array = (hsse_t*)mlr_malloc_or_die(sizeof(hsse_t) * length);
|
||||
for (int i = 0; i < length; i++)
|
||||
hsse_clear(&array[i]);
|
||||
return array;
|
||||
}
|
||||
|
||||
static void hss_init(hss_t *pset, int length) {
|
||||
pset->num_occupied = 0;
|
||||
pset->num_freed = 0;
|
||||
pset->array_length = length;
|
||||
pset->array = hss_make_alloc_array(length);
|
||||
}
|
||||
|
||||
hss_t* hss_alloc() {
|
||||
hss_t* pset = mlr_malloc_or_die(sizeof(hss_t));
|
||||
hss_init(pset, INITIAL_ARRAY_LENGTH);
|
||||
return pset;
|
||||
}
|
||||
|
||||
void hss_free(hss_t* pset) {
|
||||
if (pset == NULL)
|
||||
return;
|
||||
free(pset->array);
|
||||
pset->array = NULL;
|
||||
pset->num_occupied = 0;
|
||||
pset->num_freed = 0;
|
||||
pset->array_length = 0;
|
||||
free(pset);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int hss_find_index_for_key(hss_t* pset, char* key, int* pideal_index) {
|
||||
int hash = mlr_string_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pset->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
hsse_t* pe = &pset->array[index];
|
||||
if (pe->state == OCCUPIED) {
|
||||
char* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (streq(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pe->state == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been freed, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pset->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pset->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void hss_enlarge(hss_t* pset);
|
||||
|
||||
void hss_add(hss_t* pset, char* key) {
|
||||
if ((pset->num_occupied + pset->num_freed) >= (pset->array_length*LOAD_FACTOR))
|
||||
hss_enlarge(pset);
|
||||
|
||||
int ideal_index = 0;
|
||||
int index = hss_find_index_for_key(pset, key, &ideal_index);
|
||||
hsse_t* pe = &pset->array[index];
|
||||
|
||||
if (pe->state == OCCUPIED) {
|
||||
// Existing key found in chain. Chaining already handled by hss_find_index_for_key.
|
||||
return;
|
||||
}
|
||||
else if (pe->state == EMPTY) {
|
||||
// End of chain.
|
||||
pe->key = key;
|
||||
pe->state = OCCUPIED;
|
||||
pe->ideal_index = ideal_index;
|
||||
pset->num_occupied++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "hss_find_index_for_key did not find end of chain.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void hss_enlarge(hss_t* pset) {
|
||||
int old_array_length = pset->array_length;
|
||||
hsse_t* old_array = pset->array;
|
||||
|
||||
hss_init(pset, pset->array_length*2);
|
||||
|
||||
for (int index = 0; index < old_array_length; index++) {
|
||||
hsse_t e = old_array[index];
|
||||
if (e.state == OCCUPIED)
|
||||
hss_add(pset, e.key);
|
||||
}
|
||||
|
||||
free(old_array);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int hss_has(hss_t* pset, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = hss_find_index_for_key(pset, key, &ideal_index);
|
||||
hsse_t* pe = &pset->array[index];
|
||||
|
||||
if (pe->state == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pe->state == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "hss_find_index_for_key did not find end of chain.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void hss_remove(hss_t* pset, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = hss_find_index_for_key(pset, key, &ideal_index);
|
||||
hsse_t* pe = &pset->array[index];
|
||||
if (pe->state == OCCUPIED) {
|
||||
pe->key = NULL;
|
||||
pe->state = DELETED;
|
||||
pe->ideal_index = -1;
|
||||
pset->num_freed++;
|
||||
pset->num_occupied--;
|
||||
}
|
||||
else if (pe->state == EMPTY) {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "hss_find_index_for_key did not find end of chain.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void hss_clear(hss_t* pset) {
|
||||
for (int i = 0; i < pset->array_length; i++) {
|
||||
hsse_clear(&pset->array[i]);
|
||||
}
|
||||
pset->num_occupied = 0;
|
||||
pset->num_freed = 0;
|
||||
}
|
||||
|
||||
int hss_size(hss_t* pset) {
|
||||
return pset->num_occupied;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int hss_check_counts(hss_t* pset) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pset->array_length; index++) {
|
||||
hsse_t* pe = &pset->array[index];
|
||||
if (pe->state == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pe->state == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pset->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d.\n",
|
||||
nocc, pset->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pset->num_freed) {
|
||||
fprintf(stderr,
|
||||
"freed-count mismatch: actual %d != cached %d.\n",
|
||||
ndel, pset->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "freed"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void hss_print(hss_t* pset) {
|
||||
for (int index = 0; index < pset->array_length; index++) {
|
||||
hsse_t* pe = &pset->array[index];
|
||||
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key: %12s |\n",
|
||||
get_state_name(pe->state), index, pe->ideal_index, key_string);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-valued hash set with linear probing for
|
||||
// collisions.
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef HSS_H
|
||||
#define HSS_H
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _hsse_t {
|
||||
char* key;
|
||||
int state;
|
||||
int ideal_index;
|
||||
} hsse_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _hss_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
hsse_t* array;
|
||||
} hss_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
hss_t* hss_alloc();
|
||||
void hss_free(hss_t* pset);
|
||||
void hss_add(hss_t* pset, char* key);
|
||||
int hss_has(hss_t* pset, char* key);
|
||||
void hss_remove(hss_t* pset, char* key);
|
||||
void hss_clear(hss_t* pset);
|
||||
int hss_size(hss_t* pset);
|
||||
|
||||
// Unit-test hook
|
||||
int hss_check_counts(hss_t* pset);
|
||||
|
||||
#endif // HSS_H
|
||||
|
|
@ -1,503 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/context.h"
|
||||
#include "containers/mixutil.h"
|
||||
#include "containers/join_bucket_keeper.h"
|
||||
#include "input/lrec_readers.h"
|
||||
|
||||
// ================================================================
|
||||
// JOIN_BUCKET_KEEPER
|
||||
//
|
||||
// This data structure supports Miller's sorted (double-streaming) join. It is
|
||||
// perhaps best explained by first comparing with the unsorted (half-streaming)
|
||||
// case.
|
||||
//
|
||||
// In both cases, we have left and right join keys. Suppose the left file has
|
||||
// data with field name "L" to be joined with right-file(s) data with field
|
||||
// name "R". For the unsorted case (see mapper_join.c) the entire left file is
|
||||
// first loaded into buckets of record-lists, one for each distinct value of L.
|
||||
// E.g. given the following:
|
||||
//
|
||||
// +-----+-----+
|
||||
// | L | R |
|
||||
// + --- + --- +
|
||||
// | a | a |
|
||||
// | c | b |
|
||||
// | a | f |
|
||||
// | b | |
|
||||
// | c | |
|
||||
// | d | |
|
||||
// | a | |
|
||||
// +-----+-----+
|
||||
//
|
||||
// the left file is bucketed as
|
||||
//
|
||||
// +-----+ +-----+ +-----+ +-----+
|
||||
// | L | | L | | L | | L |
|
||||
// + --- + + --- + + --- + + --- +
|
||||
// | a | | c | | b | | d |
|
||||
// | a | | c | +-----+ +-----+
|
||||
// | a | + --- +
|
||||
// + --- +
|
||||
//
|
||||
// Then the right file is processed one record at a time (hence
|
||||
// "half-streaming"). The pairings are easy:
|
||||
// * the right record with R=a is paired with the L=a bucket,
|
||||
// * the right record with R=b is paired with the L=b bucket,
|
||||
// * the right record with R=f is unpaired, and
|
||||
// * the left records with L=c and L=d are unpaired.
|
||||
//
|
||||
// ----------------------------------------------------------------
|
||||
// Now for the sorted (doubly-streaming) case. Here we require that the left
|
||||
// and right files be already sorted (lexically ascending) by the join fields.
|
||||
// Then the example inputs look like this:
|
||||
//
|
||||
// +-----+-----+
|
||||
// | L | R |
|
||||
// + --- + --- +
|
||||
// | a | a |
|
||||
// | a | b |
|
||||
// | a | f |
|
||||
// | b | |
|
||||
// | c | |
|
||||
// | c | |
|
||||
// | d | |
|
||||
// +-----+-----+
|
||||
//
|
||||
// The right file is still read one record at a time. It's the job of this
|
||||
// join_bucket_keeper class to keep track of the left-file buckets, one bucket
|
||||
// at a time. This includes all records with same values for the join
|
||||
// field(s), e.g. the three L=a records, as well as a "peek" record which is
|
||||
// either the next record with a different join value (e.g. the L=b record), or
|
||||
// an end-of-file indicator.
|
||||
//
|
||||
// If a right-file record has join field matching the current left-file bucket,
|
||||
// then it's paired with all records in that bucket. Otherwise the
|
||||
// join_bucket_keeper needs to either stay with the current bucket or advance
|
||||
// to the next one, depending whether the current right-file record's
|
||||
// join-field values compare lexically with the the left-file bucket's
|
||||
// join-field values.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// +-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
// | L R | L R | L R | L R | L R | L R |
|
||||
// + --- --- + --- --- + --- --- + --- --- + --- --- + --- --- +
|
||||
// | a | a | e | a | e e | e e |
|
||||
// | b | e | e | e e | e | e e |
|
||||
// | e | e | e | e | e | e |
|
||||
// | e | e | f | e | f | g g |
|
||||
// | e | f | g | g | g | g |
|
||||
// | g | g | g | g | g | |
|
||||
// | g | g | h | | | |
|
||||
// +-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
//
|
||||
// In all these examples, the join_bucket_keeper goes through these steps:
|
||||
// * bucket is empty, peek rec has L=e
|
||||
// * bucket is L=e records, peek rec has L=g
|
||||
// * bucket is L=g records, peek rec is null (due to EOF)
|
||||
// * bucket is empty, peek rec is null (due to EOF)
|
||||
//
|
||||
// Example 1:
|
||||
// * left-bucket is empty and left-peek has L=e
|
||||
// * right record has R=a; join_bucket_keeper does not advance
|
||||
// * right record has R=b; join_bucket_keeper does not advance
|
||||
// * right end of file; all left records are unpaired.
|
||||
//
|
||||
// Example 2:
|
||||
// * left-bucket is empty and left-peek has L=e
|
||||
// * right record has R=a; join_bucket_keeper does not advance
|
||||
// * right record has R=f; left records with L=e are unpaired.
|
||||
// * etc.
|
||||
//
|
||||
// ================================================================
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define LEFT_STATE_0_PREFILL 0
|
||||
#define LEFT_STATE_1_FULL 1
|
||||
#define LEFT_STATE_2_LAST_BUCKET 2
|
||||
#define LEFT_STATE_3_EOF 3
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// (0) pre-fill: Lv == null, peek == null, leof = false
|
||||
// (1) midstream: Lv != null, peek != null, leof = false
|
||||
// (2) last bucket: Lv != null, peek == null, leof = true
|
||||
// (3) leof: Lv == null, peek == null, leof = true
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// Private methods
|
||||
static int join_bucket_keeper_get_state(join_bucket_keeper_t* pkeeper);
|
||||
static void join_bucket_keeper_initial_fill(join_bucket_keeper_t* pkeeper,
|
||||
sllv_t** pprecords_left_unpaired);
|
||||
static void join_bucket_keeper_advance_to(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired);
|
||||
static void join_bucket_keeper_fill(join_bucket_keeper_t* pkeeper, sllv_t** pprecords_left_unpaired);
|
||||
static void join_bucket_keeper_drain(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired);
|
||||
static char* describe_state(int state);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
join_bucket_keeper_t* join_bucket_keeper_alloc(
|
||||
char* prepipe,
|
||||
char* left_file_name,
|
||||
cli_reader_opts_t* popts,
|
||||
slls_t* pleft_field_names
|
||||
) {
|
||||
lrec_reader_t* plrec_reader = lrec_reader_alloc(popts);
|
||||
return join_bucket_keeper_alloc_from_reader(plrec_reader, prepipe, left_file_name, pleft_field_names);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
join_bucket_keeper_t* join_bucket_keeper_alloc_from_reader(
|
||||
lrec_reader_t* plrec_reader,
|
||||
char* prepipe,
|
||||
char* left_file_name,
|
||||
slls_t* pleft_field_names)
|
||||
{
|
||||
join_bucket_keeper_t* pkeeper = mlr_malloc_or_die(sizeof(join_bucket_keeper_t));
|
||||
|
||||
void* pvhandle = plrec_reader->popen_func(plrec_reader->pvstate, prepipe, left_file_name);
|
||||
plrec_reader->psof_func(plrec_reader->pvstate, pvhandle);
|
||||
|
||||
context_t* pctx = mlr_malloc_or_die(sizeof(context_t));
|
||||
context_init_from_first_file_name(pctx, left_file_name);
|
||||
|
||||
pkeeper->plrec_reader = plrec_reader;
|
||||
pkeeper->pvhandle = pvhandle;
|
||||
pkeeper->pctx = pctx;
|
||||
|
||||
pkeeper->pleft_field_names = pleft_field_names;
|
||||
|
||||
pkeeper->pbucket = mlr_malloc_or_die(sizeof(join_bucket_t));
|
||||
pkeeper->pbucket->precords = sllv_alloc();
|
||||
pkeeper->pbucket->pleft_field_values = NULL;
|
||||
pkeeper->pbucket->was_paired = FALSE;
|
||||
|
||||
pkeeper->prec_peek = NULL;
|
||||
pkeeper->leof = FALSE;
|
||||
pkeeper->state = LEFT_STATE_0_PREFILL;
|
||||
|
||||
return pkeeper;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void join_bucket_keeper_free(join_bucket_keeper_t* pkeeper, char* prepipe) {
|
||||
if (pkeeper == NULL)
|
||||
return;
|
||||
slls_free(pkeeper->pbucket->pleft_field_values);
|
||||
sllv_free(pkeeper->pbucket->precords);
|
||||
free(pkeeper->pbucket);
|
||||
pkeeper->plrec_reader->pclose_func(pkeeper->plrec_reader->pvstate, pkeeper->pvhandle, prepipe);
|
||||
pkeeper->plrec_reader->pfree_func(pkeeper->plrec_reader);
|
||||
lrec_free(pkeeper->prec_peek);
|
||||
free(pkeeper->pctx);
|
||||
free(pkeeper);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void join_bucket_keeper_emit(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired)
|
||||
{
|
||||
*pprecords_paired = NULL;
|
||||
*pprecords_left_unpaired = NULL;
|
||||
|
||||
if (pkeeper->state == LEFT_STATE_0_PREFILL) {
|
||||
join_bucket_keeper_initial_fill(pkeeper, pprecords_left_unpaired);
|
||||
pkeeper->state = join_bucket_keeper_get_state(pkeeper);
|
||||
}
|
||||
|
||||
if (pright_field_values != NULL) { // Not right EOF
|
||||
if (pkeeper->state == LEFT_STATE_1_FULL || pkeeper->state == LEFT_STATE_2_LAST_BUCKET) {
|
||||
int cmp = slls_compare_lexically(pkeeper->pbucket->pleft_field_values, pright_field_values);
|
||||
if (cmp < 0) {
|
||||
// Advance left until match or left EOF.
|
||||
join_bucket_keeper_advance_to(pkeeper, pright_field_values, pprecords_paired, pprecords_left_unpaired);
|
||||
} else if (cmp == 0) {
|
||||
pkeeper->pbucket->was_paired = TRUE;
|
||||
*pprecords_paired = pkeeper->pbucket->precords;
|
||||
} else {
|
||||
// No match and no need to advance left; return null lists.
|
||||
}
|
||||
} else if (pkeeper->state != LEFT_STATE_3_EOF) {
|
||||
fprintf(stderr, "%s: internal coding error: failed transition from prefill state.\n",
|
||||
MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
} else { // Right EOF: return the final left-unpaireds.
|
||||
join_bucket_keeper_drain(pkeeper, pright_field_values, pprecords_paired, pprecords_left_unpaired);
|
||||
}
|
||||
|
||||
pkeeper->state = join_bucket_keeper_get_state(pkeeper);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int join_bucket_keeper_get_state(join_bucket_keeper_t* pkeeper) {
|
||||
if (pkeeper->pbucket->pleft_field_values == NULL) {
|
||||
if (pkeeper->leof)
|
||||
return LEFT_STATE_3_EOF;
|
||||
else
|
||||
return LEFT_STATE_0_PREFILL;
|
||||
} else {
|
||||
if (pkeeper->prec_peek == NULL)
|
||||
return LEFT_STATE_2_LAST_BUCKET;
|
||||
else
|
||||
return LEFT_STATE_1_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void join_bucket_keeper_initial_fill(join_bucket_keeper_t* pkeeper,
|
||||
sllv_t** pprecords_left_unpaired)
|
||||
{
|
||||
while (TRUE) {
|
||||
// Skip over records not having the join keys. These go straight to the
|
||||
// left-unpaired list.
|
||||
pkeeper->prec_peek = pkeeper->plrec_reader->pprocess_func(pkeeper->plrec_reader->pvstate,
|
||||
pkeeper->pvhandle, pkeeper->pctx);
|
||||
if (pkeeper->prec_peek == NULL) {
|
||||
break;
|
||||
}
|
||||
if (record_has_all_keys(pkeeper->prec_peek, pkeeper->pleft_field_names)) {
|
||||
break;
|
||||
} else {
|
||||
if (*pprecords_left_unpaired == NULL)
|
||||
*pprecords_left_unpaired = sllv_alloc();
|
||||
sllv_append(*pprecords_left_unpaired, pkeeper->prec_peek);
|
||||
}
|
||||
}
|
||||
|
||||
if (pkeeper->prec_peek == NULL) {
|
||||
pkeeper->leof = TRUE;
|
||||
return;
|
||||
}
|
||||
join_bucket_keeper_fill(pkeeper, pprecords_left_unpaired);
|
||||
}
|
||||
|
||||
// Preconditions:
|
||||
// * prec_peek != NULL
|
||||
// * prec_peek has the join keys
|
||||
static void join_bucket_keeper_fill(join_bucket_keeper_t* pkeeper, sllv_t** pprecords_left_unpaired) {
|
||||
slls_t* pleft_field_values = mlr_reference_selected_values_from_record(pkeeper->prec_peek,
|
||||
pkeeper->pleft_field_names);
|
||||
if (pleft_field_values == NULL) {
|
||||
fprintf(stderr, "%s: internal coding error: peek record should have had join keys.\n",
|
||||
MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pkeeper->pbucket->pleft_field_values = slls_copy(pleft_field_values);
|
||||
slls_free(pleft_field_values);
|
||||
sllv_append(pkeeper->pbucket->precords, pkeeper->prec_peek);
|
||||
pkeeper->pbucket->was_paired = FALSE;
|
||||
pkeeper->prec_peek = NULL;
|
||||
while (TRUE) {
|
||||
// Skip over records not having the join keys. These go straight to the
|
||||
// left-unpaired list.
|
||||
pkeeper->prec_peek = pkeeper->plrec_reader->pprocess_func(pkeeper->plrec_reader->pvstate,
|
||||
pkeeper->pvhandle, pkeeper->pctx);
|
||||
if (pkeeper->prec_peek == NULL) {
|
||||
pkeeper->leof = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (record_has_all_keys(pkeeper->prec_peek, pkeeper->pleft_field_names)) {
|
||||
int cmp = slls_lrec_compare_lexically(
|
||||
pkeeper->pbucket->pleft_field_values,
|
||||
pkeeper->prec_peek,
|
||||
pkeeper->pleft_field_names);
|
||||
if (cmp != 0) {
|
||||
break;
|
||||
}
|
||||
sllv_append(pkeeper->pbucket->precords, pkeeper->prec_peek);
|
||||
|
||||
} else {
|
||||
if (*pprecords_left_unpaired == NULL)
|
||||
*pprecords_left_unpaired = sllv_alloc();
|
||||
sllv_append(*pprecords_left_unpaired, pkeeper->prec_peek);
|
||||
}
|
||||
pkeeper->prec_peek = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-conditions:
|
||||
// * pkeeper->pleft_field_values < pright_field_values.
|
||||
// * currently in state 1 or 2 so there is a bucket but there may or may not be a peek-record
|
||||
// * current bucket was/wasn't paired on previous emits but is not paired on this emit.
|
||||
// Actions:
|
||||
// * if bucket was never paired, return it to the caller; else discard.
|
||||
// * consume left input stream, feeding into unpaired, for as long as leftvals < rightvals && !eof.
|
||||
// * if there is leftrec with vals == rightvals: parallel initial_fill.
|
||||
// else, mimic initial_fill.
|
||||
|
||||
static void join_bucket_keeper_advance_to(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired)
|
||||
{
|
||||
if (pkeeper->pbucket->was_paired) {
|
||||
while (pkeeper->pbucket->precords->phead)
|
||||
lrec_free(sllv_pop(pkeeper->pbucket->precords));
|
||||
sllv_free(pkeeper->pbucket->precords);
|
||||
pkeeper->pbucket->precords = NULL;
|
||||
} else {
|
||||
if (*pprecords_left_unpaired == NULL) {
|
||||
*pprecords_left_unpaired = pkeeper->pbucket->precords;
|
||||
} else {
|
||||
sllv_transfer(*pprecords_left_unpaired, pkeeper->pbucket->precords);
|
||||
}
|
||||
}
|
||||
|
||||
pkeeper->pbucket->precords = sllv_alloc();
|
||||
if (pkeeper->pbucket->pleft_field_values != NULL) {
|
||||
slls_free(pkeeper->pbucket->pleft_field_values);
|
||||
pkeeper->pbucket->pleft_field_values = NULL;
|
||||
}
|
||||
pkeeper->pbucket->was_paired = FALSE;
|
||||
|
||||
if (pkeeper->prec_peek == NULL) { // left EOF
|
||||
return;
|
||||
}
|
||||
|
||||
// Need a double condition here ... the peek record is either het or hom.
|
||||
// (Or, change that: -> ensure elsewhere the peek record is hom.)
|
||||
// The former is destined for lunp and shouldn't be lexcmped. The latter
|
||||
// should be.
|
||||
|
||||
int cmp = lrec_slls_compare_lexically(pkeeper->prec_peek, pkeeper->pleft_field_names, pright_field_values);
|
||||
if (cmp < 0) {
|
||||
// keep seeking & filling the bucket until = or >; this may or may not end up being a match.
|
||||
|
||||
if (*pprecords_left_unpaired == NULL)
|
||||
*pprecords_left_unpaired = sllv_alloc();
|
||||
|
||||
while (TRUE) {
|
||||
sllv_append(*pprecords_left_unpaired, pkeeper->prec_peek);
|
||||
pkeeper->prec_peek = NULL;
|
||||
|
||||
while (TRUE) {
|
||||
// Skip over records not having the join keys. These go straight to the
|
||||
// left-unpaired list.
|
||||
pkeeper->prec_peek = pkeeper->plrec_reader->pprocess_func(pkeeper->plrec_reader->pvstate,
|
||||
pkeeper->pvhandle, pkeeper->pctx);
|
||||
if (pkeeper->prec_peek == NULL)
|
||||
break;
|
||||
if (record_has_all_keys(pkeeper->prec_peek, pkeeper->pleft_field_names)) {
|
||||
break;
|
||||
} else {
|
||||
if (*pprecords_left_unpaired == NULL)
|
||||
*pprecords_left_unpaired = sllv_alloc();
|
||||
sllv_append(*pprecords_left_unpaired, pkeeper->prec_peek);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pkeeper->prec_peek == NULL) {
|
||||
pkeeper->leof = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
cmp = lrec_slls_compare_lexically(pkeeper->prec_peek, pkeeper->pleft_field_names, pright_field_values);
|
||||
if (cmp >= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmp == 0) {
|
||||
join_bucket_keeper_fill(pkeeper, pprecords_left_unpaired);
|
||||
pkeeper->pbucket->was_paired = TRUE;
|
||||
*pprecords_paired = pkeeper->pbucket->precords;
|
||||
} else if (cmp > 0) {
|
||||
join_bucket_keeper_fill(pkeeper, pprecords_left_unpaired);
|
||||
}
|
||||
}
|
||||
|
||||
static void join_bucket_keeper_drain(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired)
|
||||
{
|
||||
// 1. Any records already in pkeeper->pbucket->precords (current bucket)
|
||||
if (pkeeper->pbucket->was_paired) {
|
||||
if (*pprecords_left_unpaired == NULL)
|
||||
*pprecords_left_unpaired = sllv_alloc();
|
||||
} else {
|
||||
if (*pprecords_left_unpaired == NULL) {
|
||||
*pprecords_left_unpaired = pkeeper->pbucket->precords;
|
||||
} else {
|
||||
sllv_transfer(*pprecords_left_unpaired, pkeeper->pbucket->precords);
|
||||
sllv_free(pkeeper->pbucket->precords);
|
||||
}
|
||||
}
|
||||
// 2. Peek-record, if any
|
||||
if (pkeeper->prec_peek != NULL) {
|
||||
sllv_append(*pprecords_left_unpaired, pkeeper->prec_peek);
|
||||
pkeeper->prec_peek = NULL;
|
||||
}
|
||||
// 3. Remainder of left input stream
|
||||
while (TRUE) {
|
||||
lrec_t* prec = pkeeper->plrec_reader->pprocess_func(pkeeper->plrec_reader->pvstate,
|
||||
pkeeper->pvhandle, pkeeper->pctx);
|
||||
if (prec == NULL)
|
||||
break;
|
||||
sllv_append(*pprecords_left_unpaired, prec);
|
||||
}
|
||||
|
||||
pkeeper->pbucket->precords = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void join_bucket_keeper_print(join_bucket_keeper_t* pkeeper) {
|
||||
printf("pbucket at %p:\n", pkeeper);
|
||||
printf(" pvhandle = %p\n", pkeeper->pvhandle);
|
||||
context_print(pkeeper->pctx, " ");
|
||||
printf(" pleft_field_names = ");
|
||||
slls_print(pkeeper->pleft_field_names);
|
||||
printf("\n");
|
||||
join_bucket_print(pkeeper->pbucket, " ");
|
||||
printf(" prec_peek = ");
|
||||
if (pkeeper->prec_peek == NULL) {
|
||||
printf("null\n");
|
||||
} else {
|
||||
lrec_print(pkeeper->prec_peek);
|
||||
}
|
||||
printf(" leof = %d\n", pkeeper->leof);
|
||||
printf(" state = %s\n", describe_state(pkeeper->state));
|
||||
}
|
||||
|
||||
void join_bucket_keeper_print_aux(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired)
|
||||
{
|
||||
join_bucket_keeper_print(pkeeper);
|
||||
printf(" pright_field_values = ");
|
||||
slls_print(pright_field_values);
|
||||
printf("\n");
|
||||
printf(" precords_paired =\n");
|
||||
lrec_print_list_with_prefix(*pprecords_paired, " ");
|
||||
printf("\n");
|
||||
printf(" precords_left_unpaired =\n");
|
||||
lrec_print_list_with_prefix(*pprecords_left_unpaired, " ");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void join_bucket_print(join_bucket_t* pbucket, char* indent) {
|
||||
printf("%spbucket at %p:\n", indent, pbucket);
|
||||
printf("%s pleft_field_values = ", indent);
|
||||
slls_print(pbucket->pleft_field_values);
|
||||
printf("\n");
|
||||
if (pbucket->precords == NULL) {
|
||||
printf("%s precords:\n", indent);
|
||||
printf("%s (null)\n", indent);
|
||||
} else {
|
||||
printf("%s precords (length=%llu):\n", indent, pbucket->precords->length);
|
||||
lrec_print_list_with_prefix(pbucket->precords, " ");
|
||||
}
|
||||
printf("%s was_paired = %d\n", indent, pbucket->was_paired);
|
||||
}
|
||||
|
||||
static char* describe_state(int state) {
|
||||
switch (state) {
|
||||
case LEFT_STATE_0_PREFILL: return "LEFT_STATE_0_PREFILL";
|
||||
case LEFT_STATE_1_FULL: return "LEFT_STATE_1_FULL";
|
||||
case LEFT_STATE_2_LAST_BUCKET: return "LEFT_STATE_2_LAST_BUCKET";
|
||||
case LEFT_STATE_3_EOF: return "LEFT_STATE_3_EOF";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
// ================================================================
|
||||
// Data structures for mlr join, sorted case. Please see descriptive
|
||||
// comments at the top of join_bucket_keeper.h.
|
||||
// ================================================================
|
||||
|
||||
#ifndef JOIN_BUCKET_KEEPER_H
|
||||
#define JOIN_BUCKET_KEEPER_H
|
||||
|
||||
#include "lib/context.h"
|
||||
#include "cli/mlrcli.h"
|
||||
#include "containers/lrec.h"
|
||||
#include "containers/slls.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "input/lrec_reader.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _join_bucket_t {
|
||||
slls_t* pleft_field_values;
|
||||
sllv_t* precords;
|
||||
int was_paired;
|
||||
} join_bucket_t;
|
||||
|
||||
typedef struct _join_bucket_keeper_t {
|
||||
lrec_reader_t* plrec_reader;
|
||||
void* pvhandle;
|
||||
context_t* pctx;
|
||||
|
||||
slls_t* pleft_field_names;
|
||||
|
||||
join_bucket_t* pbucket;
|
||||
lrec_t* prec_peek;
|
||||
|
||||
int leof;
|
||||
int state;
|
||||
} join_bucket_keeper_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
join_bucket_keeper_t* join_bucket_keeper_alloc(
|
||||
char* prepipe,
|
||||
char* left_file_name,
|
||||
cli_reader_opts_t* popts,
|
||||
slls_t* pleft_field_names);
|
||||
|
||||
join_bucket_keeper_t* join_bucket_keeper_alloc_from_reader(
|
||||
lrec_reader_t* plrec_reader,
|
||||
char* prepipe,
|
||||
char* left_file_name,
|
||||
slls_t* pleft_field_names);
|
||||
|
||||
void join_bucket_keeper_free(join_bucket_keeper_t* pkeeper, char* prepipe);
|
||||
|
||||
// *pprecords_paired should not be freed by the caller.
|
||||
// *pprecords_left_unpaired should be freed by the caller.
|
||||
void join_bucket_keeper_emit(
|
||||
join_bucket_keeper_t* pkeeper,
|
||||
slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired,
|
||||
sllv_t** pprecords_left_unpaired);
|
||||
|
||||
void join_bucket_print(join_bucket_t* pbucket, char* indent);
|
||||
void join_bucket_keeper_print(join_bucket_keeper_t* pkeeper);
|
||||
void join_bucket_keeper_print_aux(join_bucket_keeper_t* pkeeper, slls_t* pright_field_values,
|
||||
sllv_t** pprecords_paired, sllv_t** pprecords_left_unpaired);
|
||||
|
||||
#endif // JOIN_BUCKET_KEEPER_H
|
||||
|
|
@ -1,300 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-list-to-void-star linked hash map with
|
||||
// linear probing for collisions.
|
||||
//
|
||||
// John Kerl 2014-12-22
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is not supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhms2v.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 16
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void* lhms2v_put_no_enlarge(lhms2v_t* pmap, char* key1, char* key2, void* pvvalue, char free_flags);
|
||||
static void lhms2v_enlarge(lhms2v_t* pmap);
|
||||
|
||||
// ================================================================
|
||||
static void lhms2v_init(lhms2v_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhms2ve_t*)mlr_malloc_or_die(sizeof(lhms2ve_t) * length);
|
||||
// Don't do lhms2ve_clear() of all entries at init time, since this has a
|
||||
// drastic effect on the time needed to construct an empty map (and miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhms2ve_state_t*)mlr_malloc_or_die(sizeof(lhms2ve_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhms2v_t* lhms2v_alloc() {
|
||||
lhms2v_t* pmap = mlr_malloc_or_die(sizeof(lhms2v_t));
|
||||
lhms2v_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
// void-star payloads should first be freed by the caller.
|
||||
void lhms2v_free(lhms2v_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhms2ve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pe->key1);
|
||||
free(pe->key2);
|
||||
}
|
||||
}
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhms2v_find_index_for_key(lhms2v_t* pmap, char* key1, char* key2, int* pideal_index) {
|
||||
int hash = mlr_string_pair_hash_func(key1, key2);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
int done = 0;
|
||||
|
||||
while (!done) {
|
||||
lhms2ve_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
char* ekey1 = pe->key1;
|
||||
char* ekey2 = pe->key2;
|
||||
// Existing key found in chain.
|
||||
if (streq(key1, ekey1) && streq(key2, ekey2))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been deleted, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return -1; // not reached
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void* lhms2v_put(lhms2v_t* pmap, char* key1, char* key2, void* pvvalue, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhms2v_enlarge(pmap);
|
||||
return lhms2v_put_no_enlarge(pmap, key1, key2, pvvalue, free_flags);
|
||||
}
|
||||
|
||||
static void* lhms2v_put_no_enlarge(lhms2v_t* pmap, char* key1, char* key2, void* pvvalue, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhms2v_find_index_for_key(pmap, key1, key2, &ideal_index);
|
||||
lhms2ve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
pe->pvvalue = pvvalue;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key1 = key1;
|
||||
pe->key2 = key2;
|
||||
pe->pvvalue = pvvalue;
|
||||
pe->free_flags = free_flags;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: lhms2v_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
return pvvalue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void* lhms2v_get(lhms2v_t* pmap, char* key1, char* key2) {
|
||||
int ideal_index = 0;
|
||||
int index = lhms2v_find_index_for_key(pmap, key1, key2, &ideal_index);
|
||||
lhms2ve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe->pvvalue;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return NULL;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhms2v_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhms2v_has_key(lhms2v_t* pmap, char* key1, char* key2) {
|
||||
int ideal_index = 0;
|
||||
int index = lhms2v_find_index_for_key(pmap, key1, key2, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhms2v_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhms2v_size(lhms2v_t* pmap) {
|
||||
return pmap->num_occupied;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhms2v_enlarge(lhms2v_t* pmap) {
|
||||
lhms2ve_t* old_entries = pmap->entries;
|
||||
lhms2ve_state_t* old_states = pmap->states;
|
||||
lhms2ve_t* old_head = pmap->phead;
|
||||
|
||||
lhms2v_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhms2ve_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhms2v_put_no_enlarge(pmap, pe->key1, pe->key2, pe->pvvalue, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhms2v_check_counts(lhms2v_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"deleted-count mismatch: actual %d != cached %d\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "deleted"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void lhms2v_print(lhms2v_t* pmap) {
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
lhms2ve_t* pe = &pmap->entries[index];
|
||||
|
||||
const char* key1_string = (pe == NULL) ? "none" :
|
||||
pe->key1 == NULL ? "null" :
|
||||
pe->key1;
|
||||
const char* key2_string = (pe == NULL) ? "none" :
|
||||
pe->key2 == NULL ? "null" :
|
||||
pe->key2;
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->pvvalue == NULL ? "null" :
|
||||
pe->pvvalue;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key1: %12s | key2: %12s | pvvalue: %12s |\n",
|
||||
get_state_name(pmap->states[index]), index, pe->ideal_index,
|
||||
key1_string, key2_string, value_string);
|
||||
}
|
||||
printf("+\n");
|
||||
printf("| phead: %p | ptail %p\n", pmap->phead, pmap->ptail);
|
||||
printf("+\n");
|
||||
for (lhms2ve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key1_string = (pe == NULL) ? "none" :
|
||||
pe->key1 == NULL ? "null" :
|
||||
pe->key1;
|
||||
const char* key2_string = (pe == NULL) ? "none" :
|
||||
pe->key2 == NULL ? "null" :
|
||||
pe->key2;
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->pvvalue == NULL ? "null" :
|
||||
pe->pvvalue;
|
||||
printf(
|
||||
"| prev: %p curr: %p next: %p | nidx: %6d | key1: %12s | key2: %12s | pvvalue: %12s |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key1_string, key2_string, value_string);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-pair-to-void-star linked hash map with
|
||||
// linear probing for collisions.
|
||||
//
|
||||
// John Kerl 2014-12-22
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMS2V_H
|
||||
#define LHMS2V_H
|
||||
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhms2ve_t {
|
||||
int ideal_index;
|
||||
char* key1;
|
||||
char* key2;
|
||||
void* pvvalue;
|
||||
char free_flags;
|
||||
struct _lhms2ve_t *pprev;
|
||||
struct _lhms2ve_t *pnext;
|
||||
} lhms2ve_t;
|
||||
|
||||
typedef unsigned char lhms2ve_state_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhms2v_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhms2ve_t* entries;
|
||||
lhms2ve_state_t* states;
|
||||
lhms2ve_t* phead;
|
||||
lhms2ve_t* ptail;
|
||||
} lhms2v_t;
|
||||
|
||||
lhms2v_t* lhms2v_alloc();
|
||||
void lhms2v_free(lhms2v_t* pmap);
|
||||
void* lhms2v_put(lhms2v_t* pmap, char* key1, char* key2, void* pvvalue, char free_flags);
|
||||
void* lhms2v_get(lhms2v_t* pmap, char* key1, char* key2);
|
||||
int lhms2v_has_key(lhms2v_t* pmap, char* key1, char* key2);
|
||||
int lhms2v_size(lhms2v_t* pmap);
|
||||
|
||||
// Unit-test hook
|
||||
int lhms2v_check_counts(lhms2v_t* pmap);
|
||||
|
||||
#endif // LHMS2V_H
|
||||
|
|
@ -1,322 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-string linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// Keys are not strduped.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhmsi.h"
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 16
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsi_put_no_enlarge(lhmsi_t* pmap, char* key, int value, char free_flags);
|
||||
static void lhmsi_enlarge(lhmsi_t* pmap);
|
||||
|
||||
// ================================================================
|
||||
static void lhmsi_init(lhmsi_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhmsie_t*)mlr_malloc_or_die(sizeof(lhmsie_t) * length);
|
||||
// Don't do lhmsie_clear() of all entries at init time, since this has a
|
||||
// drastic effect on the time needed to construct an empty map (and miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhmsie_state_t*)mlr_malloc_or_die(sizeof(lhmsie_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhmsi_t* lhmsi_alloc() {
|
||||
lhmsi_t* pmap = mlr_malloc_or_die(sizeof(lhmsi_t));
|
||||
lhmsi_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
lhmsi_t* lhmsi_copy(lhmsi_t* pmap) {
|
||||
lhmsi_t* pnew = lhmsi_alloc();
|
||||
for (lhmsie_t* pe = pmap->phead; pe != NULL; pe = pe->pnext)
|
||||
lhmsi_put(pnew, mlr_strdup_or_die(pe->key), pe->value, FREE_ENTRY_KEY);
|
||||
return pnew;
|
||||
}
|
||||
|
||||
void lhmsi_free(lhmsi_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmsie_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
}
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhmsi_find_index_for_key(lhmsi_t* pmap, char* key, int* pideal_index) {
|
||||
int hash = mlr_string_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
lhmsie_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
char* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (streq(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been deleted, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsi_put(lhmsi_t* pmap, char* key, int value, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhmsi_enlarge(pmap);
|
||||
lhmsi_put_no_enlarge(pmap, key, value, free_flags);
|
||||
}
|
||||
|
||||
static void lhmsi_put_no_enlarge(lhmsi_t* pmap, char* key, int value, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsi_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsie_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
pe->value = value;
|
||||
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsi_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsi_get(lhmsi_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsi_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsie_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe->value;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return -999; // caller must do lhmsi_has_key to check validity
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsi_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsi_test_and_get(lhmsi_t* pmap, char* key, int* pval) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsi_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsie_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
*pval = pe->value;
|
||||
return TRUE;
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
return FALSE;
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsi_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
lhmsie_t* lhmsi_get_entry(lhmsi_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsi_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsie_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return NULL;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsi_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsi_has_key(lhmsi_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsi_find_index_for_key(pmap, key, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsi_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsi_rename(lhmsi_t* pmap, char* old_key, char* new_key) {
|
||||
fprintf(stderr, "rename is not supported in the hashed-record impl.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsi_enlarge(lhmsi_t* pmap) {
|
||||
lhmsie_t* old_entries = pmap->entries;
|
||||
lhmsie_state_t* old_states = pmap->states;
|
||||
lhmsie_t* old_head = pmap->phead;
|
||||
|
||||
lhmsi_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhmsie_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhmsi_put_no_enlarge(pmap, pe->key, pe->value, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsi_check_counts(lhmsi_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d.\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"deleted-count mismatch: actual %d != cached %d.\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "deleted"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void lhmsi_print(lhmsi_t* pmap) {
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
lhmsie_t* pe = &pmap->entries[index];
|
||||
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key: %12s | value: %8d |\n",
|
||||
get_state_name(pmap->states[index]), index, pe->ideal_index, key_string, pe->value);
|
||||
}
|
||||
printf("+\n");
|
||||
printf("| phead: %p | ptail %p\n", pmap->phead, pmap->ptail);
|
||||
printf("+\n");
|
||||
for (lhmsie_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
printf(
|
||||
"| prev: %p curr: %p next: %p | nidx: %6d | key: %12s | value: %8d |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key_string, pe->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-int linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMSI_H
|
||||
#define LHMSI_H
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmsie_t {
|
||||
int ideal_index;
|
||||
char* key;
|
||||
int value;
|
||||
char free_flags;
|
||||
struct _lhmsie_t *pprev;
|
||||
struct _lhmsie_t *pnext;
|
||||
} lhmsie_t;
|
||||
|
||||
typedef unsigned char lhmsie_state_t;
|
||||
|
||||
typedef struct _lhmsi_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhmsie_t* entries;
|
||||
lhmsie_state_t* states;
|
||||
lhmsie_t* phead;
|
||||
lhmsie_t* ptail;
|
||||
} lhmsi_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmsi_t* lhmsi_alloc();
|
||||
lhmsi_t* lhmsi_copy(lhmsi_t* pmap);
|
||||
void lhmsi_free(lhmsi_t* pmap);
|
||||
void lhmsi_put(lhmsi_t* pmap, char* key, int value, char free_flags);
|
||||
int lhmsi_get(lhmsi_t* pmap, char* key); // caller must do lhmsi_has_key to check validity
|
||||
int lhmsi_test_and_get(lhmsi_t* pmap, char* key, int* pval); // *pval undefined if return is FALSE
|
||||
lhmsie_t* lhmsi_get_entry(lhmsi_t* pmap, char* key);
|
||||
int lhmsi_has_key(lhmsi_t* pmap, char* key);
|
||||
|
||||
// Unit-test hook
|
||||
int lhmsi_check_counts(lhmsi_t* pmap);
|
||||
|
||||
#endif // LHMSI_H
|
||||
|
|
@ -1,339 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-string linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// Keys are not strduped.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhmsll.h"
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 16
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsll_put_no_enlarge(lhmsll_t* pmap, char* key, int value, char free_flags);
|
||||
static void lhmsll_enlarge(lhmsll_t* pmap);
|
||||
|
||||
// ================================================================
|
||||
static void lhmsll_init(lhmsll_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhmslle_t*)mlr_malloc_or_die(sizeof(lhmslle_t) * length);
|
||||
// Don't do lhmslle_clear() of all entries at init time, since this has a
|
||||
// drastic effect on the time needed to construct an empty map (and miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhmslle_state_t*)mlr_malloc_or_die(sizeof(lhmslle_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhmsll_t* lhmsll_alloc() {
|
||||
lhmsll_t* pmap = mlr_malloc_or_die(sizeof(lhmsll_t));
|
||||
lhmsll_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
lhmsll_t* lhmsll_copy(lhmsll_t* pmap) {
|
||||
lhmsll_t* pnew = lhmsll_alloc();
|
||||
for (lhmslle_t* pe = pmap->phead; pe != NULL; pe = pe->pnext)
|
||||
lhmsll_put(pnew, mlr_strdup_or_die(pe->key), pe->value, FREE_ENTRY_KEY);
|
||||
return pnew;
|
||||
}
|
||||
|
||||
void lhmsll_free(lhmsll_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmslle_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
}
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhmsll_find_index_for_key(lhmsll_t* pmap, char* key, int* pideal_index) {
|
||||
int hash = mlr_string_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
char* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (streq(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been deleted, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return -1; // not reached
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsll_put(lhmsll_t* pmap, char* key, int value, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhmsll_enlarge(pmap);
|
||||
lhmsll_put_no_enlarge(pmap, key, value, free_flags);
|
||||
}
|
||||
|
||||
static void lhmsll_put_no_enlarge(lhmsll_t* pmap, char* key, int value, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsll_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
pe->value = value;
|
||||
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsll_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
long long lhmsll_get(lhmsll_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsll_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe->value;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return -999; // caller must do lhmsll_has_key to check validity
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsll_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsll_test_and_get(lhmsll_t* pmap, char* key, long long* pval) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsll_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
*pval = pe->value;
|
||||
return TRUE;
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
return FALSE;
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsll_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int lhmsll_test_and_increment(lhmsll_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsll_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
pe->value++;
|
||||
return TRUE;
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
return FALSE;
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsll_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
lhmslle_t* lhmsll_get_entry(lhmsll_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsll_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return NULL;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsll_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsll_has_key(lhmsll_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsll_find_index_for_key(pmap, key, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsll_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsll_rename(lhmsll_t* pmap, char* old_key, char* new_key) {
|
||||
fprintf(stderr, "rename is not supported in the hashed-record impl.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsll_enlarge(lhmsll_t* pmap) {
|
||||
lhmslle_t* old_entries = pmap->entries;
|
||||
lhmslle_state_t* old_states = pmap->states;
|
||||
lhmslle_t* old_head = pmap->phead;
|
||||
|
||||
lhmsll_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhmslle_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhmsll_put_no_enlarge(pmap, pe->key, pe->value, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsll_check_counts(lhmsll_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d.\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"deleted-count mismatch: actual %d != cached %d.\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "deleted"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void lhmsll_print(lhmsll_t* pmap) {
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
lhmslle_t* pe = &pmap->entries[index];
|
||||
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key: %12s | value: %8lld |\n",
|
||||
get_state_name(pmap->states[index]), index, pe->ideal_index, key_string, pe->value);
|
||||
}
|
||||
printf("+\n");
|
||||
printf("| phead: %p | ptail %p\n", pmap->phead, pmap->ptail);
|
||||
printf("+\n");
|
||||
for (lhmslle_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
printf(
|
||||
"| prev: %p curr: %p next: %p | nidx: %6d | key: %12s | value: %8lld |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key_string, pe->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-int linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMSLL_H
|
||||
#define LHMSLL_H
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmslle_t {
|
||||
int ideal_index;
|
||||
char* key;
|
||||
long long value;
|
||||
char free_flags;
|
||||
struct _lhmslle_t *pprev;
|
||||
struct _lhmslle_t *pnext;
|
||||
} lhmslle_t;
|
||||
|
||||
typedef unsigned char lhmslle_state_t;
|
||||
|
||||
typedef struct _lhmsll_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhmslle_t* entries;
|
||||
lhmslle_state_t* states;
|
||||
lhmslle_t* phead;
|
||||
lhmslle_t* ptail;
|
||||
} lhmsll_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmsll_t* lhmsll_alloc();
|
||||
|
||||
lhmsll_t* lhmsll_copy(lhmsll_t* pmap);
|
||||
|
||||
void lhmsll_free(lhmsll_t* pmap);
|
||||
void lhmsll_put(lhmsll_t* pmap, char* key, int value, char free_flags);
|
||||
long long lhmsll_get(lhmsll_t* pmap, char* key); // caller must do lhmsll_has_key to check validity
|
||||
int lhmsll_test_and_get(lhmsll_t* pmap, char* key, long long* pval); // *pval undefined if return is FALSE
|
||||
int lhmsll_test_and_increment(lhmsll_t* pmap, char* key); // increments value only if mapping exists
|
||||
lhmslle_t* lhmsll_get_entry(lhmsll_t* pmap, char* key);
|
||||
int lhmsll_has_key(lhmsll_t* pmap, char* key);
|
||||
|
||||
// Unit-test hook
|
||||
int lhmsll_check_counts(lhmsll_t* pmap);
|
||||
|
||||
#endif // LHMSLL_H
|
||||
|
|
@ -1,288 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-list-to-void-star linked hash map with
|
||||
// linear probing for collisions.
|
||||
//
|
||||
// John Kerl 2014-12-22
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is not supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhmslv.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 16
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void* lhmslv_put_no_enlarge(lhmslv_t* pmap, slls_t* key, void* pvvalue, char free_flags);
|
||||
static void lhmslv_enlarge(lhmslv_t* pmap);
|
||||
|
||||
// ================================================================
|
||||
static void lhmslv_init(lhmslv_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhmslve_t*)mlr_malloc_or_die(sizeof(lhmslve_t) * length);
|
||||
// Don't do lhmslve_clear() of all entries at init time, since this has a
|
||||
// drastic effect on the time needed to construct an empty map (and miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhmslve_state_t*)mlr_malloc_or_die(sizeof(lhmslve_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhmslv_t* lhmslv_alloc() {
|
||||
lhmslv_t* pmap = mlr_malloc_or_die(sizeof(lhmslv_t));
|
||||
lhmslv_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
// void-star payloads should first be freed by the caller.
|
||||
void lhmslv_free(lhmslv_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmslve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext)
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
slls_free(pe->key);
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhmslv_find_index_for_key(lhmslv_t* pmap, slls_t* key, int* pideal_index) {
|
||||
int hash = slls_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
lhmslve_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
slls_t* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (slls_equals(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been freed, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return -1; // not reached
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void* lhmslv_put(lhmslv_t* pmap, slls_t* key, void* pvvalue, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhmslv_enlarge(pmap);
|
||||
return lhmslv_put_no_enlarge(pmap, key, pvvalue, free_flags);
|
||||
}
|
||||
|
||||
static void* lhmslv_put_no_enlarge(lhmslv_t* pmap, slls_t* key, void* pvvalue, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmslv_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
pe->pvvalue = pvvalue;
|
||||
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key = key;
|
||||
pe->free_flags = free_flags;
|
||||
pe->pvvalue = pvvalue;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmslv_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return pvvalue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void* lhmslv_get(lhmslv_t* pmap, slls_t* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmslv_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmslve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe->pvvalue;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return NULL;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmslv_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmslv_has_key(lhmslv_t* pmap, slls_t* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmslv_find_index_for_key(pmap, key, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmslv_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmslv_size(lhmslv_t* pmap) {
|
||||
return pmap->num_occupied;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmslv_enlarge(lhmslv_t* pmap) {
|
||||
lhmslve_t* old_entries = pmap->entries;
|
||||
lhmslve_state_t* old_states = pmap->states;
|
||||
lhmslve_t* old_head = pmap->phead;
|
||||
|
||||
lhmslv_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhmslve_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhmslv_put_no_enlarge(pmap, pe->key, pe->pvvalue, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmslv_check_counts(lhmslv_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"freed-count mismatch: actual %d != cached %d\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "freed"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void lhmslv_print(lhmslv_t* pmap) {
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
lhmslve_t* pe = &pmap->entries[index];
|
||||
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
slls_join(pe->key, ",");
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->pvvalue == NULL ? "null" :
|
||||
pe->pvvalue;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key: %12s | pvvalue: %12s |\n",
|
||||
get_state_name(pmap->states[index]), index, pe->ideal_index, key_string, value_string);
|
||||
}
|
||||
printf("+\n");
|
||||
printf("| phead: %p | ptail %p\n", pmap->phead, pmap->ptail);
|
||||
printf("+\n");
|
||||
for (lhmslve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
slls_join(pe->key, ",");
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->pvvalue == NULL ? "null" :
|
||||
pe->pvvalue;
|
||||
printf(
|
||||
"| prev: %p curr: %p next: %p | nidx: %6d | key: %12s | pvvalue: %12s |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key_string, value_string);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-list-to-void-star linked hash map with
|
||||
// linear probing for collisions.
|
||||
//
|
||||
// John Kerl 2014-12-22
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMSLV_H
|
||||
#define LHMSLV_H
|
||||
|
||||
#include "containers/slls.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmslve_t {
|
||||
int ideal_index;
|
||||
slls_t* key;
|
||||
void* pvvalue;
|
||||
char free_flags;
|
||||
struct _lhmslve_t *pprev;
|
||||
struct _lhmslve_t *pnext;
|
||||
} lhmslve_t;
|
||||
|
||||
typedef unsigned char lhmslve_state_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmslv_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhmslve_t* entries;
|
||||
lhmslve_state_t* states;
|
||||
lhmslve_t* phead;
|
||||
lhmslve_t* ptail;
|
||||
} lhmslv_t;
|
||||
|
||||
lhmslv_t* lhmslv_alloc();
|
||||
void lhmslv_free(lhmslv_t* pmap);
|
||||
void* lhmslv_put(lhmslv_t* pmap, slls_t* key, void* pvvalue, char free_flags);
|
||||
void* lhmslv_get(lhmslv_t* pmap, slls_t* key);
|
||||
int lhmslv_has_key(lhmslv_t* pmap, slls_t* key);
|
||||
int lhmslv_size(lhmslv_t* pmap);
|
||||
|
||||
// Unit-test hook
|
||||
int lhmslv_check_counts(lhmslv_t* pmap);
|
||||
|
||||
#endif // LHMSLV_H
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-mlrval linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// Keys and values are not strduped.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhmsmv.h"
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 32
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsmv_put_no_enlarge(lhmsmv_t* pmap, char* key, mv_t* pvalue, char free_flags);
|
||||
static void lhmsmv_enlarge(lhmsmv_t* pmap);
|
||||
|
||||
static void lhmsmv_init(lhmsmv_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhmsmve_t*)mlr_malloc_or_die(sizeof(lhmsmve_t) * length);
|
||||
// Don't do a memset of all entries at init time, since this has a drastic
|
||||
// effect on the time needed to construct an empty map (and Miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhmsmve_state_t*)mlr_malloc_or_die(sizeof(lhmsmve_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhmsmv_t* lhmsmv_alloc() {
|
||||
lhmsmv_t* pmap = mlr_malloc_or_die(sizeof(lhmsmv_t));
|
||||
lhmsmv_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmsmv_t* lhmsmv_copy(lhmsmv_t* pold) {
|
||||
lhmsmv_t* pnew = lhmsmv_alloc();
|
||||
|
||||
for (lhmsmve_t* pe = pold->phead; pe != NULL; pe = pe->pnext) {
|
||||
char* nkey = mlr_strdup_or_die(pe->key);
|
||||
mv_t nval = mv_copy(&pe->value);
|
||||
lhmsmv_put(pnew, nkey, &nval, FREE_ENTRY_KEY | FREE_ENTRY_VALUE);
|
||||
}
|
||||
|
||||
return pnew;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsmv_clear(lhmsmv_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmsmve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
mv_free(&pe->value);
|
||||
}
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
memset(pmap->states, EMPTY, pmap->array_length);
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsmv_free(lhmsmv_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmsmve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
mv_free(&pe->value);
|
||||
}
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhmsmv_find_index_for_key(lhmsmv_t* pmap, char* key, int* pideal_index) {
|
||||
int hash = mlr_string_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
lhmsmve_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
char* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (streq(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been freed, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return -1; // not reached
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsmv_put(lhmsmv_t* pmap, char* key, mv_t* pvalue, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhmsmv_enlarge(pmap);
|
||||
lhmsmv_put_no_enlarge(pmap, key, pvalue, free_flags);
|
||||
}
|
||||
|
||||
static void lhmsmv_put_no_enlarge(lhmsmv_t* pmap, char* key, mv_t* pvalue, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsmv_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsmve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
mv_free(&pe->value);
|
||||
pe->value = *pvalue;
|
||||
if (free_flags & FREE_ENTRY_VALUE)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
else
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
|
||||
// The caller asked us to free the key when we were done but another copy of the
|
||||
// key is already present. So free now what they passed in.
|
||||
if (free_flags & FREE_ENTRY_KEY)
|
||||
free(key);
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key = key;
|
||||
pe->value = *pvalue;
|
||||
pe->free_flags = free_flags;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsmv_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mv_t* lhmsmv_get(lhmsmv_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsmv_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsmve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
return &pe->value;
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
return NULL;
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsmv_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsmv_has_key(lhmsmv_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsmv_find_index_for_key(pmap, key, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsmv_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsmv_enlarge(lhmsmv_t* pmap) {
|
||||
lhmsmve_t* old_entries = pmap->entries;
|
||||
lhmsmve_state_t* old_states = pmap->states;
|
||||
lhmsmve_t* old_head = pmap->phead;
|
||||
|
||||
lhmsmv_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhmsmve_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhmsmv_put_no_enlarge(pmap, pe->key, &pe->value, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsmv_dump(lhmsmv_t* pmap) {
|
||||
for (lhmsmve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
char* value_string = mv_alloc_format_val(&pe->value);
|
||||
printf("| prev: %p curr: %p next: %p | nidx: %6d | key: %12s | value: %12s |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key_string, value_string);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsmv_check_counts(lhmsmv_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d.\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"deleted-count mismatch: actual %d != cached %d.\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-mlrval linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMSMV_H
|
||||
#define LHMSMV_H
|
||||
|
||||
#include "containers/sllv.h"
|
||||
#include "lib/mlrval.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmsmve_t {
|
||||
int ideal_index;
|
||||
char free_flags;
|
||||
char* key;
|
||||
mv_t value;
|
||||
struct _lhmsmve_t *pprev;
|
||||
struct _lhmsmve_t *pnext;
|
||||
} lhmsmve_t;
|
||||
|
||||
typedef unsigned char lhmsmve_state_t;
|
||||
|
||||
typedef struct _lhmsmv_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhmsmve_t* entries;
|
||||
lhmsmve_state_t* states;
|
||||
lhmsmve_t* phead;
|
||||
lhmsmve_t* ptail;
|
||||
} lhmsmv_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmsmv_t* lhmsmv_alloc();
|
||||
lhmsmv_t* lhmsmv_copy(lhmsmv_t* pmap);
|
||||
void lhmsmv_clear(lhmsmv_t* pmap);
|
||||
void lhmsmv_free(lhmsmv_t* pmap);
|
||||
|
||||
void lhmsmv_put(lhmsmv_t* pmap, char* key, mv_t* pvalue, char free_flags);
|
||||
mv_t* lhmsmv_get(lhmsmv_t* pmap, char* key);
|
||||
int lhmsmv_has_key(lhmsmv_t* pmap, char* key);
|
||||
|
||||
void lhmsmv_dump(lhmsmv_t* pmap);
|
||||
int lhmsmv_check_counts(lhmsmv_t* pmap);
|
||||
|
||||
#endif // LHMSMV_H
|
||||
|
|
@ -1,306 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-string linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// Keys and values are not strduped.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhmss.h"
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 16
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmss_put_no_enlarge(lhmss_t* pmap, char* key, char* value, char free_flags);
|
||||
static void lhmss_enlarge(lhmss_t* pmap);
|
||||
|
||||
static void lhmss_init(lhmss_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhmsse_t*)mlr_malloc_or_die(sizeof(lhmsse_t) * length);
|
||||
// Don't do lhmsse_clear() of all entries at init time, since this has a
|
||||
// drastic effect on the time needed to construct an empty map (and miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhmsse_state_t*)mlr_malloc_or_die(sizeof(lhmsse_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhmss_t* lhmss_alloc() {
|
||||
lhmss_t* pmap = mlr_malloc_or_die(sizeof(lhmss_t));
|
||||
lhmss_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
lhmss_t* lhmss_copy(lhmss_t* pmap) {
|
||||
lhmss_t* pnew = lhmss_alloc();
|
||||
for (lhmsse_t* pe = pmap->phead; pe != NULL; pe = pe->pnext)
|
||||
lhmss_put(pnew, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value), FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
|
||||
return pnew;
|
||||
}
|
||||
|
||||
void lhmss_free(lhmss_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmsse_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
free(pe->value);
|
||||
}
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhmss_find_index_for_key(lhmss_t* pmap, char* key, int* pideal_index) {
|
||||
int hash = mlr_string_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
lhmsse_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
char* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (streq(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been freed, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return -1; // not reached
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmss_put(lhmss_t* pmap, char* key, char* value, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhmss_enlarge(pmap);
|
||||
lhmss_put_no_enlarge(pmap, key, value, free_flags);
|
||||
}
|
||||
|
||||
static void lhmss_put_no_enlarge(lhmss_t* pmap, char* key, char* value, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmss_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsse_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(key);
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
free(pe->value);
|
||||
pe->value = value;
|
||||
if (free_flags & FREE_ENTRY_VALUE)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
else
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmss_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
char* lhmss_get(lhmss_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmss_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsse_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
return pe->value;
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
return NULL;
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmss_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmss_has_key(lhmss_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmss_find_index_for_key(pmap, key, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmss_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmss_rename(lhmss_t* pmap, char* old_key, char* new_key) {
|
||||
fprintf(stderr, "rename is not supported in the hashed-record impl.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmss_enlarge(lhmss_t* pmap) {
|
||||
lhmsse_t* old_entries = pmap->entries;
|
||||
lhmsse_state_t* old_states = pmap->states;
|
||||
lhmsse_t* old_head = pmap->phead;
|
||||
|
||||
lhmss_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhmsse_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhmss_put_no_enlarge(pmap, pe->key, pe->value, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "freed"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void lhmss_dump(lhmss_t* pmap) {
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
lhmsse_t* pe = &pmap->entries[index];
|
||||
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->value == NULL ? "null" :
|
||||
pe->value;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key: %12s | value: %12s |\n",
|
||||
get_state_name(pmap->states[index]), index, pe->ideal_index, key_string, value_string);
|
||||
}
|
||||
printf("+\n");
|
||||
printf("| phead: %p | ptail %p\n", pmap->phead, pmap->ptail);
|
||||
printf("+\n");
|
||||
for (lhmsse_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->value == NULL ? "null" :
|
||||
pe->value;
|
||||
printf(
|
||||
"| prev: %p curr: %p next: %p | nidx: %6d | key: %12s | value: %12s |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key_string, value_string);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmss_check_counts(lhmss_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d.\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"deleted-count mismatch: actual %d != cached %d.\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-string linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMSS_H
|
||||
#define LHMSS_H
|
||||
|
||||
#include "containers/sllv.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmsse_t {
|
||||
int ideal_index;
|
||||
char free_flags;
|
||||
char* key;
|
||||
char* value;
|
||||
struct _lhmsse_t *pprev;
|
||||
struct _lhmsse_t *pnext;
|
||||
} lhmsse_t;
|
||||
|
||||
typedef unsigned char lhmsse_state_t;
|
||||
|
||||
typedef struct _lhmss_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhmsse_t* entries;
|
||||
lhmsse_state_t* states;
|
||||
lhmsse_t* phead;
|
||||
lhmsse_t* ptail;
|
||||
} lhmss_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmss_t* lhmss_alloc();
|
||||
lhmss_t* lhmss_copy(lhmss_t* pmap);
|
||||
void lhmss_free(lhmss_t* pmap);
|
||||
void lhmss_put(lhmss_t* pmap, char* key, char* value, char free_flags);
|
||||
char* lhmss_get(lhmss_t* pmap, char* key);
|
||||
int lhmss_has_key(lhmss_t* pmap, char* key);
|
||||
void lhmss_rename(lhmss_t* pmap, char* old_key, char* new_key);
|
||||
|
||||
void lhmss_dump(lhmss_t* pmap);
|
||||
|
||||
// Unit-test hook
|
||||
int lhmss_check_counts(lhmss_t* pmap);
|
||||
|
||||
#endif // LHMSS_H
|
||||
|
|
@ -1,293 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-void linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// Keys are not strduped; memory management of the void* values is left to the
|
||||
// caller.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is not supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/lhmsv.h"
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Allow compile-time override, e.g using gcc -D.
|
||||
#ifndef INITIAL_ARRAY_LENGTH
|
||||
#define INITIAL_ARRAY_LENGTH 16
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_FACTOR
|
||||
#define LOAD_FACTOR 0.7
|
||||
#endif
|
||||
|
||||
#ifndef ENLARGEMENT_FACTOR
|
||||
#define ENLARGEMENT_FACTOR 2
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define OCCUPIED 0xa4
|
||||
#define DELETED 0xb8
|
||||
#define EMPTY 0xce
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsv_put_no_enlarge(lhmsv_t* pmap, char* key, void* pvvalue, char free_flags);
|
||||
static void lhmsv_enlarge(lhmsv_t* pmap);
|
||||
|
||||
static void lhmsv_init(lhmsv_t *pmap, int length) {
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = length;
|
||||
|
||||
pmap->entries = (lhmsve_t*)mlr_malloc_or_die(sizeof(lhmsve_t) * length);
|
||||
// Don't do lhmsve_clear() of all entries at init time, since this has a
|
||||
// drastic effect on the time needed to construct an empty map (and miller
|
||||
// constructs an awful lot of those). The attributes there are don't-cares
|
||||
// if the corresponding entry state is EMPTY. They are set on put, and
|
||||
// mutated on remove.
|
||||
|
||||
pmap->states = (lhmsve_state_t*)mlr_malloc_or_die(sizeof(lhmsve_state_t) * length);
|
||||
memset(pmap->states, EMPTY, length);
|
||||
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
lhmsv_t* lhmsv_alloc() {
|
||||
lhmsv_t* pmap = mlr_malloc_or_die(sizeof(lhmsv_t));
|
||||
lhmsv_init(pmap, INITIAL_ARRAY_LENGTH);
|
||||
return pmap;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsv_free(lhmsv_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmsve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
}
|
||||
free(pmap->entries);
|
||||
free(pmap->states);
|
||||
pmap->entries = NULL;
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
pmap->array_length = 0;
|
||||
free(pmap);
|
||||
}
|
||||
|
||||
void lhmsv_clear(lhmsv_t* pmap) {
|
||||
if (pmap == NULL)
|
||||
return;
|
||||
for (lhmsve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
}
|
||||
pmap->num_occupied = 0;
|
||||
pmap->num_freed = 0;
|
||||
memset(pmap->states, EMPTY, pmap->array_length);
|
||||
pmap->phead = NULL;
|
||||
pmap->ptail = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Used by get() and remove().
|
||||
// Returns >=0 for where the key is *or* should go (end of chain).
|
||||
static int lhmsv_find_index_for_key(lhmsv_t* pmap, char* key, int* pideal_index) {
|
||||
int hash = mlr_string_hash_func(key);
|
||||
int index = mlr_canonical_mod(hash, pmap->array_length);
|
||||
*pideal_index = index;
|
||||
int num_tries = 0;
|
||||
|
||||
while (TRUE) {
|
||||
lhmsve_t* pe = &pmap->entries[index];
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
char* ekey = pe->key;
|
||||
// Existing key found in chain.
|
||||
if (streq(key, ekey))
|
||||
return index;
|
||||
}
|
||||
else if (pmap->states[index] == EMPTY) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the current entry has been deleted, i.e. previously occupied,
|
||||
// the sought index may be further down the chain. So we must
|
||||
// continue looking.
|
||||
if (++num_tries >= pmap->array_length) {
|
||||
fprintf(stderr,
|
||||
"%s: internal coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Linear probing.
|
||||
if (++index >= pmap->array_length)
|
||||
index = 0;
|
||||
}
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return -1; // not reached
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lhmsv_put(lhmsv_t* pmap, char* key, void* pvvalue, char free_flags) {
|
||||
if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR))
|
||||
lhmsv_enlarge(pmap);
|
||||
lhmsv_put_no_enlarge(pmap, key, pvvalue, free_flags);
|
||||
}
|
||||
|
||||
static void lhmsv_put_no_enlarge(lhmsv_t* pmap, char* key, void* pvvalue, char free_flags) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsv_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED) {
|
||||
// Existing key found in chain; put value.
|
||||
pe->pvvalue = pvvalue;
|
||||
|
||||
} else if (pmap->states[index] == EMPTY) {
|
||||
// End of chain.
|
||||
pe->ideal_index = ideal_index;
|
||||
pe->key = key;
|
||||
pe->pvvalue = pvvalue;
|
||||
pe->free_flags = free_flags;
|
||||
pmap->states[index] = OCCUPIED;
|
||||
|
||||
if (pmap->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
pmap->phead = pe;
|
||||
pmap->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = pmap->ptail;
|
||||
pe->pnext = NULL;
|
||||
pmap->ptail->pnext = pe;
|
||||
pmap->ptail = pe;
|
||||
}
|
||||
pmap->num_occupied++;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: lhmsv_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void* lhmsv_get(lhmsv_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsv_find_index_for_key(pmap, key, &ideal_index);
|
||||
lhmsve_t* pe = &pmap->entries[index];
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return pe->pvvalue;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return NULL;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsv_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsv_has_key(lhmsv_t* pmap, char* key) {
|
||||
int ideal_index = 0;
|
||||
int index = lhmsv_find_index_for_key(pmap, key, &ideal_index);
|
||||
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
return TRUE;
|
||||
else if (pmap->states[index] == EMPTY)
|
||||
return FALSE;
|
||||
else {
|
||||
fprintf(stderr, "%s: lhmsv_find_index_for_key did not find end of chain.\n", MLR_GLOBALS.bargv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lhmsv_enlarge(lhmsv_t* pmap) {
|
||||
lhmsve_t* old_entries = pmap->entries;
|
||||
lhmsve_state_t* old_states = pmap->states;
|
||||
lhmsve_t* old_head = pmap->phead;
|
||||
|
||||
lhmsv_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR);
|
||||
|
||||
for (lhmsve_t* pe = old_head; pe != NULL; pe = pe->pnext) {
|
||||
lhmsv_put_no_enlarge(pmap, pe->key, pe->pvvalue, pe->free_flags);
|
||||
}
|
||||
free(old_entries);
|
||||
free(old_states);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lhmsv_check_counts(lhmsv_t* pmap) {
|
||||
int nocc = 0;
|
||||
int ndel = 0;
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
if (pmap->states[index] == OCCUPIED)
|
||||
nocc++;
|
||||
else if (pmap->states[index] == DELETED)
|
||||
ndel++;
|
||||
}
|
||||
if (nocc != pmap->num_occupied) {
|
||||
fprintf(stderr,
|
||||
"occupancy-count mismatch: actual %d != cached %d.\n",
|
||||
nocc, pmap->num_occupied);
|
||||
return FALSE;
|
||||
}
|
||||
if (ndel != pmap->num_freed) {
|
||||
fprintf(stderr,
|
||||
"deleted-count mismatch: actual %d != cached %d.\n",
|
||||
ndel, pmap->num_freed);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* get_state_name(int state) {
|
||||
switch(state) {
|
||||
case OCCUPIED: return "occupied"; break;
|
||||
case DELETED: return "deleted"; break;
|
||||
case EMPTY: return "empty"; break;
|
||||
default: return "?????"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void lhmsv_print(lhmsv_t* pmap) {
|
||||
for (int index = 0; index < pmap->array_length; index++) {
|
||||
lhmsve_t* pe = &pmap->entries[index];
|
||||
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
|
||||
printf(
|
||||
"| stt: %-8s | idx: %6d | nidx: %6d | key: %12s | pvvalue: %p |\n",
|
||||
get_state_name(pmap->states[index]), index, pe->ideal_index, key_string, pe->pvvalue);
|
||||
}
|
||||
printf("+\n");
|
||||
printf("| phead: %p | ptail %p\n", pmap->phead, pmap->ptail);
|
||||
printf("+\n");
|
||||
for (lhmsve_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
printf(
|
||||
"| prev: %p curr: %p next: %p | nidx: %6d | key: %12s | pvvalue: %p |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
pe->ideal_index, key_string, pe->pvvalue);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) string-to-void linked hash map with linear
|
||||
// probing for collisions.
|
||||
//
|
||||
// John Kerl 2012-08-13
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef LHMSV_H
|
||||
#define LHMSV_H
|
||||
|
||||
#include "containers/sllv.h"
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lhmsve_t {
|
||||
int ideal_index;
|
||||
char* key;
|
||||
void* pvvalue;
|
||||
char free_flags;
|
||||
struct _lhmsve_t *pprev;
|
||||
struct _lhmsve_t *pnext;
|
||||
} lhmsve_t;
|
||||
|
||||
typedef unsigned char lhmsve_state_t;
|
||||
|
||||
typedef struct _lhmsv_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
lhmsve_t* entries;
|
||||
lhmsve_state_t* states;
|
||||
lhmsve_t* phead;
|
||||
lhmsve_t* ptail;
|
||||
} lhmsv_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmsv_t* lhmsv_alloc();
|
||||
void lhmsv_free(lhmsv_t* pmap);
|
||||
void lhmsv_clear(lhmsv_t* pmap);
|
||||
|
||||
void lhmsv_put(lhmsv_t* pmap, char* key, void* pvvalue, char free_flags);
|
||||
void* lhmsv_get(lhmsv_t* pmap, char* key);
|
||||
int lhmsv_has_key(lhmsv_t* pmap, char* key);
|
||||
|
||||
// Unit-test hook
|
||||
int lhmsv_check_counts(lhmsv_t* pmap);
|
||||
|
||||
#endif // LHMSV_H
|
||||
|
|
@ -1,368 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "containers/local_stack.h"
|
||||
|
||||
// ================================================================
|
||||
static local_stack_frame_t* _local_stack_alloc(int size, int ephemeral) {
|
||||
local_stack_frame_t* pframe = mlr_malloc_or_die(sizeof(local_stack_frame_t));
|
||||
|
||||
pframe->in_use = FALSE;
|
||||
pframe->ephemeral = ephemeral;
|
||||
pframe->size = size;
|
||||
pframe->subframe_base = 0;
|
||||
pframe->pvars = mlr_malloc_or_die(size * sizeof(local_stack_frame_entry_t));
|
||||
for (int i = 0; i < size; i++) {
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[i];
|
||||
pentry->xvalue = mlhmmv_xvalue_wrap_terminal(mv_absent());
|
||||
pentry->name = NULL;
|
||||
// Any type can be written here, unless otherwise specified by a typed definition
|
||||
pentry->type_mask = TYPE_MASK_ANY;
|
||||
}
|
||||
|
||||
return pframe;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
local_stack_frame_t* local_stack_frame_alloc(int size) {
|
||||
return _local_stack_alloc(size, FALSE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_free(local_stack_frame_t* pframe) {
|
||||
if (pframe == NULL)
|
||||
return;
|
||||
for (int i = 0; i < pframe->size; i++) {
|
||||
mlhmmv_xvalue_free(&pframe->pvars[i].xvalue);
|
||||
}
|
||||
free(pframe->pvars);
|
||||
free(pframe);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe) {
|
||||
if (!pframe->in_use) {
|
||||
pframe->in_use = TRUE;
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME NON-EPH ENTER %p %d\n", pframe, pframe->size));
|
||||
return pframe;
|
||||
} else {
|
||||
local_stack_frame_t* prv = _local_stack_alloc(pframe->size, TRUE);
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME EPH ENTER %p/%p %d\n", pframe, prv, pframe->size));
|
||||
prv->in_use = TRUE;
|
||||
return prv;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_exit (local_stack_frame_t* pframe) {
|
||||
MLR_INTERNAL_CODING_ERROR_UNLESS(mlhmmv_xvalue_is_absent_and_nonterminal(&pframe->pvars[0].xvalue));
|
||||
if (!pframe->ephemeral) {
|
||||
pframe->in_use = FALSE;
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME NON-EPH EXIT %p %d\n", pframe, pframe->size));
|
||||
} else {
|
||||
local_stack_frame_free(pframe);
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME EPH EXIT %p %d\n", pframe, pframe->size));
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
local_stack_t* local_stack_alloc() {
|
||||
local_stack_t* pstack = mlr_malloc_or_die(sizeof(local_stack_t));
|
||||
|
||||
pstack->pframes = sllv_alloc();
|
||||
|
||||
return pstack;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_free(local_stack_t* pstack) {
|
||||
if (pstack == NULL)
|
||||
return;
|
||||
for (sllve_t* pe = pstack->pframes->phead; pe != NULL; pe = pe->pnext) {
|
||||
local_stack_frame_free(pe->pvvalue);
|
||||
}
|
||||
sllv_free(pstack->pframes);
|
||||
free(pstack);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe) {
|
||||
sllv_push(pstack->pframes, pframe);
|
||||
}
|
||||
|
||||
local_stack_frame_t* local_stack_pop(local_stack_t* pstack) {
|
||||
return sllv_pop(pstack->pframes);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mv_t local_stack_frame_ref_terminal_from_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
|
||||
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
mlhmmv_xvalue_t* pbase_xval = &pentry->xvalue;
|
||||
|
||||
if (!(TYPE_MASK_MAP & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_read(pentry);
|
||||
}
|
||||
|
||||
#ifdef LOCAL_STACK_TRACE_ENABLE
|
||||
if (pbase_xval == NULL) {
|
||||
printf("VALUE IS NULL\n");
|
||||
} else if (pbase_xval->is_terminal) {
|
||||
char* s = mv_alloc_format_val(&pbase_xval->terminal_mlrval);
|
||||
printf("VALUE IS %s\n", s);
|
||||
free(s);
|
||||
} else if (pbase_xval->pnext_level == NULL) {
|
||||
LOCAL_STACK_TRACE(printf("VALUE IS EMPTY\n"));
|
||||
} else {
|
||||
printf("VALUE IS:\n");
|
||||
printf("PTR IS %p\n", pbase_xval->pnext_level);
|
||||
mlhmmv_level_print_stacked(pbase_xval->pnext_level, 0, TRUE, TRUE, "", stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
// xxx this is a mess; clean it up.
|
||||
int error = 0;
|
||||
// Maybe null
|
||||
mlhmmv_xvalue_t* pxval;
|
||||
if (pmvkeys == NULL || pmvkeys->length == 0) {
|
||||
pxval = pbase_xval;
|
||||
} else {
|
||||
if (pbase_xval->is_terminal) {
|
||||
return mv_absent();
|
||||
} else {
|
||||
pxval = mlhmmv_level_look_up_and_ref_xvalue(pbase_xval->pnext_level, pmvkeys, &error);
|
||||
}
|
||||
}
|
||||
if (pxval != NULL && pxval->is_terminal) {
|
||||
return pxval->terminal_mlrval;
|
||||
} else {
|
||||
return mv_absent();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mlhmmv_xvalue_t* local_stack_frame_ref_extended_from_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
|
||||
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
mlhmmv_xvalue_t* pmvalue = &pentry->xvalue;
|
||||
|
||||
if (!(TYPE_MASK_MAP & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_read(pentry);
|
||||
}
|
||||
|
||||
#ifdef LOCAL_STACK_TRACE_ENABLE
|
||||
if (pmvalue == NULL) {
|
||||
printf("VALUE IS NULL\n");
|
||||
} else if (pmvalue->is_terminal) {
|
||||
char* s = mv_alloc_format_val(&pmvalue->terminal_mlrval);
|
||||
printf("VALUE IS %s\n", s);
|
||||
free(s);
|
||||
} else if (pmvalue->pnext_level == NULL) {
|
||||
LOCAL_STACK_TRACE(printf("VALUE IS EMPTY\n"));
|
||||
} else {
|
||||
printf("VALUE IS:\n");
|
||||
printf("PTR IS %p\n", pmvalue->pnext_level);
|
||||
mlhmmv_level_print_stacked(pmvalue->pnext_level, 0, TRUE, TRUE, "", stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pmvkeys == NULL) { // base-level access
|
||||
return pmvalue;
|
||||
} else {
|
||||
int error = 0;
|
||||
// Maybe null
|
||||
return mlhmmv_level_look_up_and_ref_xvalue(pmvalue->pnext_level, pmvkeys, &error);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_define_terminal(local_stack_frame_t* pframe, char* variable_name,
|
||||
int vardef_frame_relative_index, int type_mask, mv_t val)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "DEFINE", TRUE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
|
||||
pentry->name = variable_name; // no strdup, for performance -- caller must ensure extent
|
||||
pentry->type_mask = type_mask;
|
||||
|
||||
if (!(type_mask_from_mv(&val) & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &val);
|
||||
}
|
||||
|
||||
mlhmmv_xvalue_free(&pentry->xvalue);
|
||||
|
||||
if (mv_is_absent(&val)) {
|
||||
mv_free(&val); // xxx doc ownership semantics at header file
|
||||
} else {
|
||||
pentry->xvalue = mlhmmv_xvalue_wrap_terminal(val); // xxx deep-copy?
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_define_extended(local_stack_frame_t* pframe, char* variable_name,
|
||||
int vardef_frame_relative_index, int type_mask, mlhmmv_xvalue_t xval)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "ASSIGN", TRUE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
|
||||
pentry->name = variable_name; // no strdup, for performance -- caller must ensure extent
|
||||
pentry->type_mask = type_mask;
|
||||
|
||||
if (xval.is_terminal) {
|
||||
if (!(type_mask_from_mv(&xval.terminal_mlrval) & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &xval.terminal_mlrval);
|
||||
}
|
||||
} else {
|
||||
if (!(TYPE_MASK_MAP & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &xval.terminal_mlrval);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mlhmmv_xvalue_is_absent_and_nonterminal(&xval)) {
|
||||
mlhmmv_xvalue_free(&pentry->xvalue);
|
||||
pentry->xvalue = xval;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_assign_terminal_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys,
|
||||
mv_t terminal_value)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "ASSIGN", TRUE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
|
||||
if (!(TYPE_MASK_MAP & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &terminal_value);
|
||||
}
|
||||
|
||||
mlhmmv_xvalue_t* pmvalue = &pentry->xvalue;
|
||||
|
||||
if (pmvalue->is_terminal) {
|
||||
mv_free(&pmvalue->terminal_mlrval);
|
||||
*pmvalue = mlhmmv_xvalue_alloc_empty_map();
|
||||
}
|
||||
mlhmmv_level_put_terminal(pmvalue->pnext_level, pmvkeys->phead, &terminal_value);
|
||||
|
||||
LOCAL_STACK_TRACE(printf("VALUE IS:\n"));
|
||||
LOCAL_STACK_TRACE(mlhmmv_level_print_stacked(pmvalue->pnext_level, 0, TRUE, TRUE, "", stdout));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_assign_extended_nonindexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, mlhmmv_xvalue_t xval)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "ASSIGN", TRUE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
|
||||
if (xval.is_terminal) {
|
||||
if (!(type_mask_from_mv(&xval.terminal_mlrval) & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &xval.terminal_mlrval);
|
||||
}
|
||||
} else {
|
||||
if (!(TYPE_MASK_MAP & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &xval.terminal_mlrval);
|
||||
}
|
||||
}
|
||||
|
||||
mlhmmv_xvalue_free(&pentry->xvalue);
|
||||
pentry->xvalue = xval;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_assign_extended_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys,
|
||||
mlhmmv_xvalue_t new_value)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "ASSIGN", TRUE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
|
||||
if (!(TYPE_MASK_MAP & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_xmismatch_for_write(pentry, &new_value);
|
||||
}
|
||||
|
||||
mlhmmv_xvalue_t* pmvalue = &pentry->xvalue;
|
||||
|
||||
if (pmvalue->is_terminal) {
|
||||
mv_free(&pmvalue->terminal_mlrval);
|
||||
*pmvalue = mlhmmv_xvalue_alloc_empty_map();
|
||||
}
|
||||
mlhmmv_level_put_xvalue(pmvalue->pnext_level, pmvkeys->phead, &new_value);
|
||||
|
||||
LOCAL_STACK_TRACE(printf("VALUE IS:\n"));
|
||||
LOCAL_STACK_TRACE(mlhmmv_level_print_stacked(pmvalue->pnext_level, 0, TRUE, TRUE, "", stdout));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int local_stack_bounds_check_announce_first_call = TRUE;
|
||||
|
||||
void local_stack_bounds_check(local_stack_frame_t* pframe, char* op, int set, int vardef_frame_relative_index) {
|
||||
if (local_stack_bounds_check_announce_first_call) {
|
||||
fprintf(stderr, "%s: local-stack bounds-checking is enabled\n", MLR_GLOBALS.bargv0);
|
||||
local_stack_bounds_check_announce_first_call = FALSE;
|
||||
}
|
||||
if (vardef_frame_relative_index < 0) {
|
||||
fprintf(stderr, "OP=%s FRAME=%p IDX=%d/%d STACK UNDERFLOW\n",
|
||||
op, pframe, vardef_frame_relative_index, pframe->size);
|
||||
exit(1);
|
||||
}
|
||||
if (set && vardef_frame_relative_index == 0) {
|
||||
fprintf(stderr, "OP=%s FRAME=%p IDX=%d/%d ABSENT WRITE\n",
|
||||
op, pframe, vardef_frame_relative_index, pframe->size);
|
||||
exit(1);
|
||||
}
|
||||
if (vardef_frame_relative_index >= pframe->size) {
|
||||
fprintf(stderr, "OP=%s FRAME=%p IDX=%d/%d STACK OVERFLOW\n",
|
||||
op, pframe, vardef_frame_relative_index, pframe->size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_throw_type_mismatch_for_write(local_stack_frame_entry_t* pentry, mv_t* pval) {
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pentry->name == NULL);
|
||||
char* sval = mv_alloc_format_val_quoting_strings(pval);
|
||||
fprintf(stderr, "%s: %s type assertion for variable %s unmet by value %s with type %s.\n",
|
||||
MLR_GLOBALS.bargv0, type_mask_to_desc(pentry->type_mask), pentry->name,
|
||||
sval, mt_describe_type_simple(pval->type));
|
||||
free(sval);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void local_stack_frame_throw_type_xmismatch_for_write(local_stack_frame_entry_t* pentry, mlhmmv_xvalue_t* pxval) {
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pentry->name == NULL);
|
||||
char* sval = mv_alloc_format_val_quoting_strings(&pxval->terminal_mlrval); // xxx temp -- maybe not terminal
|
||||
fprintf(stderr, "%s: %s type assertion for variable %s unmet by value %s with type %s.\n",
|
||||
MLR_GLOBALS.bargv0, type_mask_to_desc(pentry->type_mask), pentry->name,
|
||||
sval, mlhmmv_xvalue_describe_type_simple(pxval));
|
||||
free(sval);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_throw_type_mismatch_for_read(local_stack_frame_entry_t* pentry) {
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pentry->name == NULL);
|
||||
fprintf(stderr, "%s: %s type assertion for variable %s unmet on read.\n",
|
||||
MLR_GLOBALS.bargv0, type_mask_to_desc(pentry->type_mask), pentry->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void local_stack_frame_throw_type_xmismatch_for_read(local_stack_frame_entry_t* pentry) {
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pentry->name == NULL);
|
||||
fprintf(stderr, "%s: %s type assertion for variable %s unmet on read.\n",
|
||||
MLR_GLOBALS.bargv0, type_mask_to_desc(pentry->type_mask), pentry->name);
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
#ifndef LOCAL_STACK_H
|
||||
#define LOCAL_STACK_H
|
||||
|
||||
#include "lib/mlrval.h"
|
||||
#include "containers/type_decl.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "containers/mlhmmv.h"
|
||||
|
||||
// ================================================================
|
||||
// Bound & scoped variables for use in for-loops, function bodies, and
|
||||
// subroutine bodies. Indices of local variables, and max-depth for top-level
|
||||
// statement blocks, are compted by the stack-allocator which marks up the AST
|
||||
// before the CST is built from it.
|
||||
//
|
||||
// A convention shared between the stack-allocator and this data structure is
|
||||
// that slot 0 is an absent-null which is used for reads of undefined (or
|
||||
// as-yet-undefined) local variables.
|
||||
//
|
||||
// Values assigned to a local-stack variable are owned by this container.
|
||||
// They will be freed:
|
||||
// * On overwrite, e.g. on 'x = oldval' then 'x = newval' the oldval
|
||||
// will be freed on the newval assignment, and
|
||||
// * At stack-frame exit.
|
||||
// For this reason values assigned to locals may be passed in by reference
|
||||
// if they are ephemeral, i.e. if it is desired for this container to free
|
||||
// them. Otherwise, values should be copied before being passed in.
|
||||
// ================================================================
|
||||
|
||||
// ================================================================
|
||||
typedef struct _local_stack_frame_entry_t {
|
||||
char* name; // For type-check error messages. Not strduped; the caller must ensure extent.
|
||||
mlhmmv_xvalue_t xvalue;
|
||||
int type_mask;
|
||||
} local_stack_frame_entry_t;
|
||||
|
||||
typedef struct _local_stack_frame_t {
|
||||
int in_use;
|
||||
int ephemeral;
|
||||
int size;
|
||||
int subframe_base;
|
||||
local_stack_frame_entry_t* pvars;
|
||||
} local_stack_frame_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// A stack is allocated for a top-level statement block: begin, end, or main, or
|
||||
// user-defined function/subroutine. (The latter two may be called recursively
|
||||
// in which case the in_use flag notes the need to allocate a new stack.)
|
||||
|
||||
local_stack_frame_t* local_stack_frame_alloc(int size);
|
||||
void local_stack_frame_free(local_stack_frame_t* pframe);
|
||||
|
||||
// ================================================================
|
||||
//#define LOCAL_STACK_TRACE_ENABLE
|
||||
//#define LOCAL_STACK_BOUNDS_CHECK_ENABLE
|
||||
|
||||
void local_stack_bounds_check(local_stack_frame_t* pframe, char* op, int set, int vardef_frame_relative_index);
|
||||
#ifdef LOCAL_STACK_BOUNDS_CHECK_ENABLE
|
||||
#define LOCAL_STACK_BOUNDS_CHECK(pframe, op, set, vardef_frame_relative_index) \
|
||||
local_stack_bounds_check((pframe), (op), (set), (vardef_frame_relative_index))
|
||||
#else
|
||||
#define LOCAL_STACK_BOUNDS_CHECK(pframe, op, set, vardef_frame_relative_index)
|
||||
#endif
|
||||
|
||||
#ifdef LOCAL_STACK_TRACE_ENABLE
|
||||
#define LOCAL_STACK_TRACE(p) p
|
||||
#else
|
||||
#define LOCAL_STACK_TRACE(p)
|
||||
#endif
|
||||
|
||||
// These are unconditional. With the single added character 'X' they can be
|
||||
// used to focus verbosity at specific callsites for dev/debug.
|
||||
#define LOCAL_STACK_BOUNDS_CHECKX(pframe, op, set, vardef_frame_relative_index) \
|
||||
local_stack_bounds_check((pframe), (op), (set), (vardef_frame_relative_index))
|
||||
|
||||
#define LOCAL_STACK_TRACEX(p) p
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Sets/clears the in-use flag for top-level statement blocks, and verifies the
|
||||
// contract for absent-null at slot 0.
|
||||
|
||||
// For non-recursive functions/subroutines the enter method sets the in-use flag
|
||||
// and returns its argument; the exit method clears that flag. For recursively
|
||||
// invoked functions/subroutines the enter method returns another stack of the
|
||||
// same size, and the exit method frees that.
|
||||
//
|
||||
// The reason we don't simply always allocate is that begin/main/end statements
|
||||
// are never recursive, and most functions and subroutines are not recursive, so
|
||||
// most of the time there will be a single frame for each. We allocate that once
|
||||
// at startup, reuse it on every record, and free it at exit -- rather than
|
||||
// allocating and freeing frames on every record.
|
||||
|
||||
local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe);
|
||||
void local_stack_frame_exit(local_stack_frame_t* pframe);
|
||||
void local_stack_frame_throw_type_mismatch_for_write(local_stack_frame_entry_t* pentry, mv_t* pval);
|
||||
void local_stack_frame_throw_type_xmismatch_for_write(local_stack_frame_entry_t* pentry, mlhmmv_xvalue_t* pxval);
|
||||
void local_stack_frame_throw_type_mismatch_for_read(local_stack_frame_entry_t* pentry);
|
||||
void local_stack_frame_throw_type_xmismatch_for_read(local_stack_frame_entry_t* pentry);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline mv_t local_stack_frame_get_terminal_from_nonindexed(local_stack_frame_t* pframe, // move to reference semantics
|
||||
int vardef_frame_relative_index)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
mlhmmv_xvalue_t* pvalue = &pentry->xvalue;
|
||||
if (pvalue != NULL && pvalue->is_terminal) {
|
||||
return pvalue->terminal_mlrval;
|
||||
} else {
|
||||
return mv_absent();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline void local_stack_frame_assign_terminal_nonindexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, mv_t val)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "ASSIGN", TRUE, vardef_frame_relative_index);
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
|
||||
if (!(type_mask_from_mv(&val) & pentry->type_mask)) {
|
||||
local_stack_frame_throw_type_mismatch_for_write(pentry, &val);
|
||||
}
|
||||
|
||||
mlhmmv_xvalue_free(&pentry->xvalue);
|
||||
pentry->xvalue = mlhmmv_xvalue_wrap_terminal(val); // xxx deep-copy?
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline mlhmmv_xvalue_t* local_stack_frame_ref_extended_from_nonindexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
|
||||
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
mlhmmv_xvalue_t* pmvalue = &pentry->xvalue;
|
||||
|
||||
return pmvalue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mv_t local_stack_frame_ref_terminal_from_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys);
|
||||
|
||||
mlhmmv_xvalue_t* local_stack_frame_ref_extended_from_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys);
|
||||
|
||||
void local_stack_frame_define_terminal(local_stack_frame_t* pframe, char* variable_name,
|
||||
int vardef_frame_relative_index, int type_mask, mv_t val);
|
||||
|
||||
void local_stack_frame_define_extended(local_stack_frame_t* pframe, char* variable_name,
|
||||
int vardef_frame_relative_index, int type_mask, mlhmmv_xvalue_t xval);
|
||||
|
||||
void local_stack_frame_assign_extended_nonindexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, mlhmmv_xvalue_t xval);
|
||||
|
||||
void local_stack_frame_assign_terminal_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys,
|
||||
mv_t terminal_value);
|
||||
|
||||
void local_stack_frame_assign_extended_indexed(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys,
|
||||
mlhmmv_xvalue_t terminal_value);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Frames are entered/exited for each curly-braced statement block, including
|
||||
// the top-level block itself as well as ifs/fors/whiles.
|
||||
|
||||
static inline void local_stack_subframe_enter(local_stack_frame_t* pframe, int count) {
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK SUBFRAME %p ENTER %d->%d\n",
|
||||
pframe, pframe->subframe_base, pframe->subframe_base+count));
|
||||
local_stack_frame_entry_t* psubframe = &pframe->pvars[pframe->subframe_base];
|
||||
for (int i = 0; i < count; i++) {
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p CLEAR %d\n", pframe, pframe->subframe_base+i));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "CLEAR", FALSE, pframe->subframe_base+i);
|
||||
local_stack_frame_entry_t* pentry = &psubframe[i];
|
||||
|
||||
mlhmmv_xvalue_reset(&pentry->xvalue);
|
||||
|
||||
pentry->type_mask = TYPE_MASK_ANY;
|
||||
}
|
||||
pframe->subframe_base += count;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline void local_stack_subframe_exit(local_stack_frame_t* pframe, int count) {
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK SUBFRAME %p EXIT %d->%d\n",
|
||||
pframe, pframe->subframe_base, pframe->subframe_base-count));
|
||||
pframe->subframe_base -= count;
|
||||
local_stack_frame_entry_t* psubframe = &pframe->pvars[pframe->subframe_base];
|
||||
for (int i = 0; i < count; i++) {
|
||||
local_stack_frame_entry_t* pentry = &psubframe[i];
|
||||
mlhmmv_xvalue_free(&pentry->xvalue);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
typedef struct _local_stack_t {
|
||||
sllv_t* pframes;
|
||||
} local_stack_t;
|
||||
|
||||
local_stack_t* local_stack_alloc();
|
||||
void local_stack_free(local_stack_t* pstack);
|
||||
|
||||
void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe);
|
||||
|
||||
local_stack_frame_t* local_stack_pop(local_stack_t* pstack);
|
||||
|
||||
static inline local_stack_frame_t* local_stack_get_top_frame(local_stack_t* pstack) {
|
||||
return pstack->pframes->phead->pvvalue;
|
||||
}
|
||||
|
||||
#endif // LOCAL_STACK_H
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "loop_stack.h"
|
||||
|
||||
#define INITIAL_SIZE 32
|
||||
|
||||
// Example states:
|
||||
|
||||
// num_allocated = 4 num_allocated = 4 num_allocated = 4 num_allocated = 4
|
||||
// num_used = 1 num_used = 2 num_used = 3 num_used = 4
|
||||
// num_used_minus_one = 0 num_used_minus_one = 1 num_used_minus_one = 2 num_used_minus_one = 3
|
||||
//
|
||||
// +---+ +---+ +---+ +---+
|
||||
// | 2 | 0 <--- top | 2 | 0 | 2 | 0 | 2 | 0
|
||||
// +---+ +---+ +---+ +---+
|
||||
// |///| 1 | 0 | 1 <--- top | 0 | 1 | 0 |
|
||||
// +---+ +---+ +---+ +---+
|
||||
// |///| 2 |///| 2 | 4 | 2 <--- top | 4 |
|
||||
// +---+ +---+ +---+ +---+
|
||||
// |///| 3 |///| 3 |///| 3 | 6 | 3 <--- top
|
||||
// +---+ +---+ +---+ +---+
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
loop_stack_t* loop_stack_alloc() {
|
||||
loop_stack_t* pstack = mlr_malloc_or_die(sizeof(loop_stack_t));
|
||||
|
||||
// Guard zone of one. As noted in the header file, set/get are intentionally not bounds-checked.
|
||||
// If set is called without push, or after final pop, we can at least not corrupt other code.
|
||||
pstack->num_used_minus_one = 0;
|
||||
pstack->num_allocated = INITIAL_SIZE;
|
||||
|
||||
pstack->pframes = mlr_malloc_or_die(pstack->num_allocated * sizeof(int));
|
||||
memset(pstack->pframes, 0, pstack->num_allocated * sizeof(int));
|
||||
|
||||
return pstack;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void loop_stack_free(loop_stack_t* pstack) {
|
||||
if (pstack == NULL)
|
||||
return;
|
||||
free(pstack->pframes);
|
||||
free(pstack);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void loop_stack_push(loop_stack_t* pstack) {
|
||||
if (pstack->num_used_minus_one >= pstack->num_allocated - 1) {
|
||||
pstack->num_allocated += INITIAL_SIZE;
|
||||
pstack->pframes = mlr_realloc_or_die(pstack->pframes, pstack->num_allocated * sizeof(int));
|
||||
}
|
||||
pstack->num_used_minus_one++;
|
||||
pstack->pframes[pstack->num_used_minus_one] = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int loop_stack_pop(loop_stack_t* pstack) {
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pstack->num_used_minus_one <= 0);
|
||||
int rv = pstack->pframes[pstack->num_used_minus_one];
|
||||
pstack->num_used_minus_one--;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Not bounds-checked, as noted in the header file.
|
||||
void loop_stack_set(loop_stack_t* pstack, int bits) {
|
||||
pstack->pframes[pstack->num_used_minus_one] |= bits;
|
||||
}
|
||||
void loop_stack_clear(loop_stack_t* pstack, int bits) {
|
||||
pstack->pframes[pstack->num_used_minus_one] &= ~bits;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Not bounds-checked, as noted in the header file.
|
||||
int loop_stack_get(loop_stack_t* pstack) {
|
||||
return pstack->pframes[pstack->num_used_minus_one];
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
// Holds broken/continued flags for loops (for-srec, for-oosvar, while, do-while).
|
||||
|
||||
#ifndef LOOP_STACK_H
|
||||
#define LOOP_STACK_H
|
||||
|
||||
#define LOOP_BROKEN 0x8000
|
||||
#define LOOP_CONTINUED 0x0100
|
||||
|
||||
typedef struct _loop_stack_t {
|
||||
int num_used_minus_one;
|
||||
int num_allocated;
|
||||
int* pframes;
|
||||
} loop_stack_t;
|
||||
|
||||
loop_stack_t* loop_stack_alloc();
|
||||
void loop_stack_free(loop_stack_t* pstack);
|
||||
|
||||
// To be used on entry to loop handler.
|
||||
void loop_stack_push(loop_stack_t* pstack);
|
||||
|
||||
// To be used on exit from loop handler.
|
||||
int loop_stack_pop(loop_stack_t* pstack);
|
||||
|
||||
// To be used by break/continue handler.
|
||||
// NOTE: For efficiency the stack is **NOT** bounds-checked here. E.g. if set is done before a push,
|
||||
// or after an emptying pop, behavior is unspecified.
|
||||
void loop_stack_set(loop_stack_t* pstack, int bits);
|
||||
void loop_stack_clear(loop_stack_t* pstack, int bits);
|
||||
|
||||
// To be used by loop handler.
|
||||
// NOTE: For efficiency the stack is **NOT** bounds-checked here. E.g. if set is done before a push,
|
||||
// or after an emptying pop, behavior is unspecified.
|
||||
int loop_stack_get(loop_stack_t* pstack);
|
||||
|
||||
#endif // LOOP_STACK_H
|
||||
|
|
@ -1,747 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "lib/string_builder.h"
|
||||
#include "containers/hss.h"
|
||||
#include "containers/slls.h"
|
||||
#include "containers/lrec.h"
|
||||
|
||||
#define SB_ALLOC_LENGTH 256
|
||||
|
||||
static lrece_t* lrec_find_entry(lrec_t* prec, char* key);
|
||||
static void lrec_link_at_head(lrec_t* prec, lrece_t* pe);
|
||||
static void lrec_link_at_tail(lrec_t* prec, lrece_t* pe);
|
||||
|
||||
static void lrec_unbacked_free(lrec_t* prec);
|
||||
static void lrec_free_single_line_backing(lrec_t* prec);
|
||||
static void lrec_free_csv_backing(lrec_t* prec);
|
||||
static void lrec_free_multiline_backing(lrec_t* prec);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lrec_t* lrec_unbacked_alloc() {
|
||||
lrec_t* prec = mlr_malloc_or_die(sizeof(lrec_t));
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->pfree_backing_func = lrec_unbacked_free;
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_dkvp_alloc(char* line) {
|
||||
lrec_t* prec = mlr_malloc_or_die(sizeof(lrec_t));
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->psingle_line = line;
|
||||
prec->pfree_backing_func = lrec_free_single_line_backing;
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_nidx_alloc(char* line) {
|
||||
lrec_t* prec = mlr_malloc_or_die(sizeof(lrec_t));
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->psingle_line = line;
|
||||
prec->pfree_backing_func = lrec_free_single_line_backing;
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_csvlite_alloc(char* data_line) {
|
||||
lrec_t* prec = mlr_malloc_or_die(sizeof(lrec_t));
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->psingle_line = data_line;
|
||||
prec->pfree_backing_func = lrec_free_csv_backing;
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_csv_alloc(char* data_line) {
|
||||
lrec_t* prec = mlr_malloc_or_die(sizeof(lrec_t));
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->psingle_line = data_line;
|
||||
prec->pfree_backing_func = lrec_free_csv_backing;
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_xtab_alloc(slls_t* pxtab_lines) {
|
||||
lrec_t* prec = mlr_malloc_or_die(sizeof(lrec_t));
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->pxtab_lines = pxtab_lines;
|
||||
prec->pfree_backing_func = lrec_free_multiline_backing;
|
||||
return prec;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lrec_free_contents(lrec_t* prec) {
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; /*pe = pe->pnext*/) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
free(pe->value);
|
||||
lrece_t* ope = pe;
|
||||
pe = pe->pnext;
|
||||
free(ope);
|
||||
}
|
||||
prec->pfree_backing_func(prec);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_clear(lrec_t* prec) {
|
||||
if (prec == NULL)
|
||||
return;
|
||||
lrec_free_contents(prec);
|
||||
memset(prec, 0, sizeof(lrec_t));
|
||||
prec->pfree_backing_func = lrec_unbacked_free;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_free(lrec_t* prec) {
|
||||
if (prec == NULL)
|
||||
return;
|
||||
lrec_free_contents(prec);
|
||||
free(prec);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lrec_t* lrec_copy(lrec_t* pinrec) {
|
||||
lrec_t* poutrec = lrec_unbacked_alloc();
|
||||
for (lrece_t* pe = pinrec->phead; pe != NULL; pe = pe->pnext) {
|
||||
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
|
||||
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
|
||||
}
|
||||
return poutrec;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_put(lrec_t* prec, char* key, char* value, char free_flags) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
|
||||
if (pe != NULL) {
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
if (free_flags & FREE_ENTRY_KEY)
|
||||
free(key);
|
||||
pe->value = value;
|
||||
if (free_flags & FREE_ENTRY_VALUE)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
else
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
} else {
|
||||
pe = mlr_malloc_or_die(sizeof(lrece_t));
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pe->quote_flags = 0;
|
||||
|
||||
if (prec->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
prec->phead = pe;
|
||||
prec->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = prec->ptail;
|
||||
pe->pnext = NULL;
|
||||
prec->ptail->pnext = pe;
|
||||
prec->ptail = pe;
|
||||
}
|
||||
prec->field_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void lrec_put_ext(lrec_t* prec, char* key, char* value, char free_flags, char quote_flags) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
|
||||
if (pe != NULL) {
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
if (free_flags & FREE_ENTRY_KEY)
|
||||
free(key);
|
||||
pe->value = value;
|
||||
if (free_flags & FREE_ENTRY_VALUE)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
else
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
} else {
|
||||
pe = mlr_malloc_or_die(sizeof(lrece_t));
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pe->quote_flags = quote_flags;
|
||||
|
||||
if (prec->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
prec->phead = pe;
|
||||
prec->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = prec->ptail;
|
||||
pe->pnext = NULL;
|
||||
prec->ptail->pnext = pe;
|
||||
prec->ptail = pe;
|
||||
}
|
||||
prec->field_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void lrec_prepend(lrec_t* prec, char* key, char* value, char free_flags) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
|
||||
if (pe != NULL) {
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
pe->value = value;
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
if (free_flags & FREE_ENTRY_VALUE)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
} else {
|
||||
pe = mlr_malloc_or_die(sizeof(lrece_t));
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pe->quote_flags = 0;
|
||||
|
||||
if (prec->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
prec->phead = pe;
|
||||
prec->ptail = pe;
|
||||
} else {
|
||||
pe->pnext = prec->phead;
|
||||
pe->pprev = NULL;
|
||||
prec->phead->pprev = pe;
|
||||
prec->phead = pe;
|
||||
}
|
||||
prec->field_count++;
|
||||
}
|
||||
}
|
||||
|
||||
lrece_t* lrec_put_after(lrec_t* prec, lrece_t* pd, char* key, char* value, char free_flags) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
|
||||
if (pe != NULL) { // Overwrite
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
pe->value = value;
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
if (free_flags & FREE_ENTRY_VALUE)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
} else { // Insert after specified entry
|
||||
pe = mlr_malloc_or_die(sizeof(lrece_t));
|
||||
pe->key = key;
|
||||
pe->value = value;
|
||||
pe->free_flags = free_flags;
|
||||
pe->quote_flags = 0;
|
||||
|
||||
if (pd->pnext == NULL) { // Append at end of list
|
||||
pd->pnext = pe;
|
||||
pe->pprev = pd;
|
||||
pe->pnext = NULL;
|
||||
prec->ptail = pe;
|
||||
|
||||
} else {
|
||||
lrece_t* pf = pd->pnext;
|
||||
pd->pnext = pe;
|
||||
pf->pprev = pe;
|
||||
pe->pprev = pd;
|
||||
pe->pnext = pf;
|
||||
}
|
||||
|
||||
prec->field_count++;
|
||||
}
|
||||
return pe;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
char* lrec_get(lrec_t* prec, char* key) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
if (pe != NULL) {
|
||||
return pe->value;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char* lrec_get_pff(lrec_t* prec, char* key, char** ppfree_flags) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
if (pe != NULL) {
|
||||
*ppfree_flags = &pe->free_flags;
|
||||
return pe->value;
|
||||
} else {
|
||||
*ppfree_flags = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char* lrec_get_ext(lrec_t* prec, char* key, lrece_t** ppentry) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
if (pe != NULL) {
|
||||
*ppentry = pe;
|
||||
return pe->value;
|
||||
} else {
|
||||
*ppentry = NULL;;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lrece_t* lrec_get_pair_by_position(lrec_t* prec, int position) { // 1-up not 0-up
|
||||
if (position <= 0 || position > prec->field_count) {
|
||||
return NULL;
|
||||
}
|
||||
int sought_index = position - 1;
|
||||
int found_index = 0;
|
||||
lrece_t* pe = NULL;
|
||||
for (
|
||||
found_index = 0, pe = prec->phead;
|
||||
pe != NULL;
|
||||
found_index++, pe = pe->pnext
|
||||
) {
|
||||
if (found_index == sought_index) {
|
||||
return pe;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
|
||||
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char* lrec_get_key_by_position(lrec_t* prec, int position) { // 1-up not 0-up
|
||||
lrece_t* pe = lrec_get_pair_by_position(prec, position);
|
||||
if (pe == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
return pe->key;
|
||||
}
|
||||
}
|
||||
|
||||
char* lrec_get_value_by_position(lrec_t* prec, int position) { // 1-up not 0-up
|
||||
lrece_t* pe = lrec_get_pair_by_position(prec, position);
|
||||
if (pe == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
return pe->value;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_remove(lrec_t* prec, char* key) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
if (pe == NULL)
|
||||
return;
|
||||
|
||||
lrec_unlink(prec, pe);
|
||||
|
||||
if (pe->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pe->key);
|
||||
}
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
|
||||
free(pe);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_remove_by_position(lrec_t* prec, int position) { // 1-up not 0-up
|
||||
lrece_t* pe = lrec_get_pair_by_position(prec, position);
|
||||
if (pe == NULL)
|
||||
return;
|
||||
|
||||
lrec_unlink(prec, pe);
|
||||
|
||||
if (pe->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pe->key);
|
||||
}
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
|
||||
free(pe);
|
||||
}
|
||||
|
||||
// Before:
|
||||
// "x" => "3"
|
||||
// "y" => "4" <-- pold
|
||||
// "z" => "5" <-- pnew
|
||||
//
|
||||
// Rename y to z
|
||||
//
|
||||
// After:
|
||||
// "x" => "3"
|
||||
// "z" => "4"
|
||||
//
|
||||
void lrec_rename(lrec_t* prec, char* old_key, char* new_key, int new_needs_freeing) {
|
||||
|
||||
lrece_t* pold = lrec_find_entry(prec, old_key);
|
||||
if (pold != NULL) {
|
||||
lrece_t* pnew = lrec_find_entry(prec, new_key);
|
||||
|
||||
if (pnew == NULL) { // E.g. rename "x" to "y" when "y" is not present
|
||||
if (pold->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pold->key);
|
||||
pold->key = new_key;
|
||||
if (!new_needs_freeing)
|
||||
pold->free_flags &= ~FREE_ENTRY_KEY;
|
||||
} else {
|
||||
pold->key = new_key;
|
||||
if (new_needs_freeing)
|
||||
pold->free_flags |= FREE_ENTRY_KEY;
|
||||
}
|
||||
|
||||
} else { // E.g. rename "x" to "y" when "y" is already present
|
||||
if (pnew->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pnew->value);
|
||||
}
|
||||
if (pold->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pold->key);
|
||||
pold->free_flags &= ~FREE_ENTRY_KEY;
|
||||
}
|
||||
pold->key = new_key;
|
||||
if (new_needs_freeing)
|
||||
pold->free_flags |= FREE_ENTRY_KEY;
|
||||
else
|
||||
pold->free_flags &= ~FREE_ENTRY_KEY;
|
||||
lrec_unlink(prec, pnew);
|
||||
free(pnew);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cases:
|
||||
// 1. Rename field at position 3 from "x" to "y when "y" does not exist elsewhere in the srec
|
||||
// 2. Rename field at position 3 from "x" to "y when "y" does exist elsewhere in the srec
|
||||
// Note: position is 1-up not 0-up
|
||||
void lrec_rename_at_position(lrec_t* prec, int position, char* new_key, int new_needs_freeing){
|
||||
lrece_t* pe = lrec_get_pair_by_position(prec, position);
|
||||
if (pe == NULL) {
|
||||
if (new_needs_freeing) {
|
||||
free(new_key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
lrece_t* pother = lrec_find_entry(prec, new_key);
|
||||
|
||||
if (pe->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pe->key);
|
||||
}
|
||||
pe->key = new_key;
|
||||
if (new_needs_freeing) {
|
||||
pe->free_flags |= FREE_ENTRY_KEY;
|
||||
} else {
|
||||
pe->free_flags &= ~FREE_ENTRY_KEY;
|
||||
}
|
||||
if (pother != NULL) {
|
||||
lrec_unlink(prec, pother);
|
||||
free(pother);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_move_to_head(lrec_t* prec, char* key) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
if (pe == NULL)
|
||||
return;
|
||||
|
||||
lrec_unlink(prec, pe);
|
||||
lrec_link_at_head(prec, pe);
|
||||
}
|
||||
|
||||
void lrec_move_to_tail(lrec_t* prec, char* key) {
|
||||
lrece_t* pe = lrec_find_entry(prec, key);
|
||||
if (pe == NULL)
|
||||
return;
|
||||
|
||||
lrec_unlink(prec, pe);
|
||||
lrec_link_at_tail(prec, pe);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Simply rename the first (at most) n positions where n is the length of pnames.
|
||||
//
|
||||
// Possible complications:
|
||||
//
|
||||
// * pnames itself contains duplicates -- we require this as invariant-check from the caller since (for performance)
|
||||
// we don't want to check this on every record processed.
|
||||
//
|
||||
// * pnames has length less than the current record and one of the new names becomes a clash with an existing name.
|
||||
// Example:
|
||||
// - Input record has names "a,b,c,d,e".
|
||||
// - pnames is "d,x,f"
|
||||
// - We then construct the invalid "d,x,f,d,e" -- we need to detect and unset the second 'd' field.
|
||||
|
||||
void lrec_label(lrec_t* prec, slls_t* pnames_as_list, hss_t* pnames_as_set) {
|
||||
lrece_t* pe = prec->phead;
|
||||
sllse_t* pn = pnames_as_list->phead;
|
||||
|
||||
// Process the labels list
|
||||
for ( ; pe != NULL && pn != NULL; pe = pe->pnext, pn = pn->pnext) {
|
||||
char* new_name = pn->value;
|
||||
|
||||
if (pe->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pe->key);
|
||||
}
|
||||
pe->key = mlr_strdup_or_die(new_name);;
|
||||
pe->free_flags |= FREE_ENTRY_KEY;
|
||||
}
|
||||
|
||||
// Process the remaining fields in the record beyond those affected by the new-labels list
|
||||
for ( ; pe != NULL; ) {
|
||||
char* name = pe->key;
|
||||
if (hss_has(pnames_as_set, name)) {
|
||||
lrece_t* pnext = pe->pnext;
|
||||
if (pe->free_flags & FREE_ENTRY_KEY) {
|
||||
free(pe->key);
|
||||
}
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
lrec_unlink(prec, pe);
|
||||
free(pe);
|
||||
pe = pnext;
|
||||
} else {
|
||||
pe = pe->pnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrece_update_value(lrece_t* pe, char* new_value, int new_needs_freeing) {
|
||||
if (pe == NULL) {
|
||||
return;
|
||||
}
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE) {
|
||||
free(pe->value);
|
||||
}
|
||||
pe->value = new_value;
|
||||
if (new_needs_freeing)
|
||||
pe->free_flags |= FREE_ENTRY_VALUE;
|
||||
else
|
||||
pe->free_flags &= ~FREE_ENTRY_VALUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_unlink(lrec_t* prec, lrece_t* pe) {
|
||||
if (pe == prec->phead) {
|
||||
if (pe == prec->ptail) {
|
||||
prec->phead = NULL;
|
||||
prec->ptail = NULL;
|
||||
} else {
|
||||
prec->phead = pe->pnext;
|
||||
pe->pnext->pprev = NULL;
|
||||
}
|
||||
} else {
|
||||
pe->pprev->pnext = pe->pnext;
|
||||
if (pe == prec->ptail) {
|
||||
prec->ptail = pe->pprev;
|
||||
} else {
|
||||
pe->pnext->pprev = pe->pprev;
|
||||
}
|
||||
}
|
||||
prec->field_count--;
|
||||
}
|
||||
|
||||
void lrec_unlink_and_free(lrec_t* prec, lrece_t* pe) {
|
||||
if (pe->free_flags & FREE_ENTRY_KEY)
|
||||
free(pe->key);
|
||||
if (pe->free_flags & FREE_ENTRY_VALUE)
|
||||
free(pe->value);
|
||||
lrec_unlink(prec, pe);
|
||||
free(pe);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lrec_link_at_head(lrec_t* prec, lrece_t* pe) {
|
||||
|
||||
if (prec->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
prec->phead = pe;
|
||||
prec->ptail = pe;
|
||||
} else {
|
||||
// [b,c,d] + a
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = prec->phead;
|
||||
prec->phead->pprev = pe;
|
||||
prec->phead = pe;
|
||||
}
|
||||
prec->field_count++;
|
||||
}
|
||||
|
||||
static void lrec_link_at_tail(lrec_t* prec, lrece_t* pe) {
|
||||
|
||||
if (prec->phead == NULL) {
|
||||
pe->pprev = NULL;
|
||||
pe->pnext = NULL;
|
||||
prec->phead = pe;
|
||||
prec->ptail = pe;
|
||||
} else {
|
||||
pe->pprev = prec->ptail;
|
||||
pe->pnext = NULL;
|
||||
prec->ptail->pnext = pe;
|
||||
prec->ptail = pe;
|
||||
}
|
||||
prec->field_count++;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_dump(lrec_t* prec) {
|
||||
lrec_dump_fp(prec, stdout);
|
||||
}
|
||||
void lrec_dump_fp(lrec_t* prec, FILE* fp) {
|
||||
if (prec == NULL) {
|
||||
fprintf(fp, "NULL\n");
|
||||
return;
|
||||
}
|
||||
fprintf(fp, "field_count = %d\n", prec->field_count);
|
||||
fprintf(fp, "| phead: %16p | ptail %16p\n", prec->phead, prec->ptail);
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
const char* key_string = (pe == NULL) ? "none" :
|
||||
pe->key == NULL ? "null" :
|
||||
pe->key;
|
||||
const char* value_string = (pe == NULL) ? "none" :
|
||||
pe->value == NULL ? "null" :
|
||||
pe->value;
|
||||
fprintf(fp,
|
||||
"| prev: %16p curr: %16p next: %16p | key: %12s | value: %12s |\n",
|
||||
pe->pprev, pe, pe->pnext,
|
||||
key_string, value_string);
|
||||
}
|
||||
}
|
||||
|
||||
void lrec_dump_titled(char* msg, lrec_t* prec) {
|
||||
printf("%s:\n", msg);
|
||||
lrec_dump(prec);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void lrec_pointer_dump(lrec_t* prec) {
|
||||
printf("prec %p\n", prec);
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
printf(" pe %p k %p v %p\n", pe, pe->key, pe->value);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void lrec_unbacked_free(lrec_t* prec) {
|
||||
}
|
||||
|
||||
static void lrec_free_single_line_backing(lrec_t* prec) {
|
||||
free(prec->psingle_line);
|
||||
}
|
||||
|
||||
static void lrec_free_csv_backing(lrec_t* prec) {
|
||||
free(prec->psingle_line);
|
||||
}
|
||||
|
||||
static void lrec_free_multiline_backing(lrec_t* prec) {
|
||||
slls_free(prec->pxtab_lines);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Note on efficiency:
|
||||
//
|
||||
// I was imagining/hoping that strcmp has additional optimizations (e.g.
|
||||
// hand-coded in assembly), so I don't *want* to re-implement it (i.e. I
|
||||
// probably can't outperform it).
|
||||
//
|
||||
// But actual experiments show I get about a 1-2% performance gain doing it
|
||||
// myself (on my particular system).
|
||||
|
||||
static lrece_t* lrec_find_entry(lrec_t* prec, char* key) {
|
||||
#if 1
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
char* pa = pe->key;
|
||||
char* pb = key;
|
||||
while (*pa && *pb && (*pa == *pb)) {
|
||||
pa++;
|
||||
pb++;
|
||||
}
|
||||
if (*pa == 0 && *pb == 0)
|
||||
return pe;
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext)
|
||||
if (streq(pe->key, key))
|
||||
return pe;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lrec_t* lrec_literal_1(char* k1, char* v1) {
|
||||
lrec_t* prec = lrec_unbacked_alloc();
|
||||
lrec_put(prec, k1, v1, NO_FREE);
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_literal_2(char* k1, char* v1, char* k2, char* v2) {
|
||||
lrec_t* prec = lrec_unbacked_alloc();
|
||||
lrec_put(prec, k1, v1, NO_FREE);
|
||||
lrec_put(prec, k2, v2, NO_FREE);
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_literal_3(char* k1, char* v1, char* k2, char* v2, char* k3, char* v3) {
|
||||
lrec_t* prec = lrec_unbacked_alloc();
|
||||
lrec_put(prec, k1, v1, NO_FREE);
|
||||
lrec_put(prec, k2, v2, NO_FREE);
|
||||
lrec_put(prec, k3, v3, NO_FREE);
|
||||
return prec;
|
||||
}
|
||||
|
||||
lrec_t* lrec_literal_4(char* k1, char* v1, char* k2, char* v2, char* k3, char* v3, char* k4, char* v4) {
|
||||
lrec_t* prec = lrec_unbacked_alloc();
|
||||
lrec_put(prec, k1, v1, NO_FREE);
|
||||
lrec_put(prec, k2, v2, NO_FREE);
|
||||
lrec_put(prec, k3, v3, NO_FREE);
|
||||
lrec_put(prec, k4, v4, NO_FREE);
|
||||
return prec;
|
||||
}
|
||||
|
||||
void lrec_print(lrec_t* prec) {
|
||||
FILE* output_stream = stdout;
|
||||
char ors = '\n';
|
||||
char ofs = ',';
|
||||
char ops = '=';
|
||||
if (prec == NULL) {
|
||||
fputs("NULL", output_stream);
|
||||
fputc(ors, output_stream);
|
||||
return;
|
||||
}
|
||||
int nf = 0;
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (nf > 0)
|
||||
fputc(ofs, output_stream);
|
||||
fputs(pe->key, output_stream);
|
||||
fputc(ops, output_stream);
|
||||
fputs(pe->value, output_stream);
|
||||
nf++;
|
||||
}
|
||||
fputc(ors, output_stream);
|
||||
}
|
||||
|
||||
char* lrec_sprint(lrec_t* prec, char* ors, char* ofs, char* ops) {
|
||||
string_builder_t* psb = sb_alloc(SB_ALLOC_LENGTH);
|
||||
if (prec == NULL) {
|
||||
sb_append_string(psb, "NULL");
|
||||
} else {
|
||||
int nf = 0;
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (nf > 0)
|
||||
sb_append_string(psb, ofs);
|
||||
sb_append_string(psb, pe->key);
|
||||
sb_append_string(psb, ops);
|
||||
sb_append_string(psb, pe->value);
|
||||
nf++;
|
||||
}
|
||||
sb_append_string(psb, ors);
|
||||
}
|
||||
char* rv = sb_finish(psb);
|
||||
sb_free(psb);
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
// ================================================================
|
||||
// This is a hashless implementation of insertion-ordered key-value pairs for
|
||||
// Miller's fundamental record data structure. It implements the same
|
||||
// interface as the hashed version (see lhmss.h).
|
||||
//
|
||||
// Design:
|
||||
//
|
||||
// * It keeps a doubly-linked list of key-value pairs.
|
||||
// * No hash functions are computed when the map is written to or read from.
|
||||
// * Gets are implemented by sequential scan through the list: given a key,
|
||||
// the key-value pairs are scanned through until a match is (or is not) found.
|
||||
// * Performance improvement of 10-15% percent over lhmss is found (for test data).
|
||||
//
|
||||
// Motivation:
|
||||
//
|
||||
// * The use case for records in Miller is that *all* fields are read from
|
||||
// strings & written to strings (split/join), while only *some* fields are
|
||||
// operated on.
|
||||
//
|
||||
// * Meanwhile there are few repeated accesses to a given record: the
|
||||
// access-to-construct ratio is quite low for Miller data records. Miller
|
||||
// instantiates thousands, millions, billions of records (depending on the
|
||||
// input data) but accesses each record only once per mapping operation.
|
||||
// (This is in contrast to accumulator hashmaps which are repeatedly accessed
|
||||
// during a stats run.)
|
||||
//
|
||||
// * The hashed impl computes hashsums for *all* fields whether operated on or not,
|
||||
// for the benefit of the *few* fields looked up during the mapping operation.
|
||||
//
|
||||
// * The hashless impl only keeps string pointers. Lookups are done at runtime
|
||||
// doing prefix search on the key names. Assuming field names are distinct,
|
||||
// this is just a few char-ptr accesses which (in experiments) turn out to
|
||||
// offer about a 10-15% performance improvement.
|
||||
//
|
||||
// * Added benefit: the field-rename operation (preserving field order) becomes
|
||||
// trivial.
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is supported.
|
||||
// ================================================================
|
||||
|
||||
#ifndef LREC_H
|
||||
#define LREC_H
|
||||
|
||||
#include "lib/free_flags.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "containers/slls.h"
|
||||
#include "containers/hss.h"
|
||||
#include "containers/header_keeper.h"
|
||||
|
||||
#define FIELD_QUOTED_ON_INPUT 0x02
|
||||
|
||||
struct _lrec_t; // forward reference
|
||||
typedef struct _lrec_t lrec_t;
|
||||
|
||||
typedef void lrec_free_func_t(lrec_t* prec);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lrece_t {
|
||||
char* key;
|
||||
char* value;
|
||||
// These indicate whether the key/value should be freed on lrec_free().
|
||||
// Affirmative example: key/value is strdup of something.
|
||||
// Negative example: key/value are pointers into a line the memory
|
||||
// management of which is separately managed.
|
||||
// Another negative example: key/value is a string literal, e.g. "".
|
||||
char free_flags;
|
||||
char quote_flags;
|
||||
|
||||
struct _lrece_t *pprev;
|
||||
struct _lrece_t *pnext;
|
||||
} lrece_t;
|
||||
|
||||
struct _lrec_t {
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int field_count;
|
||||
lrece_t* phead;
|
||||
lrece_t* ptail;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// See comments above free_flags. Used to track a mallocked pointer to be
|
||||
// freed at lrec_free().
|
||||
|
||||
// E.g. for NIDX, DKVP, and CSV formats (header handled separately in the
|
||||
// latter case).
|
||||
char* psingle_line;
|
||||
|
||||
// For XTAB format.
|
||||
slls_t* pxtab_lines;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Format-dependent virtual-function pointer:
|
||||
lrec_free_func_t* pfree_backing_func;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lrec_t* lrec_unbacked_alloc();
|
||||
lrec_t* lrec_dkvp_alloc(char* line);
|
||||
lrec_t* lrec_nidx_alloc(char* line);
|
||||
lrec_t* lrec_csvlite_alloc(char* data_line);
|
||||
lrec_t* lrec_csv_alloc(char* data_line);
|
||||
lrec_t* lrec_xtab_alloc(slls_t* pxtab_lines);
|
||||
|
||||
void lrec_clear(lrec_t* prec);
|
||||
void lrec_free(lrec_t* prec);
|
||||
lrec_t* lrec_copy(lrec_t* pinrec);
|
||||
|
||||
// The only difference between lrec_put and lrec_prepend is that the latter
|
||||
// adds to the end of the record, while the former adds to the beginning.
|
||||
//
|
||||
// For both, the key/value respectively will be freed by lrec_free if the
|
||||
// corresponding bits are set in the free_flags.
|
||||
//
|
||||
// * If a string literal or other non-allocated pointer (e.g. mmapped memory
|
||||
// from a file reader) is passed in, the free flag should not be set.
|
||||
//
|
||||
// * If dynamically allocated pointers are passed in, then either:
|
||||
//
|
||||
// o The respective free_flag(s) should be set and the caller should be sure
|
||||
// not to also free (else, there will be heap corruption due to
|
||||
// double-free), or
|
||||
//
|
||||
// o The respective free_flag(s) should not be set and the caller should
|
||||
// free the memory (else, there will be a memory leak).
|
||||
void lrec_put(lrec_t* prec, char* key, char* value, char free_flags);
|
||||
void lrec_put_ext(lrec_t* prec, char* key, char* value, char free_flags, char quote_flags);
|
||||
// Like lrec_put: if key is present, modify value. But if not, add new field at start of record, not at end.
|
||||
void lrec_prepend(lrec_t* prec, char* key, char* value, char free_flags);
|
||||
// Like lrec_put: if key is present, modify value. But if not, add new field after specified entry, not at end.
|
||||
// Returns a pointer to the added/modified node.
|
||||
lrece_t* lrec_put_after(lrec_t* prec, lrece_t* pd, char* key, char* value, char free_flags);
|
||||
|
||||
char* lrec_get(lrec_t* prec, char* key);
|
||||
lrece_t* lrec_get_pair_by_position(lrec_t* prec, int position); // 1-up not 0-up
|
||||
char* lrec_get_key_by_position(lrec_t* prec, int position); // 1-up not 0-up
|
||||
char* lrec_get_value_by_position(lrec_t* prec, int position); // 1-up not 0-up
|
||||
|
||||
// This returns a pointer to the lrec's free-flags so that the caller can do ownership-transfer
|
||||
// of about-to-be-removed key-value pairs.
|
||||
char* lrec_get_pff(lrec_t* prec, char* key, char** ppfree_flags);
|
||||
|
||||
// This returns a pointer to the entry so the caller can update it directly without needing
|
||||
// to do another field-scan on subsequent lrec_put etc. This is a performance optimization;
|
||||
// it also allows mlr nest --explode to do explode-in-place rather than explode-at-end.
|
||||
char* lrec_get_ext(lrec_t* prec, char* key, lrece_t** ppentry);
|
||||
|
||||
void lrec_remove(lrec_t* prec, char* key);
|
||||
void lrec_remove_by_position(lrec_t* prec, int position); // 1-up not 0-up
|
||||
void lrec_rename(lrec_t* prec, char* old_key, char* new_key, int new_needs_freeing);
|
||||
void lrec_rename_at_position(lrec_t* prec, int position, char* new_key, int new_needs_freeing); // 1-up not 0-up
|
||||
void lrec_move_to_head(lrec_t* prec, char* key);
|
||||
void lrec_move_to_tail(lrec_t* prec, char* key);
|
||||
// Renames the first n fields where n is the length of pnames.
|
||||
// The hash-set argument is for efficient dedupe.
|
||||
// Assumes as a precondition that pnames_as_list has no duplicates.
|
||||
// If the new labels include any field names existing later on in the record, those are unset.
|
||||
// For example, input record "a=1,b=2,c=3,d=4,e=5" with labels "d,x,f" results in output record "d=1,x=2,f=3,e=5".
|
||||
void lrec_label(lrec_t* prec, slls_t* pnames_as_list, hss_t* pnames_as_set);
|
||||
|
||||
void lrece_update_value(lrece_t* pe, char* new_value, int new_needs_freeing);
|
||||
|
||||
// For lrec-internal use:
|
||||
void lrec_unlink(lrec_t* prec, lrece_t* pe);
|
||||
// May be used for removing fields from a record while iterating over it:
|
||||
void lrec_unlink_and_free(lrec_t* prec, lrece_t* pe);
|
||||
|
||||
void lrec_print(lrec_t* prec);
|
||||
void lrec_dump(lrec_t* prec);
|
||||
void lrec_dump_fp(lrec_t* prec, FILE* fp);
|
||||
void lrec_dump_titled(char* msg, lrec_t* prec);
|
||||
void lrec_pointer_dump(lrec_t* prec);
|
||||
// The caller should free the return value
|
||||
char* lrec_sprint(lrec_t* prec, char* ors, char* ofs, char* ops);
|
||||
|
||||
// NIDX data are keyed by one-up field index which is not explicitly contained
|
||||
// in the file, e.g. line "a b c" splits to an lrec with "{"1" => "a", "2" =>
|
||||
// "b", "3" => "c"}. This function creates the keys, avoiding redundant memory
|
||||
// allocation for most-used keys such as "1", "2", ... up to 100 or so. In case
|
||||
// of large idx, free_flags & FREE_ENTRY_KEY will indicate that the key
|
||||
// was dynamically allocated.
|
||||
char* low_int_to_string(int idx, char* pfree_flags);
|
||||
|
||||
// For unit-test.
|
||||
lrec_t* lrec_literal_1(char* k1, char* v1);
|
||||
lrec_t* lrec_literal_2(char* k1, char* v1, char* k2, char* v2);
|
||||
lrec_t* lrec_literal_3(char* k1, char* v1, char* k2, char* v2, char* k3, char* v3);
|
||||
lrec_t* lrec_literal_4(char* k1, char* v1, char* k2, char* v2, char* k3, char* v3, char* k4, char* v4);
|
||||
|
||||
#endif // LREC_H
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "lib/mlr_globals.h"
|
||||
#include "containers/mixutil.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Makes a list with values pointing to the lrec's keys. slls_free() will
|
||||
// respect that and not corrupt the lrec. However, the slls values will be
|
||||
// invalid after the lrec is freed.
|
||||
|
||||
slls_t* mlr_reference_keys_from_record(lrec_t* prec) {
|
||||
slls_t* plist = slls_alloc();
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
slls_append_no_free(plist, pe->key);
|
||||
}
|
||||
return plist;
|
||||
}
|
||||
|
||||
slls_t* mlr_copy_keys_from_record(lrec_t* prec) {
|
||||
slls_t* plist = slls_alloc();
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
slls_append_with_free(plist, mlr_strdup_or_die(pe->key));
|
||||
}
|
||||
return plist;
|
||||
}
|
||||
|
||||
slls_t* mlr_reference_values_from_record(lrec_t* prec) {
|
||||
slls_t* plist = slls_alloc();
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
slls_append_no_free(plist, pe->value);
|
||||
}
|
||||
return plist;
|
||||
}
|
||||
|
||||
slls_t* mlr_reference_keys_from_record_except(lrec_t* prec, lrece_t* px) {
|
||||
slls_t* plist = slls_alloc();
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe != px)
|
||||
slls_append_no_free(plist, pe->key);
|
||||
}
|
||||
return plist;
|
||||
}
|
||||
|
||||
slls_t* mlr_reference_values_from_record_except(lrec_t* prec, lrece_t* px) {
|
||||
slls_t* plist = slls_alloc();
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
if (pe != px)
|
||||
slls_append_no_free(plist, pe->value);
|
||||
}
|
||||
return plist;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Makes a list with values pointing into the lrec's values. slls_free() will
|
||||
// respect that and not corrupt the lrec. However, the slls values will be
|
||||
// invalid after the lrec is freed.
|
||||
|
||||
slls_t* mlr_reference_selected_values_from_record(lrec_t* prec, slls_t* pselected_field_names) {
|
||||
slls_t* pvalue_list = slls_alloc();
|
||||
for (sllse_t* pe = pselected_field_names->phead; pe != NULL; pe = pe->pnext) {
|
||||
char* selected_field_name = pe->value;
|
||||
char* value = lrec_get(prec, selected_field_name);
|
||||
if (value == NULL) {
|
||||
slls_free(pvalue_list);
|
||||
return NULL;
|
||||
} else {
|
||||
slls_append_no_free(pvalue_list, value);
|
||||
}
|
||||
}
|
||||
return pvalue_list;
|
||||
}
|
||||
|
||||
// Makes an array with values pointing into the lrec's values.
|
||||
// string_array_free() will respect that and not corrupt the lrec. However,
|
||||
// the array's values will be invalid after the lrec is freed.
|
||||
|
||||
void mlr_reference_values_from_record_into_string_array(lrec_t* prec, string_array_t* pselected_field_names,
|
||||
string_array_t* pvalues)
|
||||
{
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pselected_field_names->length != pvalues->length);
|
||||
pvalues->strings_need_freeing = FALSE;
|
||||
for (int i = 0; i < pselected_field_names->length; i++) {
|
||||
char* selected_field_name = pselected_field_names->strings[i];
|
||||
if (selected_field_name == NULL) {
|
||||
pvalues->strings[i] = NULL;
|
||||
} else {
|
||||
pvalues->strings[i] = lrec_get(prec, selected_field_name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int record_has_all_keys(lrec_t* prec, slls_t* pselected_field_names) {
|
||||
for (sllse_t* pe = pselected_field_names->phead; pe != NULL; pe = pe->pnext) {
|
||||
char* selected_field_name = pe->value;
|
||||
char* value = lrec_get(prec, selected_field_name);
|
||||
if (value == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
lhmss_t* mlr_reference_key_value_pairs_from_regex_names(lrec_t* prec, regex_t* pregexes, int num_regexes,
|
||||
int invert_matches)
|
||||
{
|
||||
lhmss_t* pmap = lhmss_alloc();
|
||||
|
||||
for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext) {
|
||||
int matches_any = FALSE;
|
||||
for (int i = 0; i < num_regexes; i++) {
|
||||
regex_t* pregex = &pregexes[i];
|
||||
if (regmatch_or_die(pregex, pe->key, 0, NULL)) {
|
||||
matches_any = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matches_any ^ invert_matches) {
|
||||
lhmss_put(pmap, pe->key, pe->value, NO_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
return pmap;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
hss_t* hss_from_slls(slls_t* plist) {
|
||||
hss_t* pset = hss_alloc();
|
||||
for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext)
|
||||
hss_add(pset, pe->value);
|
||||
return pset;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void lrec_print_list(sllv_t* plist) {
|
||||
for (sllve_t* pe = plist->phead; pe != NULL; pe = pe->pnext) {
|
||||
lrec_print(pe->pvvalue);
|
||||
}
|
||||
}
|
||||
|
||||
void lrec_print_list_with_prefix(sllv_t* plist, char* prefix) {
|
||||
if (plist == NULL) {
|
||||
printf("%s NULL", prefix);
|
||||
} else {
|
||||
for (sllve_t* pe = plist->phead; pe != NULL; pe = pe->pnext) {
|
||||
printf("%s", prefix);
|
||||
lrec_print(pe->pvvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int slls_lrec_compare_lexically(
|
||||
slls_t* plist,
|
||||
lrec_t* prec,
|
||||
slls_t* pkeys)
|
||||
{
|
||||
sllse_t* pe = plist->phead;
|
||||
sllse_t* pf = pkeys->phead;
|
||||
while (TRUE) {
|
||||
if (pe == NULL && pf == NULL)
|
||||
return 0;
|
||||
if (pe == NULL)
|
||||
return 1;
|
||||
if (pf == NULL)
|
||||
return -1;
|
||||
|
||||
char* precval = lrec_get(prec, pf->value);
|
||||
if (precval == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
int rc = strcmp(pe->value, precval);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
pe = pe->pnext;
|
||||
pf = pf->pnext;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lrec_slls_compare_lexically(
|
||||
lrec_t* prec,
|
||||
slls_t* pkeys,
|
||||
slls_t* plist)
|
||||
{
|
||||
return -slls_lrec_compare_lexically(plist, prec, pkeys);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int lrec_keys_equal_list(
|
||||
lrec_t* prec,
|
||||
slls_t* plist)
|
||||
{
|
||||
lrece_t* pe = prec->phead;
|
||||
sllse_t* pf = plist->phead;
|
||||
while (TRUE) {
|
||||
if (pe == NULL && pf == NULL)
|
||||
return TRUE;
|
||||
if (pe == NULL || pf == NULL)
|
||||
return FALSE;
|
||||
if (!streq(pe->key, pf->value))
|
||||
return FALSE;
|
||||
pe = pe->pnext;
|
||||
pf = pf->pnext;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// ================================================================
|
||||
// Functions involving more than one container type
|
||||
// ================================================================
|
||||
|
||||
#ifndef MIXUTIL_H
|
||||
#define MIXUTIL_H
|
||||
#include "containers/lrec.h"
|
||||
#include "containers/slls.h"
|
||||
#include "containers/hss.h"
|
||||
#include "containers/lhmss.h"
|
||||
#include "lib/string_array.h"
|
||||
#include "lib/mlrregex.h"
|
||||
|
||||
// Makes a list with values pointing to the lrec's keys. slls_free() will respect that and not corrupt the lrec.
|
||||
// However, the slls values will be invalid after the lrec is freed.
|
||||
slls_t* mlr_reference_keys_from_record(lrec_t* prec);
|
||||
// Makes a list with values pointing to the lrec's values. slls_free() will respect that and not corrupt the lrec.
|
||||
// However, the slls values will be invalid after the lrec is freed.
|
||||
slls_t* mlr_reference_values_from_record(lrec_t* prec);
|
||||
|
||||
slls_t* mlr_reference_keys_from_record_except(lrec_t* prec, lrece_t* px);
|
||||
slls_t* mlr_reference_values_from_record_except(lrec_t* prec, lrece_t* px);
|
||||
|
||||
// Copies data; no referencing concerns.
|
||||
slls_t* mlr_copy_keys_from_record(lrec_t* prec);
|
||||
|
||||
// Makes a list with values pointing into the lrec's values. slls_free() will
|
||||
// respect that and not corrupt the lrec. However, the slls values will be
|
||||
// invalid after the lrec is freed.
|
||||
slls_t* mlr_reference_selected_values_from_record(lrec_t* prec, slls_t* pselected_field_names);
|
||||
void mlr_reference_values_from_record_into_string_array(lrec_t* prec, string_array_t* pselected_field_names,
|
||||
string_array_t* pvalues);
|
||||
int record_has_all_keys(lrec_t* prec, slls_t* pselected_field_names);
|
||||
|
||||
lhmss_t* mlr_reference_key_value_pairs_from_regex_names(lrec_t* prec, regex_t* pregexes, int num_regexes,
|
||||
int invert_matches);
|
||||
|
||||
// Copies data; no referencing concerns.
|
||||
hss_t* hss_from_slls(slls_t* plist);
|
||||
|
||||
// Prints a list of lrecs using lrec_print.
|
||||
void lrec_print_list(sllv_t* plist);
|
||||
void lrec_print_list_with_prefix(sllv_t* plist, char* prefix);
|
||||
|
||||
// Same as
|
||||
// slls_t* prec_values = mlr_reference_selected_values_from_record(prec, pkeys);
|
||||
// return slls_compare_lexically(plist, prec_values);
|
||||
// but without the unnecessary copy.
|
||||
int slls_lrec_compare_lexically(
|
||||
slls_t* plist,
|
||||
lrec_t* prec,
|
||||
slls_t* pkeys);
|
||||
int lrec_slls_compare_lexically(
|
||||
lrec_t* prec,
|
||||
slls_t* pkeys,
|
||||
slls_t* plist);
|
||||
|
||||
int lrec_keys_equal_list(
|
||||
lrec_t* prec,
|
||||
slls_t* plist);
|
||||
|
||||
#endif // MIXUTIL_H
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,318 +0,0 @@
|
|||
// ================================================================
|
||||
// Array-only (open addressing) multi-level hash map, with linear probing for collisions.
|
||||
// All keys, and terminal-level values, are mlrvals. All data passed into the put method
|
||||
// are copied; no pointers in this data structure reference anything external.
|
||||
//
|
||||
// Notes:
|
||||
// * null key is not supported.
|
||||
// * null value is not supported.
|
||||
//
|
||||
// See also:
|
||||
// * http://en.wikipedia.org/wiki/Hash_table
|
||||
// * http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
|
||||
// ================================================================
|
||||
|
||||
#ifndef MLHMMV_H
|
||||
#define MLHMMV_H
|
||||
|
||||
#include "lib/mlrval.h"
|
||||
#include "containers/sllmv.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "containers/lrec.h"
|
||||
|
||||
#define MLHMMV_ERROR_NONE 0x0000
|
||||
#define MLHMMV_ERROR_KEYLIST_TOO_DEEP 0xdeef
|
||||
#define MLHMMV_ERROR_KEYLIST_TOO_SHALLOW 0x58a1
|
||||
|
||||
// This is made visible here in the API so the unit-tester can be sure to exercise the resize logic.
|
||||
#define MLHMMV_INITIAL_ARRAY_LENGTH 16
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void mlhmmv_print_terminal(mv_t* pmv, int quote_keys_always, int quote_values_always,
|
||||
FILE* ostream);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
struct _mlhmmv_level_t; // forward reference
|
||||
|
||||
// The 'x' is for extended: this can hold a scalar or a map.
|
||||
typedef struct _mlhmmv_xvalue_t {
|
||||
struct _mlhmmv_level_t* pnext_level;
|
||||
mv_t terminal_mlrval;
|
||||
char is_terminal;
|
||||
} mlhmmv_xvalue_t;
|
||||
|
||||
void mlhmmv_xvalue_reset(mlhmmv_xvalue_t* pxvalue);
|
||||
mlhmmv_xvalue_t mlhmmv_xvalue_alloc_empty_map();
|
||||
mlhmmv_xvalue_t mlhmmv_xvalue_copy(mlhmmv_xvalue_t* pxvalue);
|
||||
void mlhmmv_xvalue_free(mlhmmv_xvalue_t* pxvalue);
|
||||
|
||||
char* mlhmmv_xvalue_describe_type_simple(mlhmmv_xvalue_t* pxvalue);
|
||||
|
||||
static inline int mlhmmv_xvalue_is_absent_and_nonterminal(mlhmmv_xvalue_t* pxvalue) {
|
||||
return (pxvalue->is_terminal && mv_is_absent(&pxvalue->terminal_mlrval));
|
||||
}
|
||||
|
||||
static inline int mlhmmv_xvalue_is_present_and_nonterminal(mlhmmv_xvalue_t* pxvalue) {
|
||||
return (pxvalue->is_terminal && mv_is_present(&pxvalue->terminal_mlrval));
|
||||
}
|
||||
|
||||
// Used by for-loops over map-valued local variables
|
||||
sllv_t* mlhmmv_xvalue_copy_keys_indexed (mlhmmv_xvalue_t* pxvalue, sllmv_t* pmvkeys);
|
||||
sllv_t* mlhmmv_xvalue_copy_keys_nonindexed(mlhmmv_xvalue_t* pxvalue);
|
||||
|
||||
void mlhmmv_xvalues_to_lrecs_lashed(
|
||||
mlhmmv_xvalue_t** ptop_values,
|
||||
int num_submaps,
|
||||
mv_t* pbasenames,
|
||||
sllmv_t* pnames,
|
||||
sllv_t* poutrecs,
|
||||
int do_full_prefixing,
|
||||
char* flatten_separator);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _mlhmmv_level_entry_t {
|
||||
int ideal_index;
|
||||
mv_t level_key;
|
||||
mlhmmv_xvalue_t level_xvalue; // terminal mlrval, or another hashmap
|
||||
struct _mlhmmv_level_entry_t *pprev;
|
||||
struct _mlhmmv_level_entry_t *pnext;
|
||||
} mlhmmv_level_entry_t;
|
||||
|
||||
typedef unsigned char mlhmmv_level_entry_state_t;
|
||||
|
||||
// Store a mlrval into the mlhmmv_xvalue without copying, implicitly transferring
|
||||
// ownership of the mlrval's free_flags. This means the mlrval will be freed
|
||||
// when the mlhmmv_xvalue is freed, so the caller should make a copy first if
|
||||
// necessary.
|
||||
//
|
||||
// This is a hot path for non-map local-variable assignments.
|
||||
static inline mlhmmv_xvalue_t mlhmmv_xvalue_wrap_terminal(mv_t val) {
|
||||
return (mlhmmv_xvalue_t) {.is_terminal = TRUE, .terminal_mlrval = val, .pnext_level = NULL};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _mlhmmv_level_t {
|
||||
int num_occupied;
|
||||
int num_freed;
|
||||
int array_length;
|
||||
mlhmmv_level_entry_t* entries;
|
||||
mlhmmv_level_entry_state_t* states;
|
||||
mlhmmv_level_entry_t* phead;
|
||||
mlhmmv_level_entry_t* ptail;
|
||||
} mlhmmv_level_t;
|
||||
|
||||
mlhmmv_level_t* mlhmmv_level_alloc();
|
||||
void mlhmmv_level_free(mlhmmv_level_t* plevel);
|
||||
|
||||
void mlhmmv_level_clear(mlhmmv_level_t* plevel);
|
||||
void mlhmmv_level_remove(mlhmmv_level_t* plevel, sllmve_t* prestkeys);
|
||||
int mlhmmv_level_has_key(mlhmmv_level_t* plevel, mv_t* plevel_key);
|
||||
|
||||
mv_t* mlhmmv_level_look_up_and_ref_terminal(
|
||||
mlhmmv_level_t* plevel,
|
||||
sllmv_t* pmvkeys,
|
||||
int* perror);
|
||||
|
||||
mlhmmv_xvalue_t* mlhmmv_level_look_up_and_ref_xvalue(
|
||||
mlhmmv_level_t* plevel,
|
||||
sllmv_t* pmvkeys,
|
||||
int* perror);
|
||||
|
||||
mlhmmv_level_t* mlhmmv_level_put_empty_map(
|
||||
mlhmmv_level_t* plevel,
|
||||
mv_t* pkey);
|
||||
|
||||
void mlhmmv_level_put_xvalue(
|
||||
mlhmmv_level_t* plevel,
|
||||
sllmve_t* prest_keys,
|
||||
mlhmmv_xvalue_t* pvalue);
|
||||
|
||||
void mlhmmv_level_put_xvalue_singly_keyed(
|
||||
mlhmmv_level_t* plevel,
|
||||
mv_t* pkey,
|
||||
mlhmmv_xvalue_t* pvalue);
|
||||
|
||||
void mlhmmv_level_put_terminal(
|
||||
mlhmmv_level_t* plevel,
|
||||
sllmve_t* prest_keys,
|
||||
mv_t* pterminal_value);
|
||||
|
||||
void mlhmmv_level_put_terminal_singly_keyed(
|
||||
mlhmmv_level_t* plevel,
|
||||
mv_t* pkey,
|
||||
mv_t* pterminal_value);
|
||||
|
||||
void mlhmmv_level_to_lrecs(
|
||||
mlhmmv_level_t* plevel,
|
||||
sllmv_t* pkeys,
|
||||
sllmv_t* pnames,
|
||||
sllv_t* poutrecs,
|
||||
int do_full_prefixing,
|
||||
char* flatten_separator);
|
||||
|
||||
void mlhmmv_level_print_stacked(
|
||||
mlhmmv_level_t* plevel,
|
||||
int depth,
|
||||
int do_final_comma,
|
||||
int quote_keys_always,
|
||||
int quote_values_always,
|
||||
char* line_indent,
|
||||
char* line_term,
|
||||
FILE* ostream);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _mlhmmv_root_t {
|
||||
mlhmmv_xvalue_t root_xvalue;
|
||||
} mlhmmv_root_t;
|
||||
|
||||
mlhmmv_root_t* mlhmmv_root_alloc();
|
||||
|
||||
void mlhmmv_root_free(mlhmmv_root_t* pmap);
|
||||
|
||||
void mlhmmv_root_clear(mlhmmv_root_t* pmap);
|
||||
|
||||
// If the return value is non-null, error will be MLHMMV_ERROR_NONE. If the
|
||||
// return value is null, the error will be MLHMMV_ERROR_KEYLIST_TOO_DEEP or
|
||||
// MLHMMV_ERROR_KEYLIST_TOO_SHALLOW, or MLHMMV_ERROR_NONE if the keylist matches
|
||||
// map depth but the entry is not found.
|
||||
//
|
||||
// Note: this returns a pointer to the map's data, not to a copy.
|
||||
// The caller shouldn't free it, or modify it.
|
||||
mv_t* mlhmmv_root_look_up_and_ref_terminal(mlhmmv_root_t* pmap, sllmv_t* pmvkeys, int* perror);
|
||||
|
||||
// These are an optimization for assignment from full srec, e.g. '@records[$key1][$key2] = $*'.
|
||||
// Using mlhmmv_root_look_up_or_create_then_ref_level, the CST logic can get or create the @records[$key1][$key2]
|
||||
// level of the mlhmmv, then copy values there.
|
||||
mlhmmv_level_t* mlhmmv_root_look_up_or_create_then_ref_level(mlhmmv_root_t* pmap, sllmv_t* pmvkeys);
|
||||
|
||||
void mlhmmv_root_put_terminal(mlhmmv_root_t* pmap, sllmv_t* pmvkeys, mv_t* pterminal_value);
|
||||
|
||||
// For for-loop-over-oosvar, wherein we need to copy the submap before iterating over it
|
||||
// (since the iteration may modify it). If the keys don't index a submap, then the return
|
||||
// value has is_terminal = TRUE and pnext_level = NULL.
|
||||
mlhmmv_xvalue_t mlhmmv_root_copy_xvalue(mlhmmv_root_t* pmap, sllmv_t* pmvkeys);
|
||||
|
||||
// Used by for-loops over oosvars. Return value is an array of ephemeral mlrvals.
|
||||
sllv_t* mlhmmv_root_copy_keys_from_submap(mlhmmv_root_t* pmap, sllmv_t* pmvkeys);
|
||||
|
||||
// Unset value/submap from a specified level onward, also unsetting any maps which become empty as a result.
|
||||
// Examples:
|
||||
// {
|
||||
// "a" : { "x" : 1, "y" : 2 },
|
||||
// "b" : { "x" : 3, "y" : 4 },
|
||||
// }
|
||||
// with pmvkeys = ["a"] leaves
|
||||
// {
|
||||
// "b" : { "x" : 3, "y" : 4 },
|
||||
// }
|
||||
// but with pmvkeys = ["a", "y"] leaves
|
||||
// {
|
||||
// "a" : { "x" : 1 },
|
||||
// "b" : { "x" : 3, "y" : 4 },
|
||||
// }
|
||||
// and with pmvkeys = [] leaves
|
||||
// {
|
||||
// }
|
||||
// Now if ["a","x"] is removed from
|
||||
// {
|
||||
// "a" : { "x" : 1 },
|
||||
// "b" : { "x" : 3, "y" : 4 },
|
||||
// }
|
||||
// then
|
||||
// {
|
||||
// "b" : { "x" : 3, "y" : 4 },
|
||||
// }
|
||||
// is left: unsetting "a":"x" leaves the map at "a" so this is unset as well.
|
||||
void mlhmmv_root_remove(mlhmmv_root_t* pmap, sllmv_t* pmvkeys);
|
||||
|
||||
// For 'emit' and 'emitp' in the DSL. These allocate lrecs, appended to the poutrecs list.
|
||||
// * pmap is the base-level oosvar multi-level hashmap.
|
||||
// * pkeys specify the level in the mlhmmv at which to produce data.
|
||||
// * pnames is used to pull subsequent-level keys out into separate fields.
|
||||
// * In case pnames isn't long enough to reach a terminal mlrval level in the mlhmmv,
|
||||
// do_full_prefixing specifies whether to concatenate nested mlhmmv keys into single lrec keys.
|
||||
//
|
||||
// Examples:
|
||||
|
||||
// * pkeys reaches a terminal level:
|
||||
//
|
||||
// $ mlr --opprint put -q '@sum += $x; end { emit @sum }' ../data/small
|
||||
// sum
|
||||
// 4.536294
|
||||
|
||||
// * pkeys reaches terminal levels:
|
||||
//
|
||||
// $ mlr --opprint put -q '@sum[$a][$b] += $x; end { emit @sum, "a", "b" }' ../data/small
|
||||
// a b sum
|
||||
// pan pan 0.346790
|
||||
// pan wye 0.502626
|
||||
// eks pan 0.758680
|
||||
// eks wye 0.381399
|
||||
// eks zee 0.611784
|
||||
// wye wye 0.204603
|
||||
// wye pan 0.573289
|
||||
// zee pan 0.527126
|
||||
// zee wye 0.598554
|
||||
// hat wye 0.031442
|
||||
|
||||
// * pkeys reaches non-terminal levels: non-prefixed:
|
||||
//
|
||||
// $ mlr --opprint put -q '@sum[$a][$b] += $x; end { emit @sum, "a" }' ../data/small
|
||||
// a pan wye
|
||||
// pan 0.346790 0.502626
|
||||
//
|
||||
// a pan wye zee
|
||||
// eks 0.758680 0.381399 0.611784
|
||||
//
|
||||
// a wye pan
|
||||
// wye 0.204603 0.573289
|
||||
//
|
||||
// a pan wye
|
||||
// zee 0.527126 0.598554
|
||||
//
|
||||
// a wye
|
||||
// hat 0.031442
|
||||
|
||||
// * pkeys reaches non-terminal levels: prefixed:
|
||||
//
|
||||
// $ mlr --opprint put -q '@sum[$a][$b] += $x; end { emitp @sum, "a" }' ../data/small
|
||||
// a sum:pan sum:wye
|
||||
// pan 0.346790 0.502626
|
||||
//
|
||||
// a sum:pan sum:wye sum:zee
|
||||
// eks 0.758680 0.381399 0.611784
|
||||
//
|
||||
// a sum:wye sum:pan
|
||||
// wye 0.204603 0.573289
|
||||
//
|
||||
// a sum:pan sum:wye
|
||||
// zee 0.527126 0.598554
|
||||
//
|
||||
// a sum:wye
|
||||
// hat 0.031442
|
||||
|
||||
// For 'emit all' and 'emitp all' in the DSL
|
||||
void mlhmmv_root_all_to_lrecs(mlhmmv_root_t* pmap, sllmv_t* pnames, sllv_t* poutrecs,
|
||||
int do_full_prefixing, char* flatten_separator);
|
||||
|
||||
// For 'emit' and 'emitp' in the DSL
|
||||
void mlhmmv_root_partial_to_lrecs(mlhmmv_root_t* pmap, sllmv_t* pkeys, sllmv_t* pnames, sllv_t* poutrecs,
|
||||
int do_full_prefixing, char* flatten_separator);
|
||||
|
||||
// For 'dump' in the DSL; also used by the lrec-to-JSON writer.
|
||||
void mlhmmv_root_print_json_stacked(mlhmmv_root_t* pmap,
|
||||
int quote_keys_always, int quote_values_always,
|
||||
char* line_indent, char* line_term, FILE* ostream);
|
||||
void mlhmmv_root_print_json_single_lines(mlhmmv_root_t* pmap, int quote_keys_always,
|
||||
int quote_values_always, char* line_term, FILE* ostream);
|
||||
|
||||
// Used for emit of localvars. Puts the xvalue in a single-key-value-pair map
|
||||
// keyed by the specified name. The xvalue is referenced, not copied.
|
||||
mlhmmv_root_t* mlhmmv_wrap_name_and_xvalue(mv_t* pname, mlhmmv_xvalue_t* pxval);
|
||||
|
||||
// Used for takedown of the temporary map returned by mlhmmv_wrap_name_and_xvalue. Since the xvalue there
|
||||
// is referenced, not copied, mlhmmv_xvalue_free would prematurely free the xvalue. This method releases
|
||||
// the xvalue so that the remaining, map-internal structures can be freed correctly.
|
||||
void mlhmmv_unwrap_name_and_xvalue(mlhmmv_root_t* pmap);
|
||||
|
||||
#endif // MLHMMV_H
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/parse_trie.h"
|
||||
|
||||
static parse_trie_node_t* parse_trie_node_alloc(char c);
|
||||
static void parse_trie_print_aux(parse_trie_node_t* pnode, int depth);
|
||||
static void parse_trie_add_string_aux(parse_trie_node_t* pnode, char* string, int stridx, int len);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
parse_trie_t* parse_trie_alloc() {
|
||||
parse_trie_t* ptrie = mlr_malloc_or_die(sizeof(parse_trie_t));
|
||||
ptrie->past = parse_trie_node_alloc(0);
|
||||
ptrie->maxlen = 0;
|
||||
return ptrie;
|
||||
}
|
||||
|
||||
static parse_trie_node_t* parse_trie_node_alloc(char c) {
|
||||
parse_trie_node_t* pnode = mlr_malloc_or_die(sizeof(parse_trie_node_t));
|
||||
for (int i = 0; i < 256; i++)
|
||||
pnode->pnexts[i] = NULL;
|
||||
pnode->c = c;
|
||||
pnode->stridx = -1;
|
||||
pnode->strlen = -1;
|
||||
return pnode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void parse_trie_free_node_descendants(parse_trie_node_t* pnode) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
parse_trie_node_t* pnext = pnode->pnexts[i];
|
||||
if (pnext != NULL) {
|
||||
parse_trie_free_node_descendants(pnext);
|
||||
free(pnext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_trie_free(parse_trie_t* ptrie) {
|
||||
parse_trie_free_node_descendants(ptrie->past);
|
||||
free(ptrie->past);
|
||||
free(ptrie);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void parse_trie_print(parse_trie_t* ptrie) {
|
||||
parse_trie_node_t* pnode = ptrie->past;
|
||||
printf("PARSE TRIE DUMP START\n");
|
||||
if (pnode != NULL) {
|
||||
parse_trie_print_aux(pnode, 0);
|
||||
}
|
||||
printf("PARSE TRIE DUMP END\n");
|
||||
}
|
||||
|
||||
static void parse_trie_print_aux(parse_trie_node_t* pnode, int depth) {
|
||||
for (int i = 0; i < depth; i++)
|
||||
printf(" ");
|
||||
printf("c=%c[%02x],stridx=%d,strlen=%d\n",
|
||||
isprint((unsigned char)pnode->c) ? pnode->c : '?',
|
||||
(unsigned)pnode->c,
|
||||
pnode->stridx,
|
||||
pnode->strlen);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
parse_trie_node_t* pnext = pnode->pnexts[i];
|
||||
if (pnext != NULL)
|
||||
parse_trie_print_aux(pnext, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void parse_trie_add_string(parse_trie_t* ptrie, char* string, int stridx) {
|
||||
int len = strlen(string);
|
||||
parse_trie_add_string_aux(ptrie->past, string, stridx, strlen(string));
|
||||
if (len > ptrie->maxlen)
|
||||
ptrie->maxlen = len;
|
||||
}
|
||||
|
||||
static void parse_trie_add_string_aux(parse_trie_node_t* pnode, char* string, int stridx, int len) {
|
||||
char c = string[0];
|
||||
if (c == 0) {
|
||||
pnode->stridx = stridx;
|
||||
pnode->strlen = len;
|
||||
} else {
|
||||
parse_trie_node_t* pnext = pnode->pnexts[(unsigned char)c];
|
||||
if (pnext == NULL) {
|
||||
pnext = parse_trie_node_alloc(c);
|
||||
pnext->c = c;
|
||||
pnext->stridx = -1;
|
||||
pnext->strlen = -1;
|
||||
pnode->pnexts[(unsigned char)c] = pnext;
|
||||
}
|
||||
parse_trie_add_string_aux(pnext, &string[1], stridx, len);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#ifndef PARSE_TRIE_H
|
||||
#define PARSE_TRIE_H
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// This is for parsing of Miller RFC-CSV data, not for parsing of DSL
|
||||
// expressions for the put and filter verbs. This is used instead of flex or
|
||||
// lemon since such parsers, by design, must read to end of input to complete
|
||||
// parsing. Here, by contrast, we want to split the input stream by delimiters,
|
||||
// identifying one record at a time. This is so that data may be processed in a
|
||||
// streaming manner rather than an ingest-all manner.
|
||||
|
||||
struct _parse_trie_node_t;
|
||||
typedef struct _parse_trie_node_t {
|
||||
struct _parse_trie_node_t* pnexts[256];
|
||||
char c; // current character at this node
|
||||
int stridx; // which string was stored ending here; -1 if not end of string.
|
||||
int strlen; // length of string stored ending here; -1 if not end of string.
|
||||
} parse_trie_node_t;
|
||||
typedef struct _parse_trie_t {
|
||||
parse_trie_node_t* past;
|
||||
int maxlen;
|
||||
} parse_trie_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
parse_trie_t* parse_trie_alloc();
|
||||
void parse_trie_free(parse_trie_t* ptrie);
|
||||
void parse_trie_print(parse_trie_t* ptrie);
|
||||
void parse_trie_add_string(parse_trie_t* ptrie, char* string, int stridx);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Example input:
|
||||
// * string 0 is "a"
|
||||
// * string 1 is "aa"
|
||||
// * buf is "aaabc"
|
||||
// Output:
|
||||
// * return value is TRUE
|
||||
// * stridx is 1 since longest match is "aa"
|
||||
// * matchlen is 2 since "aa" has length 2
|
||||
|
||||
// This does a longest-prefix match: input data "\"\nabcdefg" is matched
|
||||
// against "\"\n" rather than against "\"".
|
||||
|
||||
// We assume that enough data has been peeked into the ring buffer for the
|
||||
// parse-trie's maxlen. There is no check here. This function is called on
|
||||
// every single character of RFC-CSV input data so the error-checking would be
|
||||
// inefficient here, as well as misplaced.
|
||||
|
||||
// The start of buffer (sob), buflen, and mask attributes are nominally
|
||||
// presented from a ring_buffer object.
|
||||
|
||||
static inline int parse_trie_ring_match(parse_trie_t* ptrie, char* buf, int sob, int buflen, int mask,
|
||||
int* pstridx, int* pmatchlen)
|
||||
{
|
||||
parse_trie_node_t* pnode = ptrie->past;
|
||||
parse_trie_node_t* pnext;
|
||||
parse_trie_node_t* pterm = NULL;
|
||||
for (int i = 0; i < buflen; i++) {
|
||||
char c = buf[(sob+i)&mask];
|
||||
pnext = pnode->pnexts[(unsigned char) c];
|
||||
if (pnext == NULL)
|
||||
break;
|
||||
if (pnext->strlen > 0) {
|
||||
pterm = pnext;
|
||||
}
|
||||
pnode = pnext;
|
||||
}
|
||||
if (pterm == NULL) {
|
||||
return FALSE;
|
||||
} else {
|
||||
*pstridx = pterm->stridx;
|
||||
*pmatchlen = pterm->strlen;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int parse_trie_match(parse_trie_t* ptrie, char* p, char* e, int* pstridx, int* pmatchlen) {
|
||||
parse_trie_node_t* pnode = ptrie->past;
|
||||
parse_trie_node_t* pnext;
|
||||
parse_trie_node_t* pterm = NULL;
|
||||
for ( ; p < e; p++) {
|
||||
char c = *p;
|
||||
pnext = pnode->pnexts[(unsigned char) c];
|
||||
if (pnext == NULL)
|
||||
break;
|
||||
if (pnext->strlen > 0) {
|
||||
pterm = pnext;
|
||||
}
|
||||
pnode = pnext;
|
||||
}
|
||||
if (pterm == NULL) {
|
||||
return FALSE;
|
||||
} else {
|
||||
*pstridx = pterm->stridx;
|
||||
*pmatchlen = pterm->strlen;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PARSE_TRIE_H
|
||||
|
|
@ -1,280 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/percentile_keeper.h"
|
||||
#include "lib/mvfuncs.h"
|
||||
|
||||
#define INITIAL_CAPACITY 10000
|
||||
#define GROWTH_FACTOR 2.0
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
percentile_keeper_t* percentile_keeper_alloc() {
|
||||
unsigned long long capacity = INITIAL_CAPACITY;
|
||||
percentile_keeper_t* ppercentile_keeper = mlr_malloc_or_die(sizeof(percentile_keeper_t));
|
||||
ppercentile_keeper->data = mlr_malloc_or_die(capacity*sizeof(mv_t));
|
||||
ppercentile_keeper->size = 0LL;
|
||||
ppercentile_keeper->capacity = capacity;
|
||||
ppercentile_keeper->sorted = FALSE;
|
||||
return ppercentile_keeper;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void percentile_keeper_free(percentile_keeper_t* ppercentile_keeper) {
|
||||
if (ppercentile_keeper == NULL)
|
||||
return;
|
||||
for (unsigned long long i = 0; i < ppercentile_keeper->size; i++) {
|
||||
mv_free(&ppercentile_keeper->data[i]);
|
||||
}
|
||||
free(ppercentile_keeper->data);
|
||||
ppercentile_keeper->data = NULL;
|
||||
ppercentile_keeper->size = 0LL;
|
||||
ppercentile_keeper->capacity = 0LL;
|
||||
free(ppercentile_keeper);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void percentile_keeper_ingest(percentile_keeper_t* ppercentile_keeper, mv_t value) {
|
||||
if (ppercentile_keeper->size >= ppercentile_keeper->capacity) {
|
||||
ppercentile_keeper->capacity = (unsigned long long)(ppercentile_keeper->capacity * GROWTH_FACTOR);
|
||||
ppercentile_keeper->data = (mv_t*)mlr_realloc_or_die(ppercentile_keeper->data,
|
||||
ppercentile_keeper->capacity*sizeof(mv_t));
|
||||
}
|
||||
ppercentile_keeper->data[ppercentile_keeper->size++] = value;
|
||||
ppercentile_keeper->sorted = FALSE;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Non-interpolated percentiles (see also https://en.wikipedia.org/wiki/Percentile)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// OPTION 1: int index = p*n/100.0;
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 20
|
||||
// 40
|
||||
// 60
|
||||
// 80
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 0 x_p20 20 x_p30 20 x_p40 40 x_p50 60 x_p60 60 x_p70 80 x_p80 80 x_p90 100 x_p100 100
|
||||
// x_p01 0 x_p11 0 x_p21 20 x_p31 20 x_p41 40 x_p51 60 x_p61 60 x_p71 80 x_p81 80 x_p91 100
|
||||
// x_p02 0 x_p12 0 x_p22 20 x_p32 20 x_p42 40 x_p52 60 x_p62 60 x_p72 80 x_p82 80 x_p92 100
|
||||
// x_p03 0 x_p13 0 x_p23 20 x_p33 20 x_p43 40 x_p53 60 x_p63 60 x_p73 80 x_p83 80 x_p93 100
|
||||
// x_p04 0 x_p14 0 x_p24 20 x_p34 40 x_p44 40 x_p54 60 x_p64 60 x_p74 80 x_p84 100 x_p94 100
|
||||
// x_p05 0 x_p15 0 x_p25 20 x_p35 40 x_p45 40 x_p55 60 x_p65 60 x_p75 80 x_p85 100 x_p95 100
|
||||
// x_p06 0 x_p16 0 x_p26 20 x_p36 40 x_p46 40 x_p56 60 x_p66 60 x_p76 80 x_p86 100 x_p96 100
|
||||
// x_p07 0 x_p17 20 x_p27 20 x_p37 40 x_p47 40 x_p57 60 x_p67 80 x_p77 80 x_p87 100 x_p97 100
|
||||
// x_p08 0 x_p18 20 x_p28 20 x_p38 40 x_p48 40 x_p58 60 x_p68 80 x_p78 80 x_p88 100 x_p98 100
|
||||
// x_p09 0 x_p19 20 x_p29 20 x_p39 40 x_p49 40 x_p59 60 x_p69 80 x_p79 80 x_p89 100 x_p99 100
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 25
|
||||
// 50
|
||||
// 75
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 0 x_p20 25 x_p30 25 x_p40 50 x_p50 50 x_p60 75 x_p70 75 x_p80 100 x_p90 100 x_p100 100
|
||||
// x_p01 0 x_p11 0 x_p21 25 x_p31 25 x_p41 50 x_p51 50 x_p61 75 x_p71 75 x_p81 100 x_p91 100
|
||||
// x_p02 0 x_p12 0 x_p22 25 x_p32 25 x_p42 50 x_p52 50 x_p62 75 x_p72 75 x_p82 100 x_p92 100
|
||||
// x_p03 0 x_p13 0 x_p23 25 x_p33 25 x_p43 50 x_p53 50 x_p63 75 x_p73 75 x_p83 100 x_p93 100
|
||||
// x_p04 0 x_p14 0 x_p24 25 x_p34 25 x_p44 50 x_p54 50 x_p64 75 x_p74 75 x_p84 100 x_p94 100
|
||||
// x_p05 0 x_p15 0 x_p25 25 x_p35 25 x_p45 50 x_p55 50 x_p65 75 x_p75 75 x_p85 100 x_p95 100
|
||||
// x_p06 0 x_p16 0 x_p26 25 x_p36 25 x_p46 50 x_p56 50 x_p66 75 x_p76 75 x_p86 100 x_p96 100
|
||||
// x_p07 0 x_p17 0 x_p27 25 x_p37 25 x_p47 50 x_p57 50 x_p67 75 x_p77 75 x_p87 100 x_p97 100
|
||||
// x_p08 0 x_p18 0 x_p28 25 x_p38 25 x_p48 50 x_p58 50 x_p68 75 x_p78 75 x_p88 100 x_p98 100
|
||||
// x_p09 0 x_p19 0 x_p29 25 x_p39 25 x_p49 50 x_p59 50 x_p69 75 x_p79 75 x_p89 100 x_p99 100
|
||||
//
|
||||
// ----------------------------------------------------------------
|
||||
// OPTION 2: int index = p*(n-1)/100.0;
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 20
|
||||
// 40
|
||||
// 60
|
||||
// 80
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 0 x_p20 20 x_p30 20 x_p40 40 x_p50 40 x_p60 60 x_p70 60 x_p80 80 x_p90 80 x_p100 100
|
||||
// x_p01 0 x_p11 0 x_p21 20 x_p31 20 x_p41 40 x_p51 40 x_p61 60 x_p71 60 x_p81 80 x_p91 80
|
||||
// x_p02 0 x_p12 0 x_p22 20 x_p32 20 x_p42 40 x_p52 40 x_p62 60 x_p72 60 x_p82 80 x_p92 80
|
||||
// x_p03 0 x_p13 0 x_p23 20 x_p33 20 x_p43 40 x_p53 40 x_p63 60 x_p73 60 x_p83 80 x_p93 80
|
||||
// x_p04 0 x_p14 0 x_p24 20 x_p34 20 x_p44 40 x_p54 40 x_p64 60 x_p74 60 x_p84 80 x_p94 80
|
||||
// x_p05 0 x_p15 0 x_p25 20 x_p35 20 x_p45 40 x_p55 40 x_p65 60 x_p75 60 x_p85 80 x_p95 80
|
||||
// x_p06 0 x_p16 0 x_p26 20 x_p36 20 x_p46 40 x_p56 40 x_p66 60 x_p76 60 x_p86 80 x_p96 80
|
||||
// x_p07 0 x_p17 0 x_p27 20 x_p37 20 x_p47 40 x_p57 40 x_p67 60 x_p77 60 x_p87 80 x_p97 80
|
||||
// x_p08 0 x_p18 0 x_p28 20 x_p38 20 x_p48 40 x_p58 40 x_p68 60 x_p78 60 x_p88 80 x_p98 80
|
||||
// x_p09 0 x_p19 0 x_p29 20 x_p39 20 x_p49 40 x_p59 40 x_p69 60 x_p79 60 x_p89 80 x_p99 80
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 25
|
||||
// 50
|
||||
// 75
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 0 x_p20 0 x_p30 25 x_p40 25 x_p50 50 x_p60 50 x_p70 50 x_p80 75 x_p90 75 x_p100 100
|
||||
// x_p01 0 x_p11 0 x_p21 0 x_p31 25 x_p41 25 x_p51 50 x_p61 50 x_p71 50 x_p81 75 x_p91 75
|
||||
// x_p02 0 x_p12 0 x_p22 0 x_p32 25 x_p42 25 x_p52 50 x_p62 50 x_p72 50 x_p82 75 x_p92 75
|
||||
// x_p03 0 x_p13 0 x_p23 0 x_p33 25 x_p43 25 x_p53 50 x_p63 50 x_p73 50 x_p83 75 x_p93 75
|
||||
// x_p04 0 x_p14 0 x_p24 0 x_p34 25 x_p44 25 x_p54 50 x_p64 50 x_p74 50 x_p84 75 x_p94 75
|
||||
// x_p05 0 x_p15 0 x_p25 25 x_p35 25 x_p45 25 x_p55 50 x_p65 50 x_p75 75 x_p85 75 x_p95 75
|
||||
// x_p06 0 x_p16 0 x_p26 25 x_p36 25 x_p46 25 x_p56 50 x_p66 50 x_p76 75 x_p86 75 x_p96 75
|
||||
// x_p07 0 x_p17 0 x_p27 25 x_p37 25 x_p47 25 x_p57 50 x_p67 50 x_p77 75 x_p87 75 x_p97 75
|
||||
// x_p08 0 x_p18 0 x_p28 25 x_p38 25 x_p48 25 x_p58 50 x_p68 50 x_p78 75 x_p88 75 x_p98 75
|
||||
// x_p09 0 x_p19 0 x_p29 25 x_p39 25 x_p49 25 x_p59 50 x_p69 50 x_p79 75 x_p89 75 x_p99 75
|
||||
//
|
||||
// ----------------------------------------------------------------
|
||||
// OPTION 3: int index = (int)ceil(p*(n-1)/100.0);
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 20
|
||||
// 40
|
||||
// 60
|
||||
// 80
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 20 x_p20 20 x_p30 40 x_p40 40 x_p50 60 x_p60 60 x_p70 80 x_p80 80 x_p90 100 x_p100 100
|
||||
// x_p01 20 x_p11 20 x_p21 40 x_p31 40 x_p41 60 x_p51 60 x_p61 80 x_p71 80 x_p81 100 x_p91 100
|
||||
// x_p02 20 x_p12 20 x_p22 40 x_p32 40 x_p42 60 x_p52 60 x_p62 80 x_p72 80 x_p82 100 x_p92 100
|
||||
// x_p03 20 x_p13 20 x_p23 40 x_p33 40 x_p43 60 x_p53 60 x_p63 80 x_p73 80 x_p83 100 x_p93 100
|
||||
// x_p04 20 x_p14 20 x_p24 40 x_p34 40 x_p44 60 x_p54 60 x_p64 80 x_p74 80 x_p84 100 x_p94 100
|
||||
// x_p05 20 x_p15 20 x_p25 40 x_p35 40 x_p45 60 x_p55 60 x_p65 80 x_p75 80 x_p85 100 x_p95 100
|
||||
// x_p06 20 x_p16 20 x_p26 40 x_p36 40 x_p46 60 x_p56 60 x_p66 80 x_p76 80 x_p86 100 x_p96 100
|
||||
// x_p07 20 x_p17 20 x_p27 40 x_p37 40 x_p47 60 x_p57 60 x_p67 80 x_p77 80 x_p87 100 x_p97 100
|
||||
// x_p08 20 x_p18 20 x_p28 40 x_p38 40 x_p48 60 x_p58 60 x_p68 80 x_p78 80 x_p88 100 x_p98 100
|
||||
// x_p09 20 x_p19 20 x_p29 40 x_p39 40 x_p49 60 x_p59 60 x_p69 80 x_p79 80 x_p89 100 x_p99 100
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 25
|
||||
// 50
|
||||
// 75
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 25 x_p20 25 x_p30 50 x_p40 50 x_p50 50 x_p60 75 x_p70 75 x_p80 100 x_p90 100 x_p100 100
|
||||
// x_p01 25 x_p11 25 x_p21 25 x_p31 50 x_p41 50 x_p51 75 x_p61 75 x_p71 75 x_p81 100 x_p91 100
|
||||
// x_p02 25 x_p12 25 x_p22 25 x_p32 50 x_p42 50 x_p52 75 x_p62 75 x_p72 75 x_p82 100 x_p92 100
|
||||
// x_p03 25 x_p13 25 x_p23 25 x_p33 50 x_p43 50 x_p53 75 x_p63 75 x_p73 75 x_p83 100 x_p93 100
|
||||
// x_p04 25 x_p14 25 x_p24 25 x_p34 50 x_p44 50 x_p54 75 x_p64 75 x_p74 75 x_p84 100 x_p94 100
|
||||
// x_p05 25 x_p15 25 x_p25 25 x_p35 50 x_p45 50 x_p55 75 x_p65 75 x_p75 75 x_p85 100 x_p95 100
|
||||
// x_p06 25 x_p16 25 x_p26 50 x_p36 50 x_p46 50 x_p56 75 x_p66 75 x_p76 100 x_p86 100 x_p96 100
|
||||
// x_p07 25 x_p17 25 x_p27 50 x_p37 50 x_p47 50 x_p57 75 x_p67 75 x_p77 100 x_p87 100 x_p97 100
|
||||
// x_p08 25 x_p18 25 x_p28 50 x_p38 50 x_p48 50 x_p58 75 x_p68 75 x_p78 100 x_p88 100 x_p98 100
|
||||
// x_p09 25 x_p19 25 x_p29 50 x_p39 50 x_p49 50 x_p59 75 x_p69 75 x_p79 100 x_p89 100 x_p99 100
|
||||
//
|
||||
// ----------------------------------------------------------------
|
||||
// OPTION 4: int index = (int)ceil(-0.5 + p*(n-1)/100.0);
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 20
|
||||
// 40
|
||||
// 60
|
||||
// 80
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 0 x_p20 20 x_p30 20 x_p40 40 x_p50 40 x_p60 60 x_p70 60 x_p80 80 x_p90 80 x_p100 100
|
||||
// x_p01 0 x_p11 20 x_p21 20 x_p31 40 x_p41 40 x_p51 60 x_p61 60 x_p71 80 x_p81 80 x_p91 100
|
||||
// x_p02 0 x_p12 20 x_p22 20 x_p32 40 x_p42 40 x_p52 60 x_p62 60 x_p72 80 x_p82 80 x_p92 100
|
||||
// x_p03 0 x_p13 20 x_p23 20 x_p33 40 x_p43 40 x_p53 60 x_p63 60 x_p73 80 x_p83 80 x_p93 100
|
||||
// x_p04 0 x_p14 20 x_p24 20 x_p34 40 x_p44 40 x_p54 60 x_p64 60 x_p74 80 x_p84 80 x_p94 100
|
||||
// x_p05 0 x_p15 20 x_p25 20 x_p35 40 x_p45 40 x_p55 60 x_p65 60 x_p75 80 x_p85 80 x_p95 100
|
||||
// x_p06 0 x_p16 20 x_p26 20 x_p36 40 x_p46 40 x_p56 60 x_p66 60 x_p76 80 x_p86 80 x_p96 100
|
||||
// x_p07 0 x_p17 20 x_p27 20 x_p37 40 x_p47 40 x_p57 60 x_p67 60 x_p77 80 x_p87 80 x_p97 100
|
||||
// x_p08 0 x_p18 20 x_p28 20 x_p38 40 x_p48 40 x_p58 60 x_p68 60 x_p78 80 x_p88 80 x_p98 100
|
||||
// x_p09 0 x_p19 20 x_p29 20 x_p39 40 x_p49 40 x_p59 60 x_p69 60 x_p79 80 x_p89 80 x_p99 100
|
||||
//
|
||||
// x
|
||||
// 0
|
||||
// 25
|
||||
// 50
|
||||
// 75
|
||||
// 100
|
||||
//
|
||||
// x_p00 0 x_p10 0 x_p20 25 x_p30 25 x_p40 50 x_p50 50 x_p60 50 x_p70 75 x_p80 75 x_p90 100 x_p100 100
|
||||
// x_p01 0 x_p11 0 x_p21 25 x_p31 25 x_p41 50 x_p51 50 x_p61 50 x_p71 75 x_p81 75 x_p91 100
|
||||
// x_p02 0 x_p12 0 x_p22 25 x_p32 25 x_p42 50 x_p52 50 x_p62 50 x_p72 75 x_p82 75 x_p92 100
|
||||
// x_p03 0 x_p13 25 x_p23 25 x_p33 25 x_p43 50 x_p53 50 x_p63 75 x_p73 75 x_p83 75 x_p93 100
|
||||
// x_p04 0 x_p14 25 x_p24 25 x_p34 25 x_p44 50 x_p54 50 x_p64 75 x_p74 75 x_p84 75 x_p94 100
|
||||
// x_p05 0 x_p15 25 x_p25 25 x_p35 25 x_p45 50 x_p55 50 x_p65 75 x_p75 75 x_p85 75 x_p95 100
|
||||
// x_p06 0 x_p16 25 x_p26 25 x_p36 25 x_p46 50 x_p56 50 x_p66 75 x_p76 75 x_p86 75 x_p96 100
|
||||
// x_p07 0 x_p17 25 x_p27 25 x_p37 25 x_p47 50 x_p57 50 x_p67 75 x_p77 75 x_p87 75 x_p97 100
|
||||
// x_p08 0 x_p18 25 x_p28 25 x_p38 50 x_p48 50 x_p58 50 x_p68 75 x_p78 75 x_p88 100 x_p98 100
|
||||
// x_p09 0 x_p19 25 x_p29 25 x_p39 50 x_p49 50 x_p59 50 x_p69 75 x_p79 75 x_p89 100 x_p99 100
|
||||
//
|
||||
// ----------------------------------------------------------------
|
||||
// CONCLUSION:
|
||||
// * I like option 2 for its simplicity ...
|
||||
// * ... but option 1 matches R's quantile with type=1.
|
||||
// * (Note that Miller's interpolated percentiles match match R's quantile with type=7)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
static unsigned long long compute_index_non_interpolated(unsigned long long n, double p) {
|
||||
long long index = p*n/100.0;
|
||||
//unsigned long long index = p*(n-1)/100.0;
|
||||
//unsigned long long index = (unsigned long long)ceil(p*(n-1)/100.0);
|
||||
//unsigned long long index = (unsigned long long)ceil(-0.5 + p*(n-1)/100.0);
|
||||
if (index >= n)
|
||||
index = n-1;
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
return (unsigned long long)index;
|
||||
}
|
||||
|
||||
static mv_t get_percentile_linearly_interpolated(mv_t* array, unsigned long long n, double p) {
|
||||
double findex = (p/100.0)*(n-1);
|
||||
if (findex < 0)
|
||||
findex = 0;
|
||||
unsigned long long iindex = (unsigned long long)floor(findex);
|
||||
if (iindex >= n-1) {
|
||||
return array[iindex];
|
||||
} else {
|
||||
// array[iindex] + frac * (array[iindex+1] - array[iindex]);
|
||||
mv_t frac = mv_from_float(findex - iindex);
|
||||
mv_t* pa = &array[iindex];
|
||||
mv_t* pb = &array[iindex+1];
|
||||
mv_t diff = x_xx_minus_func(pb, pa);
|
||||
mv_t prod = x_xx_times_func(&frac, &diff);
|
||||
mv_t rv = x_xx_plus_func(pa, &prod);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mv_t percentile_keeper_emit_non_interpolated(percentile_keeper_t* ppercentile_keeper, double percentile) {
|
||||
if (ppercentile_keeper->size == 0) {
|
||||
return mv_absent();
|
||||
}
|
||||
if (!ppercentile_keeper->sorted) {
|
||||
qsort(ppercentile_keeper->data, ppercentile_keeper->size, sizeof(mv_t), mv_xx_comparator);
|
||||
ppercentile_keeper->sorted = TRUE;
|
||||
}
|
||||
return ppercentile_keeper->data[compute_index_non_interpolated(ppercentile_keeper->size, percentile)];
|
||||
}
|
||||
|
||||
mv_t percentile_keeper_emit_linearly_interpolated(percentile_keeper_t* ppercentile_keeper, double percentile) {
|
||||
if (ppercentile_keeper->size == 0) {
|
||||
return mv_absent();
|
||||
}
|
||||
if (!ppercentile_keeper->sorted) {
|
||||
qsort(ppercentile_keeper->data, ppercentile_keeper->size, sizeof(mv_t), mv_xx_comparator);
|
||||
ppercentile_keeper->sorted = TRUE;
|
||||
}
|
||||
return get_percentile_linearly_interpolated(ppercentile_keeper->data, ppercentile_keeper->size, percentile);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void percentile_keeper_print(percentile_keeper_t* ppercentile_keeper) {
|
||||
printf("percentile_keeper dump:\n");
|
||||
for (unsigned long long i = 0; i < ppercentile_keeper->size; i++) {
|
||||
mv_t* pa = &ppercentile_keeper->data[i];
|
||||
if (pa->type == MT_FLOAT)
|
||||
printf("[%02llu] %.8lf\n", i, ppercentile_keeper->data[i].u.fltv);
|
||||
else
|
||||
printf("[%02llu] %8lld\n", i, ppercentile_keeper->data[i].u.intv);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// ================================================================
|
||||
// For mlr stats1 percentiles
|
||||
// ================================================================
|
||||
|
||||
#ifndef PERCENTILE_KEEPER_H
|
||||
#define PERCENTILE_KEEPER_H
|
||||
#include "lib/mlrval.h"
|
||||
|
||||
typedef struct _percentile_keeper_t {
|
||||
mv_t* data;
|
||||
unsigned long long size;
|
||||
unsigned long long capacity;
|
||||
int sorted;
|
||||
} percentile_keeper_t;
|
||||
|
||||
percentile_keeper_t* percentile_keeper_alloc();
|
||||
void percentile_keeper_free(percentile_keeper_t* ppercentile_keeper);
|
||||
void percentile_keeper_ingest(percentile_keeper_t* ppercentile_keeper, mv_t value);
|
||||
|
||||
typedef mv_t percentile_keeper_emitter_t(percentile_keeper_t* ppercentile_keeper, double percentile);
|
||||
mv_t percentile_keeper_emit_non_interpolated(percentile_keeper_t* ppercentile_keeper, double percentile);
|
||||
mv_t percentile_keeper_emit_linearly_interpolated(percentile_keeper_t* ppercentile_keeper, double percentile);
|
||||
|
||||
// For debug/test
|
||||
void percentile_keeper_print(percentile_keeper_t* ppercentile_keeper);
|
||||
|
||||
#endif // PERCENTILE_KEEPER_H
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/rslls.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
rslls_t* rslls_alloc() {
|
||||
rslls_t* plist = mlr_malloc_or_die(sizeof(rslls_t));
|
||||
plist->phead = NULL;
|
||||
plist->ptail = NULL;
|
||||
plist->length = 0;
|
||||
return plist;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void rslls_reset(rslls_t* plist) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
if (plist->phead == NULL)
|
||||
return;
|
||||
rsllse_t* pnode = plist->phead;
|
||||
while (pnode != NULL) {
|
||||
if (pnode->free_flag & FREE_ENTRY_VALUE)
|
||||
free(pnode->value);
|
||||
pnode->value = NULL;
|
||||
pnode = pnode->pnext;
|
||||
}
|
||||
plist->ptail = plist->phead;
|
||||
plist->length = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void rslls_free(rslls_t* plist) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
rsllse_t* pnode = plist->phead;
|
||||
while (pnode != NULL) {
|
||||
rsllse_t* pdel = pnode;
|
||||
pnode = pnode->pnext;
|
||||
if (pdel->free_flag & FREE_ENTRY_VALUE)
|
||||
free(pdel->value);
|
||||
free(pdel);
|
||||
}
|
||||
plist->phead = NULL;
|
||||
plist->ptail = 0;
|
||||
plist->length = 0;
|
||||
free(plist);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void rslls_append(rslls_t* plist, char* value, char free_flag, char quote_flag) {
|
||||
if (plist->ptail == NULL) {
|
||||
// First add on new list
|
||||
rsllse_t* pnode = mlr_malloc_or_die(sizeof(rsllse_t));
|
||||
pnode->value = value;
|
||||
pnode->free_flag = free_flag;
|
||||
pnode->quote_flag = quote_flag;
|
||||
pnode->pnext = NULL;
|
||||
plist->phead = pnode;
|
||||
plist->ptail = pnode;
|
||||
} else if (plist->ptail->value == NULL) {
|
||||
// Subsequent add on reused list
|
||||
plist->ptail->value = value;
|
||||
plist->ptail->free_flag = free_flag;
|
||||
plist->ptail->quote_flag = quote_flag;
|
||||
if (plist->ptail->pnext != NULL)
|
||||
plist->ptail = plist->ptail->pnext;
|
||||
} else {
|
||||
// Append at end of list
|
||||
rsllse_t* pnode = mlr_malloc_or_die(sizeof(rsllse_t));
|
||||
pnode->value = value;
|
||||
pnode->free_flag = free_flag;
|
||||
pnode->quote_flag = quote_flag;
|
||||
pnode->pnext = NULL;
|
||||
plist->ptail->pnext = pnode;
|
||||
plist->ptail = pnode;
|
||||
}
|
||||
plist->length++;
|
||||
}
|
||||
|
||||
void rslls_print(rslls_t* plist) {
|
||||
if (plist == NULL) {
|
||||
printf("NULL");
|
||||
} else {
|
||||
unsigned long long i = 0;
|
||||
for (rsllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext, i++) {
|
||||
if (i > 0)
|
||||
printf(",");
|
||||
if (pe->value == NULL)
|
||||
printf("NULL");
|
||||
else
|
||||
printf("%s", pe->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// ================================================================
|
||||
// Reusable singly linked list of string, with tail for append.
|
||||
//
|
||||
// Unlike slls which frees all memory on the destructor, this rslls class is
|
||||
// designed to be reusable: there is a reset method which doesn't free all node
|
||||
// structures. The context is the CSV-reader which extends a singly linked
|
||||
// list for every data line. Now, all CSV lines have nominally the same number
|
||||
// of fields (say N), so using slls, the CSV reader would be allocating and
|
||||
// freeing N nodes on every line. Mingled in with other mallocs and frees, this
|
||||
// results in needless heap fragmentation. Here, by contrast, as a performance
|
||||
// optimization, the CSV reader can keep and reuse the nodes of a list, only
|
||||
// changing the value-pointers on each CSV line.
|
||||
//
|
||||
// This means that while an slls iteration looks like
|
||||
//
|
||||
// for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// an rslls iteration must also check length:
|
||||
//
|
||||
// unsigned long long i = 0;
|
||||
// for (rsllse_t* pe = plist->phead; i < plist->length && pe != NULL; pe = pe->pnext, i++) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// ================================================================
|
||||
|
||||
#ifndef RSLLS_H
|
||||
#define RSLLS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
typedef struct _rsllse_t {
|
||||
char* value;
|
||||
char free_flag;
|
||||
char quote_flag;
|
||||
struct _rsllse_t *pnext;
|
||||
} rsllse_t;
|
||||
|
||||
typedef struct _rslls_t {
|
||||
rsllse_t *phead;
|
||||
rsllse_t *ptail;
|
||||
unsigned long long length;
|
||||
} rslls_t;
|
||||
|
||||
rslls_t* rslls_alloc();
|
||||
void rslls_reset(rslls_t* plist);
|
||||
void rslls_free(rslls_t* plist);
|
||||
void rslls_append(rslls_t* plist, char* value, char free_flag, char quote_flag);
|
||||
|
||||
void rslls_print(rslls_t* plist);
|
||||
|
||||
#endif // RSLLS_H
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
#include "lib/mlrutil.h"
|
||||
#include "containers/sllmv.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
sllmv_t* sllmv_alloc() {
|
||||
sllmv_t* plist = mlr_malloc_or_die(sizeof(sllmv_t));
|
||||
plist->phead = NULL;
|
||||
plist->ptail = NULL;
|
||||
plist->length = 0;
|
||||
return plist;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void sllmv_free(sllmv_t* plist) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
sllmve_t* pnode = plist->phead;
|
||||
while (pnode != NULL) {
|
||||
sllmve_t* pdel = pnode;
|
||||
pnode = pnode->pnext;
|
||||
if (pdel->free_flags & FREE_ENTRY_VALUE)
|
||||
mv_free(&pdel->value);
|
||||
free(pdel);
|
||||
}
|
||||
plist->phead = NULL;
|
||||
plist->ptail = 0;
|
||||
plist->length = 0;
|
||||
|
||||
free(plist);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Mlrvals are small structs and we do struct assignment from argument
|
||||
// to list storage. For all but string mlrvals, this is a copy.
|
||||
// For string mlrvals, it is pointer assignment without string duplication.
|
||||
// This is intentional (for performance); callees are advised.
|
||||
|
||||
static void sllmv_append(sllmv_t* plist, mv_t* pvalue, char free_flags) {
|
||||
sllmve_t* pnode = mlr_malloc_or_die(sizeof(sllmve_t));
|
||||
pnode->value = *pvalue; // struct assignment
|
||||
pnode->free_flags = free_flags;
|
||||
if (plist->ptail == NULL) {
|
||||
pnode->pnext = NULL;
|
||||
plist->phead = pnode;
|
||||
plist->ptail = pnode;
|
||||
} else {
|
||||
pnode->pnext = NULL;
|
||||
plist->ptail->pnext = pnode;
|
||||
plist->ptail = pnode;
|
||||
}
|
||||
plist->length++;
|
||||
}
|
||||
|
||||
void sllmv_append_with_free(sllmv_t* plist, mv_t* pvalue) {
|
||||
sllmv_append(plist, pvalue, FREE_ENTRY_VALUE);
|
||||
}
|
||||
|
||||
void sllmv_append_no_free(sllmv_t* plist, mv_t* pvalue) {
|
||||
sllmv_append(plist, pvalue, NO_FREE);
|
||||
}
|
||||
|
||||
static void sllmv_prepend(sllmv_t* plist, mv_t* pvalue, char free_flags) {
|
||||
sllmve_t* pnode = mlr_malloc_or_die(sizeof(sllmve_t));
|
||||
pnode->value = *pvalue; // struct assignment
|
||||
pnode->free_flags = free_flags;
|
||||
pnode->value = *pvalue; // struct assignment
|
||||
if (plist->ptail == NULL) {
|
||||
pnode->pnext = NULL;
|
||||
plist->phead = pnode;
|
||||
plist->ptail = pnode;
|
||||
} else {
|
||||
pnode->pnext = plist->phead;
|
||||
plist->phead = pnode;
|
||||
}
|
||||
plist->length++;
|
||||
}
|
||||
|
||||
void sllmv_prepend_with_free(sllmv_t* plist, mv_t* pvalue) {
|
||||
sllmv_prepend(plist, pvalue, FREE_ENTRY_VALUE);
|
||||
}
|
||||
|
||||
void sllmv_prepend_no_free(sllmv_t* plist, mv_t* pvalue) {
|
||||
sllmv_prepend(plist, pvalue, NO_FREE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
sllmv_t* sllmv_single_no_free(mv_t* pvalue) {
|
||||
sllmv_t* psllmv = sllmv_alloc();
|
||||
sllmv_append_no_free(psllmv, pvalue);
|
||||
return psllmv;
|
||||
}
|
||||
|
||||
sllmv_t* sllmv_single_with_free(mv_t* pvalue) {
|
||||
sllmv_t* psllmv = sllmv_alloc();
|
||||
sllmv_append_with_free(psllmv, pvalue);
|
||||
return psllmv;
|
||||
}
|
||||
|
||||
sllmv_t* sllmv_double_with_free(mv_t* pvalue1, mv_t* pvalue2) {
|
||||
sllmv_t* psllmv = sllmv_alloc();
|
||||
sllmv_append_with_free(psllmv, pvalue1);
|
||||
sllmv_append_with_free(psllmv, pvalue2);
|
||||
return psllmv;
|
||||
}
|
||||
|
||||
sllmv_t* sllmv_triple_with_free(mv_t* pvalue1, mv_t* pvalue2, mv_t* pvalue3) {
|
||||
sllmv_t* psllmv = sllmv_alloc();
|
||||
sllmv_append_with_free(psllmv, pvalue1);
|
||||
sllmv_append_with_free(psllmv, pvalue2);
|
||||
sllmv_append_with_free(psllmv, pvalue3);
|
||||
return psllmv;
|
||||
}
|
||||
|
||||
sllmv_t* sllmv_quadruple_with_free(mv_t* pvalue1, mv_t* pvalue2, mv_t* pvalue3, mv_t* pvalue4) {
|
||||
sllmv_t* psllmv = sllmv_alloc();
|
||||
sllmv_append_with_free(psllmv, pvalue1);
|
||||
sllmv_append_with_free(psllmv, pvalue2);
|
||||
sllmv_append_with_free(psllmv, pvalue3);
|
||||
sllmv_append_with_free(psllmv, pvalue4);
|
||||
return psllmv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void sllmv_print(sllmv_t* plist) {
|
||||
sllmve_tail_print(plist->phead);
|
||||
}
|
||||
|
||||
void sllmve_tail_print(sllmve_t* pnode) {
|
||||
printf("[");
|
||||
int i = 0;
|
||||
for (sllmve_t* pe = pnode; pe != NULL; pe = pe->pnext, i++) {
|
||||
char* string = mv_alloc_format_val(&pe->value);
|
||||
if (i > 0)
|
||||
printf(", ");
|
||||
printf(" ");
|
||||
printf("%s", string);
|
||||
free(string);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// ================================================================
|
||||
// Singly-linked list of mlrval, with tail for append.
|
||||
// Strings inside mlrvals are referenced, not copied.
|
||||
// ================================================================
|
||||
|
||||
#ifndef SLLMV_H
|
||||
#define SLLMV_H
|
||||
|
||||
#include "../lib/mlrval.h"
|
||||
#include "../lib/free_flags.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _sllmve_t {
|
||||
mv_t value;
|
||||
char free_flags;
|
||||
struct _sllmve_t *pnext;
|
||||
} sllmve_t;
|
||||
|
||||
typedef struct _sllmv_t {
|
||||
sllmve_t *phead;
|
||||
sllmve_t *ptail;
|
||||
int length;
|
||||
} sllmv_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
sllmv_t* sllmv_alloc();
|
||||
void sllmv_free(sllmv_t* plist);
|
||||
void sllmv_prepend_with_free(sllmv_t* plist, mv_t* pvalue);
|
||||
void sllmv_prepend_no_free(sllmv_t* plist, mv_t* pvalue);
|
||||
void sllmv_append_with_free(sllmv_t* plist, mv_t* pvalue);
|
||||
void sllmv_append_no_free(sllmv_t* plist, mv_t* pvalue);
|
||||
|
||||
sllmv_t* sllmv_single_no_free(mv_t* pvalue);
|
||||
sllmv_t* sllmv_single_with_free(mv_t* pvalue);
|
||||
sllmv_t* sllmv_double_with_free(mv_t* pvalue1, mv_t* pvalue2);
|
||||
sllmv_t* sllmv_triple_with_free(mv_t* pvalue1, mv_t* pvalue2, mv_t* pvalue3);
|
||||
sllmv_t* sllmv_quadruple_with_free(mv_t* pvalue1, mv_t* pvalue2, mv_t* pvalue3, mv_t* pvalue4);
|
||||
|
||||
void sllmv_print(sllmv_t* plist);
|
||||
void sllmve_tail_print(sllmve_t* pnode);
|
||||
|
||||
#endif // SLLMV_H
|
||||
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib/mlr_arch.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/slls.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
slls_t* slls_alloc() {
|
||||
slls_t* plist = mlr_malloc_or_die(sizeof(slls_t));
|
||||
plist->phead = NULL;
|
||||
plist->ptail = NULL;
|
||||
plist->length = 0;
|
||||
return plist;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int slls_size(slls_t* plist) {
|
||||
return plist->length;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
slls_t* slls_copy(slls_t* pold) {
|
||||
slls_t* pnew = slls_alloc();
|
||||
for (sllse_t* pe = pold->phead; pe != NULL; pe = pe->pnext)
|
||||
slls_append_with_free(pnew, mlr_strdup_or_die(pe->value));
|
||||
return pnew;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void slls_free(slls_t* plist) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
sllse_t* pnode = plist->phead;
|
||||
while (pnode != NULL) {
|
||||
sllse_t* pdel = pnode;
|
||||
pnode = pnode->pnext;
|
||||
if (pdel->free_flag & FREE_ENTRY_VALUE)
|
||||
free(pdel->value);
|
||||
free(pdel);
|
||||
}
|
||||
plist->phead = NULL;
|
||||
plist->ptail = 0;
|
||||
plist->length = 0;
|
||||
free(plist);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
slls_t* slls_single_with_free(char* value) {
|
||||
slls_t* pslls = slls_alloc();
|
||||
slls_append_with_free(pslls, value);
|
||||
return pslls;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
slls_t* slls_single_no_free(char* value) {
|
||||
slls_t* pslls = slls_alloc();
|
||||
slls_append_no_free(pslls, value);
|
||||
return pslls;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void slls_append(slls_t* plist, char* value, char free_flag) {
|
||||
sllse_t* pnode = mlr_malloc_or_die(sizeof(sllse_t));
|
||||
pnode->value = value;
|
||||
pnode->free_flag = free_flag;
|
||||
|
||||
if (plist->ptail == NULL) {
|
||||
pnode->pnext = NULL;
|
||||
plist->phead = pnode;
|
||||
plist->ptail = pnode;
|
||||
} else {
|
||||
pnode->pnext = NULL;
|
||||
plist->ptail->pnext = pnode;
|
||||
plist->ptail = pnode;
|
||||
}
|
||||
plist->length++;
|
||||
}
|
||||
|
||||
void slls_append_with_free(slls_t* plist, char* value) {
|
||||
slls_append(plist, value, FREE_ENTRY_VALUE);
|
||||
}
|
||||
void slls_append_no_free(slls_t* plist, char* value) {
|
||||
slls_append(plist, value, 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int slls_equals(slls_t* pa, slls_t* pb) {
|
||||
if (pa->length != pb->length)
|
||||
return FALSE;
|
||||
sllse_t* pea = pa->phead;
|
||||
sllse_t* peb = pb->phead;
|
||||
for ( ; pea != NULL && peb != NULL; pea = pea->pnext, peb = peb->pnext) {
|
||||
if (!streq(pea->value, peb->value))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
slls_t* slls_from_line(char* line, char ifs, int allow_repeat_ifs) {
|
||||
slls_t* plist = slls_alloc();
|
||||
if (*line == 0) // empty string splits to empty list
|
||||
return plist;
|
||||
|
||||
char seps[2] = {ifs, 0};
|
||||
char* sep = &seps[0];
|
||||
int seplen = 1;
|
||||
char* walker = line;
|
||||
char* piece;
|
||||
while ((piece = mlr_strmsep(&walker, sep, seplen)) != NULL) {
|
||||
mlr_rstrip(piece); // https://github.com/johnkerl/miller/issues/313
|
||||
slls_append_no_free(plist, piece);
|
||||
}
|
||||
|
||||
return plist;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// This is inefficient and intended only for debug use.
|
||||
char* slls_join(slls_t* plist, char* ofs) {
|
||||
unsigned long long len = 0;
|
||||
for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext)
|
||||
len += strlen(pe->value) + 1; // include space for ofs and null-terminator
|
||||
char* output = mlr_malloc_or_die(len);
|
||||
*output = 0;
|
||||
for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext) {
|
||||
strcat(output, pe->value);
|
||||
if (pe->pnext != NULL) {
|
||||
strcat(output, ofs);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void slls_print(slls_t* plist) {
|
||||
if (plist == NULL) {
|
||||
printf("NULL");
|
||||
} else {
|
||||
unsigned long long i = 0;
|
||||
for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext, i++) {
|
||||
if (i > 0)
|
||||
printf(",");
|
||||
printf("%s", pe->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void slls_print_quoted(slls_t* plist) {
|
||||
if (plist == NULL) {
|
||||
printf("NULL");
|
||||
} else {
|
||||
unsigned long long i = 0;
|
||||
for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext, i++) {
|
||||
if (i > 0)
|
||||
printf(" ");
|
||||
printf("\"%s\"", pe->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void slls_reverse(slls_t* plist) {
|
||||
if (plist->phead == NULL)
|
||||
return;
|
||||
|
||||
sllse_t* pnewhead = NULL;
|
||||
sllse_t* pnewtail = plist->phead;
|
||||
sllse_t* p = plist->phead;
|
||||
sllse_t* q = p->pnext;
|
||||
while (1) {
|
||||
p->pnext = pnewhead;
|
||||
pnewhead = p;
|
||||
if (q == NULL)
|
||||
break;
|
||||
p = q;
|
||||
q = p->pnext;
|
||||
}
|
||||
plist->phead = pnewhead;
|
||||
plist->ptail = pnewtail;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int slls_hash_func(slls_t *plist) {
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
|
||||
for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext) {
|
||||
char* str = pe->value;
|
||||
while ((c = *str++) != 0)
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
// So that ["ab","c"] doesn't hash to the same as ["a","bc"]:
|
||||
hash = ((hash << 5) + hash) + ',';
|
||||
}
|
||||
|
||||
return (int)hash;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int slls_compare_lexically(slls_t* pa, slls_t* pb) {
|
||||
sllse_t* pe = pa->phead;
|
||||
sllse_t* pf = pb->phead;
|
||||
while (TRUE) {
|
||||
if (pe == NULL && pf == NULL)
|
||||
return 0;
|
||||
if (pe == NULL)
|
||||
return 1;
|
||||
if (pf == NULL)
|
||||
return -1;
|
||||
int rc = strcmp(pe->value, pf->value);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
pe = pe->pnext;
|
||||
pf = pf->pnext;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int sllse_vcmp(const void* pva, const void* pvb) {
|
||||
const sllse_t** pa = (const sllse_t**)pva;
|
||||
const sllse_t** pb = (const sllse_t**)pvb;
|
||||
return strcmp((*pa)->value, (*pb)->value);
|
||||
}
|
||||
|
||||
void slls_sort(slls_t* plist) {
|
||||
if (plist->length < 2)
|
||||
return;
|
||||
|
||||
unsigned long long i;
|
||||
sllse_t* pe;
|
||||
|
||||
// Copy to array
|
||||
sllse_t** node_array = mlr_malloc_or_die(sizeof(sllse_t*) * plist->length);
|
||||
for (i = 0, pe = plist->phead; pe != NULL; i++, pe = pe->pnext)
|
||||
node_array[i] = pe;
|
||||
|
||||
// Sort the array
|
||||
qsort(node_array, plist->length, sizeof(sllse_t*), sllse_vcmp);
|
||||
|
||||
// Copy back
|
||||
plist->phead = node_array[0];
|
||||
plist->ptail = node_array[plist->length - 1];
|
||||
for (i = 1; i < plist->length; i++) {
|
||||
node_array[i-1]->pnext = node_array[i];
|
||||
}
|
||||
plist->ptail->pnext = NULL;
|
||||
|
||||
free(node_array);
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// ================================================================
|
||||
// Singly linked list of string, with tail for append.
|
||||
// ================================================================
|
||||
|
||||
#ifndef SLLS_H
|
||||
#define SLLS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lib/free_flags.h"
|
||||
|
||||
typedef struct _sllse_t {
|
||||
char* value;
|
||||
char free_flag;
|
||||
struct _sllse_t *pnext;
|
||||
} sllse_t;
|
||||
|
||||
typedef struct _slls_t {
|
||||
sllse_t *phead;
|
||||
sllse_t *ptail;
|
||||
unsigned long long length;
|
||||
} slls_t;
|
||||
|
||||
slls_t* slls_alloc();
|
||||
int slls_size(slls_t* plist);
|
||||
slls_t* slls_copy(slls_t* pold);
|
||||
void slls_free(slls_t* plist);
|
||||
slls_t* slls_single_with_free(char* value);
|
||||
slls_t* slls_single_no_free(char* value);
|
||||
void slls_append_with_free(slls_t* plist, char* value);
|
||||
void slls_append_no_free(slls_t* plist, char* value);
|
||||
void slls_append(slls_t* plist, char* value, char free_flag);
|
||||
int slls_equals(slls_t* pa, slls_t* pb);
|
||||
slls_t* slls_from_line(char* line, char ifs, int allow_repeat_ifs);
|
||||
|
||||
void slls_reverse(slls_t* plist);
|
||||
int slls_hash_func(slls_t *plist);
|
||||
int slls_compare_lexically(slls_t* pa, slls_t* pb);
|
||||
|
||||
void slls_sort(slls_t* plist);
|
||||
|
||||
// Debug routines:
|
||||
char* slls_join(slls_t* plist, char* ofs);
|
||||
void slls_print(slls_t* plist);
|
||||
void slls_print_quoted(slls_t* plist);
|
||||
|
||||
#endif // SLLS_H
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
#include "lib/mlrutil.h"
|
||||
#include "containers/sllv.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
sllv_t* sllv_alloc() {
|
||||
sllv_t* plist = mlr_malloc_or_die(sizeof(sllv_t));
|
||||
plist->phead = NULL;
|
||||
plist->ptail = NULL;
|
||||
plist->length = 0;
|
||||
return plist;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void sllv_free(sllv_t* plist) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
sllve_t* pnode = plist->phead;
|
||||
while (pnode != NULL) {
|
||||
sllve_t* pdel = pnode;
|
||||
pnode = pnode->pnext;
|
||||
free(pdel);
|
||||
}
|
||||
plist->phead = NULL;
|
||||
plist->ptail = 0;
|
||||
plist->length = 0;
|
||||
|
||||
free(plist);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
sllv_t* sllv_single(void* pvvalue) {
|
||||
sllv_t* psllv = sllv_alloc();
|
||||
sllv_append(psllv, pvvalue);
|
||||
return psllv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void sllv_append(sllv_t* plist, void* pvvalue) {
|
||||
sllve_t* pnode = mlr_malloc_or_die(sizeof(sllve_t));
|
||||
pnode->pvvalue = pvvalue;
|
||||
if (plist->ptail == NULL) {
|
||||
pnode->pnext = NULL;
|
||||
plist->phead = pnode;
|
||||
plist->ptail = pnode;
|
||||
} else {
|
||||
pnode->pnext = NULL;
|
||||
plist->ptail->pnext = pnode;
|
||||
plist->ptail = pnode;
|
||||
}
|
||||
plist->length++;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void sllv_push(sllv_t* plist, void* pvvalue) {
|
||||
sllve_t* pnode = mlr_malloc_or_die(sizeof(sllve_t));
|
||||
pnode->pvvalue = pvvalue;
|
||||
if (plist->ptail == NULL) {
|
||||
pnode->pnext = NULL;
|
||||
plist->phead = pnode;
|
||||
plist->ptail = pnode;
|
||||
} else {
|
||||
pnode->pnext = plist->phead;
|
||||
plist->phead = pnode;
|
||||
}
|
||||
plist->length++;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void* sllv_pop(sllv_t* plist) {
|
||||
// Zero entries in list
|
||||
if (plist->phead == NULL)
|
||||
return NULL;
|
||||
|
||||
void* pval = plist->phead->pvvalue;
|
||||
// One entry in list
|
||||
if (plist->phead->pnext == NULL) {
|
||||
free(plist->phead);
|
||||
plist->phead = NULL;
|
||||
plist->ptail = NULL;
|
||||
plist->length = 0;
|
||||
}
|
||||
// Two or more entries in list
|
||||
else {
|
||||
sllve_t* pnext = plist->phead->pnext;
|
||||
free(plist->phead);
|
||||
plist->phead = pnext;
|
||||
plist->length--;
|
||||
}
|
||||
|
||||
return pval;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void sllv_reverse(sllv_t* plist) {
|
||||
if (plist->phead == NULL)
|
||||
return;
|
||||
|
||||
sllve_t* pnewhead = NULL;
|
||||
sllve_t* pnewtail = plist->phead;
|
||||
sllve_t* p = plist->phead;
|
||||
sllve_t* q = p->pnext;
|
||||
while (1) {
|
||||
p->pnext = pnewhead;
|
||||
pnewhead = p;
|
||||
if (q == NULL)
|
||||
break;
|
||||
p = q;
|
||||
q = p->pnext;
|
||||
}
|
||||
plist->phead = pnewhead;
|
||||
plist->ptail = pnewtail;
|
||||
}
|
||||
|
||||
void sllv_transfer(sllv_t* pthis, sllv_t* pthat) {
|
||||
if (pthat == NULL)
|
||||
return;
|
||||
if (pthis->phead == NULL) {
|
||||
pthis->phead = pthat->phead;
|
||||
pthis->ptail = pthat->ptail;
|
||||
pthis->length = pthat->length;
|
||||
} else if (pthat->phead != NULL) {
|
||||
pthis->ptail->pnext = pthat->phead;
|
||||
pthis->ptail = pthat->ptail;
|
||||
pthis->length += pthat->length;
|
||||
}
|
||||
pthat->phead = NULL;
|
||||
pthat->ptail = NULL;
|
||||
pthat->length = 0;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// ================================================================
|
||||
// Singly-linked list of void-star, with tail for append.
|
||||
// ================================================================
|
||||
|
||||
#ifndef SLLV_H
|
||||
#define SLLV_H
|
||||
|
||||
typedef struct _sllve_t {
|
||||
void* pvvalue;
|
||||
struct _sllve_t *pnext;
|
||||
} sllve_t;
|
||||
|
||||
typedef struct _sllv_t {
|
||||
sllve_t *phead;
|
||||
sllve_t *ptail;
|
||||
unsigned long long length;
|
||||
} sllv_t;
|
||||
|
||||
sllv_t* sllv_alloc();
|
||||
void sllv_free(sllv_t* plist);
|
||||
sllv_t* sllv_single(void* pvvalue);
|
||||
void sllv_append(sllv_t* plist, void* pvvalue); // Add at tail
|
||||
void sllv_push(sllv_t* plist, void* pvvalue); // Add at head
|
||||
void* sllv_pop(sllv_t* plist);
|
||||
void sllv_reverse(sllv_t* plist);
|
||||
// Move all records from pthat to end of pthis. Upon return, pthat is the empty
|
||||
// list.
|
||||
void sllv_transfer(sllv_t* pthis, sllv_t* pthat);
|
||||
|
||||
#endif // SLLV_H
|
||||
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "lib/mlrutil.h"
|
||||
#include "containers/top_keeper.h"
|
||||
#include "lib/mvfuncs.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
top_keeper_t* top_keeper_alloc(int capacity) {
|
||||
top_keeper_t* ptop_keeper = mlr_malloc_or_die(sizeof(top_keeper_t));
|
||||
ptop_keeper->top_values = mlr_malloc_or_die(capacity*sizeof(mv_t));
|
||||
ptop_keeper->top_precords = mlr_malloc_or_die(capacity*sizeof(lrec_t*));
|
||||
ptop_keeper->size = 0;
|
||||
ptop_keeper->capacity = capacity;
|
||||
return ptop_keeper;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void top_keeper_free(top_keeper_t* ptop_keeper) {
|
||||
if (ptop_keeper == NULL)
|
||||
return;
|
||||
free(ptop_keeper->top_values);
|
||||
free(ptop_keeper->top_precords);
|
||||
ptop_keeper->top_values = NULL;
|
||||
ptop_keeper->top_precords = NULL;
|
||||
ptop_keeper->size = 0;
|
||||
ptop_keeper->capacity = 0;
|
||||
free(ptop_keeper);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Cases:
|
||||
// 1. array size < capacity
|
||||
// * find destidx
|
||||
// * if destidx == size
|
||||
// put it there
|
||||
// else
|
||||
// shift down & insert
|
||||
// increment size
|
||||
//
|
||||
// 2. array size == capacity
|
||||
// * find destidx
|
||||
// * if destidx == size
|
||||
// discard
|
||||
// else
|
||||
// shift down & insert
|
||||
|
||||
// capacity = 10, size = 6, destidx = 3 capacity = 10, size = 10, destidx = 3
|
||||
// [0 #] [0 #] [0 #] [0 #]
|
||||
// [1 #] [1 #] [1 #] [1 #]
|
||||
// [2 #] [2 #] [2 #] [2 #]
|
||||
// [3 #]* [3 X] [3 #]* [3 X]
|
||||
// [4 #] [4 #] [4 #] [4 #]
|
||||
// [5 #] [5 #] [5 #] [5 #]
|
||||
// [6 ] [6 #] [6 #] [6 #]
|
||||
// [7 ] [7 ] [7 #] [7 #]
|
||||
// [8 ] [8 ] [8 #] [8 #]
|
||||
// [9 ] [9 ] [9 #] [9 #]
|
||||
|
||||
// Our caller, mapper_top, feeds us records. We keep them or free them.
|
||||
void top_keeper_add(top_keeper_t* ptop_keeper, mv_t value, lrec_t* prec) {
|
||||
int destidx = mlr_bsearch_mv_n_for_insert(ptop_keeper->top_values, ptop_keeper->size, &value);
|
||||
if (ptop_keeper->size < ptop_keeper->capacity) {
|
||||
for (int i = ptop_keeper->size-1; i >= destidx; i--) {
|
||||
ptop_keeper->top_values[i+1] = ptop_keeper->top_values[i];
|
||||
ptop_keeper->top_precords[i+1] = ptop_keeper->top_precords[i];
|
||||
}
|
||||
ptop_keeper->top_values[destidx] = value;
|
||||
ptop_keeper->top_precords[destidx] = prec;
|
||||
ptop_keeper->size++;
|
||||
} else {
|
||||
if (destidx >= ptop_keeper->capacity) {
|
||||
lrec_free(prec);
|
||||
return;
|
||||
}
|
||||
lrec_free(ptop_keeper->top_precords[ptop_keeper->size-1]);
|
||||
for (int i = ptop_keeper->size-2; i >= destidx; i--) {
|
||||
ptop_keeper->top_values[i+1] = ptop_keeper->top_values[i];
|
||||
ptop_keeper->top_precords[i+1] = ptop_keeper->top_precords[i];
|
||||
}
|
||||
ptop_keeper->top_values[destidx] = value;
|
||||
ptop_keeper->top_precords[destidx] = prec;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void top_keeper_print(top_keeper_t* ptop_keeper) {
|
||||
printf("top_keeper dump:\n");
|
||||
for (int i = 0; i < ptop_keeper->size; i++) {
|
||||
mv_t* pvalue = &ptop_keeper->top_values[i];
|
||||
if (pvalue->type == MT_FLOAT)
|
||||
printf("[%02d] %.8lf\n", i, pvalue->u.fltv);
|
||||
else
|
||||
printf("[%02d] %lld\n", i, pvalue->u.intv);
|
||||
}
|
||||
for (int i = ptop_keeper->size; i < ptop_keeper->capacity; i++)
|
||||
printf("[%02d] ---\n", i);
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// ================================================================
|
||||
// Data structure for mlr top: just a decorated array.
|
||||
// ================================================================
|
||||
|
||||
#ifndef TOP_KEEPER_H
|
||||
#define TOP_KEEPER_H
|
||||
#include "lib/mlrval.h"
|
||||
#include "containers/lrec.h"
|
||||
|
||||
typedef struct _top_keeper_t {
|
||||
mv_t* top_values;
|
||||
lrec_t** top_precords;
|
||||
int size;
|
||||
int capacity;
|
||||
} top_keeper_t;
|
||||
|
||||
top_keeper_t* top_keeper_alloc(int capacity);
|
||||
void top_keeper_free(top_keeper_t* ptop_keeper);
|
||||
void top_keeper_add(top_keeper_t* ptop_keeper, mv_t value, lrec_t* prec);
|
||||
|
||||
// For debug/test
|
||||
void top_keeper_print(top_keeper_t* ptop_keeper);
|
||||
|
||||
#endif // TOP_KEEPER_H
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#include "containers/type_decl.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
char* type_mask_to_desc(int type_mask) {
|
||||
switch(type_mask) {
|
||||
case TYPE_MASK_ERROR: return "error"; break;
|
||||
case TYPE_MASK_ANY: return "any"; break;
|
||||
case TYPE_MASK_ABSENT: return "absent"; break;
|
||||
case TYPE_MASK_EMPTY: return "empty"; break;
|
||||
case TYPE_MASK_STRING: return "string"; break;
|
||||
case TYPE_MASK_INT: return "int"; break;
|
||||
case TYPE_MASK_FLOAT: return "float"; break;
|
||||
case TYPE_MASK_BOOLEAN: return "boolean"; break;
|
||||
case TYPE_MASK_NUMERIC: return "numeric"; break;
|
||||
case TYPE_MASK_MAP: return "map"; break;
|
||||
default: return "???"; break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
int type_mask_from_name(char* name) {
|
||||
if (streq(name, "error")) { return TYPE_MASK_ERROR; }
|
||||
else if (streq(name, "absent")) { return TYPE_MASK_ABSENT; }
|
||||
else if (streq(name, "empty")) { return TYPE_MASK_EMPTY; }
|
||||
else if (streq(name, "string")) { return TYPE_MASK_STRING; }
|
||||
else if (streq(name, "str")) { return TYPE_MASK_STRING; }
|
||||
else if (streq(name, "int")) { return TYPE_MASK_INT; }
|
||||
else if (streq(name, "float")) { return TYPE_MASK_FLOAT; }
|
||||
else if (streq(name, "numeric")) { return TYPE_MASK_NUMERIC; }
|
||||
else if (streq(name, "num")) { return TYPE_MASK_NUMERIC; }
|
||||
else if (streq(name, "boolean")) { return TYPE_MASK_BOOLEAN; }
|
||||
else if (streq(name, "bool")) { return TYPE_MASK_BOOLEAN; }
|
||||
else if (streq(name, "map")) { return TYPE_MASK_MAP; }
|
||||
else if (streq(name, "var")) { return TYPE_MASK_ANY; }
|
||||
else if (streq(name, "any")) { return TYPE_MASK_ANY; }
|
||||
|
||||
else {
|
||||
MLR_INTERNAL_CODING_ERROR();
|
||||
return 0; // not reached
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef TYPE_DECL_H
|
||||
#define TYPE_DECL_H
|
||||
|
||||
#include "../lib/mlrval.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// These use the MT defines from mlrval.h, except that map-types (mlhmmv.h)
|
||||
// are outside of mlrval.h.
|
||||
#define TYPE_MASK_ERROR (1 << MT_ERROR)
|
||||
#define TYPE_MASK_ABSENT (1 << MT_ABSENT)
|
||||
#define TYPE_MASK_EMPTY (1 << MT_EMPTY)
|
||||
#define TYPE_MASK_STRING ((1 << MT_STRING) | (1 << MT_EMPTY))
|
||||
#define TYPE_MASK_INT (1 << MT_INT)
|
||||
#define TYPE_MASK_FLOAT (1 << MT_FLOAT)
|
||||
#define TYPE_MASK_NUMERIC (TYPE_MASK_INT | TYPE_MASK_FLOAT)
|
||||
#define TYPE_MASK_BOOLEAN (1 << MT_BOOLEAN)
|
||||
#define TYPE_MASK_MAP (1 << MT_DIM)
|
||||
#define TYPE_MASK_ANY (~0)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
char* type_mask_to_desc(int type_mask);
|
||||
static inline int type_mask_from_mv(mv_t* pmv) {
|
||||
return 1 << pmv->type;
|
||||
}
|
||||
int type_mask_from_name(char* name);
|
||||
|
||||
#endif // TYPE_DECL_H
|
||||
|
|
@ -1,492 +0,0 @@
|
|||
#include "../lib/mlr_arch.h"
|
||||
#include "../lib/string_builder.h"
|
||||
#include "../lib/free_flags.h"
|
||||
#include "../containers/xvfuncs.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
boxed_xval_t b_xx_haskey_xfunc(boxed_xval_t* pmapval, boxed_xval_t* pkeyval) {
|
||||
boxed_xval_t rv;
|
||||
if (pmapval->xval.is_terminal) {
|
||||
rv = box_ephemeral_val(mv_from_bool(FALSE));
|
||||
} else if (!pkeyval->xval.is_terminal) {
|
||||
rv = box_ephemeral_val(mv_from_bool(FALSE));
|
||||
} else {
|
||||
rv = box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
mlhmmv_level_has_key(pmapval->xval.pnext_level, &pkeyval->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
if (pmapval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pmapval->xval);
|
||||
if (pkeyval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pkeyval->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
boxed_xval_t i_x_length_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv;
|
||||
if (pbxval1->xval.is_terminal) {
|
||||
rv = box_ephemeral_val(
|
||||
mv_from_int(1)
|
||||
);
|
||||
} else {
|
||||
rv = box_ephemeral_val(
|
||||
mv_from_int(
|
||||
pbxval1->xval.pnext_level->num_occupied
|
||||
)
|
||||
);
|
||||
}
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int depth_aux(mlhmmv_xvalue_t* pxval) {
|
||||
if (pxval->is_terminal) {
|
||||
return 0;
|
||||
} else {
|
||||
int max = 0;
|
||||
for (mlhmmv_level_entry_t* pe = pxval->pnext_level->phead; pe != NULL; pe = pe->pnext) {
|
||||
int curr = depth_aux(&pe->level_xvalue);
|
||||
max = (curr > max) ? curr : max;
|
||||
}
|
||||
return 1 + max;
|
||||
}
|
||||
}
|
||||
|
||||
boxed_xval_t i_x_depth_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = box_ephemeral_val(
|
||||
mv_from_int(
|
||||
depth_aux(&pbxval1->xval)
|
||||
)
|
||||
);
|
||||
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static int leafcount_aux(mlhmmv_xvalue_t* pxval) {
|
||||
if (pxval->is_terminal) {
|
||||
return 1;
|
||||
} else {
|
||||
int sum = 0;
|
||||
for (mlhmmv_level_entry_t* pe = pxval->pnext_level->phead; pe != NULL; pe = pe->pnext) {
|
||||
sum += leafcount_aux(&pe->level_xvalue);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
boxed_xval_t i_x_leafcount_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = box_ephemeral_val(
|
||||
mv_from_int(
|
||||
leafcount_aux(&pbxval1->xval)
|
||||
)
|
||||
);
|
||||
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
boxed_xval_t variadic_mapsum_xfunc(boxed_xval_t* pbxvals, int nxvals) {
|
||||
// xxx to-do optmization: transfer arg 1 if it's ephemeral
|
||||
mlhmmv_xvalue_t sum = mlhmmv_xvalue_alloc_empty_map();
|
||||
for (int i = 0; i < nxvals; i++) {
|
||||
if (pbxvals[i].xval.is_terminal)
|
||||
continue;
|
||||
mlhmmv_level_t* plevel = pbxvals[i].xval.pnext_level;
|
||||
for (mlhmmv_level_entry_t* pe = plevel->phead; pe != NULL; pe = pe->pnext) {
|
||||
// xxx do refs/copies correctly
|
||||
mlhmmv_xvalue_t xval_copy = mlhmmv_xvalue_copy(&pe->level_xvalue);
|
||||
sllmve_t e = (sllmve_t) { .value = pe->level_key, .free_flags = 0, .pnext = NULL };
|
||||
mlhmmv_level_put_xvalue(sum.pnext_level, &e, &xval_copy);
|
||||
}
|
||||
}
|
||||
boxed_xval_t rv = box_ephemeral_xval(sum);
|
||||
|
||||
for (int i = 0; i < nxvals; i++) {
|
||||
if (pbxvals[i].is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxvals[i].xval);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
boxed_xval_t variadic_mapdiff_xfunc(boxed_xval_t* pbxvals, int nxvals) {
|
||||
mlhmmv_xvalue_t diff = mlhmmv_xvalue_alloc_empty_map();
|
||||
if (nxvals == 0) {
|
||||
return box_ephemeral_xval(diff);
|
||||
}
|
||||
// xxx to-do optmization: transfer arg 1 if it's ephemeral
|
||||
|
||||
// xxx methodize
|
||||
int i = 0;
|
||||
if (!pbxvals[i].xval.is_terminal) {
|
||||
mlhmmv_level_t* plevel = pbxvals[i].xval.pnext_level;
|
||||
for (mlhmmv_level_entry_t* pe = plevel->phead; pe != NULL; pe = pe->pnext) {
|
||||
// xxx do refs/copies correctly
|
||||
mlhmmv_xvalue_t xval_copy = mlhmmv_xvalue_copy(&pe->level_xvalue);
|
||||
sllmve_t e = (sllmve_t) { .value = pe->level_key, .free_flags = 0, .pnext = NULL };
|
||||
mlhmmv_level_put_xvalue(diff.pnext_level, &e, &xval_copy);
|
||||
}
|
||||
if (pbxvals[i].is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxvals[i].xval);
|
||||
}
|
||||
|
||||
for (i = 1; i < nxvals; i++) {
|
||||
if (!pbxvals[i].xval.is_terminal) {
|
||||
mlhmmv_level_t* plevel = pbxvals[i].xval.pnext_level;
|
||||
for (mlhmmv_level_entry_t* pe = plevel->phead; pe != NULL; pe = pe->pnext) {
|
||||
sllmve_t e = (sllmve_t) { .value = pe->level_key, .free_flags = 0, .pnext = NULL };
|
||||
mlhmmv_level_remove(diff.pnext_level, &e);
|
||||
}
|
||||
}
|
||||
if (pbxvals[i].is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxvals[i].xval);
|
||||
}
|
||||
|
||||
return box_ephemeral_xval(diff);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition (validated before we're called): there is at least one argument
|
||||
// which is the map to be unkeyed.
|
||||
boxed_xval_t variadic_mapexcept_xfunc(
|
||||
boxed_xval_t* pbxvals,
|
||||
int nxvals)
|
||||
{
|
||||
MLR_INTERNAL_CODING_ERROR_IF(nxvals < 1);
|
||||
|
||||
boxed_xval_t* pinbxval = &pbxvals[0];
|
||||
boxed_xval_t outbxval = box_ephemeral_xval(mlhmmv_xvalue_copy(&pinbxval->xval));
|
||||
|
||||
if (pinbxval->xval.is_terminal) { // non-map
|
||||
return outbxval;
|
||||
}
|
||||
|
||||
mlhmmv_level_t* poutlevel = outbxval.xval.pnext_level;
|
||||
|
||||
for (int i = 1; i < nxvals; i++) {
|
||||
if (pbxvals[i].xval.is_terminal) {
|
||||
mv_t* pkey = &pbxvals[i].xval.terminal_mlrval;
|
||||
sllmve_t e = (sllmve_t) { .value = *pkey, .free_flags = 0, .pnext = NULL };
|
||||
mlhmmv_level_remove(poutlevel, &e);
|
||||
}
|
||||
if (pbxvals[i].is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxvals[i].xval);
|
||||
}
|
||||
|
||||
return outbxval;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition (validated before we're called): there is at least one argument
|
||||
// which is the map to be unkeyed.
|
||||
boxed_xval_t variadic_mapselect_xfunc(
|
||||
boxed_xval_t* pbxvals,
|
||||
int nxvals)
|
||||
{
|
||||
MLR_INTERNAL_CODING_ERROR_IF(nxvals < 1);
|
||||
|
||||
boxed_xval_t* pinbxval = &pbxvals[0];
|
||||
boxed_xval_t outbxval = box_ephemeral_xval(mlhmmv_xvalue_alloc_empty_map());
|
||||
|
||||
if (pinbxval->xval.is_terminal) { // non-map
|
||||
return outbxval;
|
||||
}
|
||||
|
||||
mlhmmv_level_t* pinlevel = pinbxval->xval.pnext_level;
|
||||
mlhmmv_level_t* poutlevel = outbxval.xval.pnext_level;
|
||||
|
||||
for (int i = 1; i < nxvals; i++) {
|
||||
|
||||
if (pbxvals[i].xval.is_terminal) {
|
||||
mv_t* pkey = &pbxvals[i].xval.terminal_mlrval;
|
||||
sllmv_t* pkeylist = sllmv_single_no_free(pkey);
|
||||
int unused = 0;
|
||||
mlhmmv_xvalue_t* pval = mlhmmv_level_look_up_and_ref_xvalue(pinlevel, pkeylist, &unused);
|
||||
if (pval != NULL) {
|
||||
mlhmmv_xvalue_t copyval = mlhmmv_xvalue_copy(pval);
|
||||
// mlhmmv_level_put_xvalue copies key not value
|
||||
mlhmmv_level_put_xvalue(poutlevel, pkeylist->phead, ©val);
|
||||
}
|
||||
sllmv_free(pkeylist);
|
||||
}
|
||||
if (pbxvals[i].is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxvals[i].xval);
|
||||
|
||||
}
|
||||
|
||||
return outbxval;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that both arguments are string-valued terminals.
|
||||
boxed_xval_t m_ss_splitnv_xfunc(boxed_xval_t* pstringval, boxed_xval_t* psepval) {
|
||||
mlhmmv_xvalue_t map = mlhmmv_xvalue_alloc_empty_map();
|
||||
char* input = mlr_strdup_or_die(pstringval->xval.terminal_mlrval.u.strv);
|
||||
char* sep = psepval->xval.terminal_mlrval.u.strv;
|
||||
int seplen = strlen(sep);
|
||||
|
||||
int i = 1;
|
||||
char* walker = input;
|
||||
char* piece;
|
||||
while ((piece = mlr_strmsep(&walker, sep, seplen)) != NULL) {
|
||||
mv_t key = mv_from_int(i);
|
||||
mv_t val = mv_ref_type_infer_string_or_float_or_int(piece);
|
||||
mlhmmv_level_put_terminal_singly_keyed(map.pnext_level, &key, &val);
|
||||
i++;
|
||||
}
|
||||
free(input);
|
||||
|
||||
if (pstringval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pstringval->xval);
|
||||
if (psepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&psepval->xval);
|
||||
|
||||
return box_ephemeral_xval(map);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that both arguments are string-valued terminals.
|
||||
boxed_xval_t m_ss_splitnvx_xfunc(boxed_xval_t* pstringval, boxed_xval_t* psepval) {
|
||||
mlhmmv_xvalue_t map = mlhmmv_xvalue_alloc_empty_map();
|
||||
char* input = mlr_strdup_or_die(pstringval->xval.terminal_mlrval.u.strv);
|
||||
char* sep = psepval->xval.terminal_mlrval.u.strv;
|
||||
int seplen = strlen(sep);
|
||||
|
||||
int i = 1;
|
||||
char* walker = input;
|
||||
char* piece;
|
||||
while ((piece = mlr_strmsep(&walker, sep, seplen)) != NULL) {
|
||||
mv_t key = mv_from_int(i);
|
||||
// xxx do not ref here
|
||||
mv_t val = mv_ref_type_infer_string(piece);
|
||||
// xxx make clear the copy/ref semantics for mlhmmv put with scalar value.
|
||||
// at the moment this does an mv_copy.
|
||||
mlhmmv_level_put_terminal_singly_keyed(map.pnext_level, &key, &val);
|
||||
i++;
|
||||
}
|
||||
|
||||
free(input);
|
||||
|
||||
if (pstringval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pstringval->xval);
|
||||
if (psepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&psepval->xval);
|
||||
|
||||
return box_ephemeral_xval(map);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that all arguments are string-valued terminals.
|
||||
boxed_xval_t m_sss_splitkv_xfunc(boxed_xval_t* pstringval, boxed_xval_t* ppairsepval, boxed_xval_t* plistsepval) {
|
||||
mlhmmv_xvalue_t map = mlhmmv_xvalue_alloc_empty_map();
|
||||
char* input = mlr_strdup_or_die(pstringval->xval.terminal_mlrval.u.strv);
|
||||
char* listsep = plistsepval->xval.terminal_mlrval.u.strv;
|
||||
char* pairsep = ppairsepval->xval.terminal_mlrval.u.strv;
|
||||
int listseplen = strlen(listsep);
|
||||
int pairseplen = strlen(pairsep);
|
||||
|
||||
int i = 1;
|
||||
char* walker = input;
|
||||
char* piece;
|
||||
while ((piece = mlr_strmsep(&walker, listsep, listseplen)) != NULL) {
|
||||
char* pair = piece;
|
||||
char* left = mlr_strmsep(&pair, pairsep, pairseplen);
|
||||
if (pair == NULL) {
|
||||
mv_t key = mv_from_int(i);
|
||||
mv_t val = mv_ref_type_infer_string_or_float_or_int(left);
|
||||
mlhmmv_level_put_terminal_singly_keyed(map.pnext_level, &key, &val);
|
||||
} else {
|
||||
char* right = mlr_strmsep(&pair, pairsep, pairseplen);
|
||||
mv_t key = mv_from_string(left, NO_FREE);
|
||||
mv_t val = mv_ref_type_infer_string_or_float_or_int(right);
|
||||
mlhmmv_level_put_terminal_singly_keyed(map.pnext_level, &key, &val);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
free(input);
|
||||
|
||||
if (pstringval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pstringval->xval);
|
||||
if (ppairsepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&ppairsepval->xval);
|
||||
if (plistsepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&plistsepval->xval);
|
||||
|
||||
return box_ephemeral_xval(map);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that all arguments are string-valued terminals.
|
||||
boxed_xval_t m_sss_splitkvx_xfunc(boxed_xval_t* pstringval, boxed_xval_t* ppairsepval, boxed_xval_t* plistsepval) {
|
||||
mlhmmv_xvalue_t map = mlhmmv_xvalue_alloc_empty_map();
|
||||
char* input = mlr_strdup_or_die(pstringval->xval.terminal_mlrval.u.strv);
|
||||
char* listsep = plistsepval->xval.terminal_mlrval.u.strv;
|
||||
char* pairsep = ppairsepval->xval.terminal_mlrval.u.strv;
|
||||
int listseplen = strlen(listsep);
|
||||
int pairseplen = strlen(pairsep);
|
||||
|
||||
int i = 1;
|
||||
char* walker = input;
|
||||
char* piece;
|
||||
while ((piece = mlr_strmsep(&walker, listsep, listseplen)) != NULL) {
|
||||
char* pair = piece;
|
||||
char* left = mlr_strmsep(&pair, pairsep, pairseplen);
|
||||
if (pair == NULL) {
|
||||
mv_t key = mv_from_int(i);
|
||||
mv_t val = mv_ref_type_infer_string(left);
|
||||
mlhmmv_level_put_terminal_singly_keyed(map.pnext_level, &key, &val);
|
||||
} else {
|
||||
char* right = mlr_strmsep(&pair, pairsep, pairseplen);
|
||||
mv_t key = mv_from_string(left, NO_FREE);
|
||||
mv_t val = mv_ref_type_infer_string(right);
|
||||
mlhmmv_level_put_terminal_singly_keyed(map.pnext_level, &key, &val);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
free(input);
|
||||
|
||||
if (pstringval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pstringval->xval);
|
||||
if (ppairsepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&ppairsepval->xval);
|
||||
if (plistsepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&plistsepval->xval);
|
||||
|
||||
return box_ephemeral_xval(map);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
#define SB_JOIN_ALLOC_SIZE 128
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that the separator is a string-valued terminal.
|
||||
boxed_xval_t s_ms_joink_xfunc(boxed_xval_t* pmapval, boxed_xval_t* psepval) {
|
||||
if (pmapval->xval.is_terminal) {
|
||||
return box_ephemeral_val(mv_absent());
|
||||
}
|
||||
|
||||
string_builder_t* psb = sb_alloc(SB_JOIN_ALLOC_SIZE);
|
||||
for (mlhmmv_level_entry_t* pentry = pmapval->xval.pnext_level->phead; pentry != NULL; pentry = pentry->pnext) {
|
||||
// The string_builder object will copy the string so we can point into source string space,
|
||||
// without a copy here, when possible.
|
||||
char free_flags = 0;
|
||||
char* sval = mv_maybe_alloc_format_val(&pentry->level_key, &free_flags);
|
||||
sb_append_string(psb, sval);
|
||||
if (free_flags)
|
||||
free(sval);
|
||||
if (pentry->pnext != NULL) {
|
||||
sb_append_string(psb, psepval->xval.terminal_mlrval.u.strv);
|
||||
}
|
||||
}
|
||||
|
||||
char* sretval = sb_finish(psb);
|
||||
sb_free(psb);
|
||||
|
||||
if (pmapval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pmapval->xval);
|
||||
if (psepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&psepval->xval);
|
||||
|
||||
return box_ephemeral_val(
|
||||
mv_from_string(sretval, FREE_ENTRY_VALUE)
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that the separator is a string-valued terminal.
|
||||
boxed_xval_t s_ms_joinv_xfunc(boxed_xval_t* pmapval, boxed_xval_t* psepval) {
|
||||
if (pmapval->xval.is_terminal) {
|
||||
return box_ephemeral_val(mv_absent());
|
||||
}
|
||||
|
||||
string_builder_t* psb = sb_alloc(SB_JOIN_ALLOC_SIZE);
|
||||
for (mlhmmv_level_entry_t* pentry = pmapval->xval.pnext_level->phead; pentry != NULL; pentry = pentry->pnext) {
|
||||
if (pentry->level_xvalue.is_terminal) {
|
||||
// The string_builder object will copy the string so we can point into source string space,
|
||||
// without a copy here, when possible.
|
||||
char free_flags = 0;
|
||||
char* sval = mv_maybe_alloc_format_val(&pentry->level_xvalue.terminal_mlrval, &free_flags);
|
||||
sb_append_string(psb, sval);
|
||||
if (free_flags)
|
||||
free(sval);
|
||||
if (pentry->pnext != NULL) {
|
||||
sb_append_string(psb, psepval->xval.terminal_mlrval.u.strv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* sretval = sb_finish(psb);
|
||||
sb_free(psb);
|
||||
|
||||
if (pmapval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pmapval->xval);
|
||||
if (psepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&psepval->xval);
|
||||
|
||||
return box_ephemeral_val(
|
||||
mv_from_string(sretval, FREE_ENTRY_VALUE)
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Precondition: the caller has ensured that the separators are string-valued terminals.
|
||||
boxed_xval_t s_mss_joinkv_xfunc(boxed_xval_t* pmapval, boxed_xval_t* ppairsepval, boxed_xval_t* plistsepval) {
|
||||
if (pmapval->xval.is_terminal) {
|
||||
return box_ephemeral_val(mv_absent());
|
||||
}
|
||||
|
||||
string_builder_t* psb = sb_alloc(SB_JOIN_ALLOC_SIZE);
|
||||
for (mlhmmv_level_entry_t* pentry = pmapval->xval.pnext_level->phead; pentry != NULL; pentry = pentry->pnext) {
|
||||
if (pentry->level_xvalue.is_terminal) {
|
||||
// The string_builder object will copy the string so we can point into source string space,
|
||||
// without a copy here, when possible.
|
||||
|
||||
char kfree_flags = 0;
|
||||
char* skval = mv_maybe_alloc_format_val(&pentry->level_key, &kfree_flags);
|
||||
sb_append_string(psb, skval);
|
||||
if (kfree_flags)
|
||||
free(skval);
|
||||
|
||||
sb_append_string(psb, ppairsepval->xval.terminal_mlrval.u.strv);
|
||||
|
||||
char vfree_flags = 0;
|
||||
char* svval = mv_maybe_alloc_format_val(&pentry->level_xvalue.terminal_mlrval, &vfree_flags);
|
||||
sb_append_string(psb, svval);
|
||||
if (vfree_flags)
|
||||
free(svval);
|
||||
|
||||
if (pentry->pnext != NULL) {
|
||||
sb_append_string(psb, plistsepval->xval.terminal_mlrval.u.strv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* sretval = sb_finish(psb);
|
||||
sb_free(psb);
|
||||
|
||||
if (pmapval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pmapval->xval);
|
||||
if (ppairsepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&ppairsepval->xval);
|
||||
if (plistsepval->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&plistsepval->xval);
|
||||
|
||||
return box_ephemeral_val(
|
||||
mv_from_string(sretval, FREE_ENTRY_VALUE)
|
||||
);
|
||||
}
|
||||
|
|
@ -1,352 +0,0 @@
|
|||
#ifndef XVFUNCS_H
|
||||
#define XVFUNCS_H
|
||||
|
||||
// ================================================================
|
||||
// Functions on extended values, namely, scalars and maps.
|
||||
//
|
||||
// NOTE ON EPHEMERALITY OF MAPS:
|
||||
//
|
||||
// Most functions here free their inputs. E.g. for string concatenation, the
|
||||
// output which is returned is the concatenation of the two inputs which are
|
||||
// freed. This is true for functions on scalars as well as functions on maps
|
||||
// (the latter in this header file).
|
||||
//
|
||||
// However, maps are treated differently from scalars in that some maps are
|
||||
// referenced, rather than copied, within the concrete syntax tree. E.g. in
|
||||
// 'mapsum({3:4},@v)', the map literal {3:4} is ephemeral to the expression and
|
||||
// must be freed during evaluation, but the @v part is referenced to the @v data
|
||||
// structure and is only copied on write. The boxed_xval_t's is_ephemeral flag
|
||||
// tracks the difference between the two cases.
|
||||
// ================================================================
|
||||
|
||||
#include "../lib/mlrutil.h"
|
||||
#include "../containers/mlhmmv.h"
|
||||
#include "../containers/boxed_xval.h"
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef boxed_xval_t xv_variadic_func_t(
|
||||
boxed_xval_t* pbxvals,
|
||||
int nxvals);
|
||||
|
||||
typedef boxed_xval_t xv_zary_func_t();
|
||||
|
||||
typedef boxed_xval_t xv_unary_func_t(
|
||||
boxed_xval_t* pbxval1);
|
||||
|
||||
typedef boxed_xval_t xv_binary_func_t(
|
||||
boxed_xval_t* pbxval1,
|
||||
boxed_xval_t* pbxval2);
|
||||
|
||||
typedef boxed_xval_t xv_ternary_func_t(
|
||||
boxed_xval_t* pbxval1,
|
||||
boxed_xval_t* pbxval2,
|
||||
boxed_xval_t* pbxval3);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Most functions here free their inputs. E.g. for string concatenation, the
|
||||
// output which is returned is the concatenation of the two inputs which are
|
||||
// freed. For another example, is_string frees its input and returns the boolean
|
||||
// value of the result. These functions, by contrast, only return a boolean for
|
||||
// the outcome of the test but do not free the inputs. The intended usage is for
|
||||
// type-assertion checks. E.g. in '$b = asserting_string($a)', if $a is a
|
||||
// string it is assigned to $b, else an error is thrown.
|
||||
|
||||
static inline boxed_xval_t b_x_is_present_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
!pbxval1->xval.is_terminal || mv_is_present(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_absent_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_absent(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
!pbxval1->xval.is_terminal
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_not_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_numeric_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_numeric(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_int_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_int(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_float_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_float(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_boolean_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_boolean(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_string_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_string(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_null_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_null(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_not_null_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
!(pbxval1->xval.is_terminal && mv_is_null(&pbxval1->xval.terminal_mlrval))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_empty_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
pbxval1->xval.is_terminal && mv_is_empty(&pbxval1->xval.terminal_mlrval)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_not_empty_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
!(pbxval1->xval.is_terminal && mv_is_empty(&pbxval1->xval.terminal_mlrval))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_empty_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
!pbxval1->xval.is_terminal && pbxval1->xval.pnext_level->num_occupied == 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_nonempty_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_bool(
|
||||
!pbxval1->xval.is_terminal && pbxval1->xval.pnext_level->num_occupied != 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static inline boxed_xval_t s_x_typeof_no_free_xfunc(boxed_xval_t* pbxval1) {
|
||||
return box_ephemeral_val(
|
||||
mv_from_string(
|
||||
mlhmmv_xvalue_describe_type_simple(&pbxval1->xval), NO_FREE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline boxed_xval_t b_x_is_present_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_present_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_absent_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_absent_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_map_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_map_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_not_map_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_not_map_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_numeric_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_numeric_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_int_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_int_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_float_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_float_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_boolean_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_boolean_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_string_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_string_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_null_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_null_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_not_null_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_not_null_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_empty_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_empty_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_not_empty_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_not_empty_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_empty_map_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_empty_map_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t b_x_is_nonempty_map_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = b_x_is_nonempty_map_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline boxed_xval_t s_x_typeof_xfunc(boxed_xval_t* pbxval1) {
|
||||
boxed_xval_t rv = s_x_typeof_no_free_xfunc(pbxval1);
|
||||
if (pbxval1->is_ephemeral)
|
||||
mlhmmv_xvalue_free(&pbxval1->xval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
boxed_xval_t b_xx_haskey_xfunc(
|
||||
boxed_xval_t* pmapval,
|
||||
boxed_xval_t* pkeyval);
|
||||
|
||||
boxed_xval_t i_x_length_xfunc(
|
||||
boxed_xval_t* pbxval1);
|
||||
|
||||
boxed_xval_t i_x_depth_xfunc(
|
||||
boxed_xval_t* pbxval1);
|
||||
|
||||
boxed_xval_t i_x_leafcount_xfunc(
|
||||
boxed_xval_t* pbxval1);
|
||||
|
||||
boxed_xval_t variadic_mapsum_xfunc(
|
||||
boxed_xval_t* pbxvals, int nxvals);
|
||||
|
||||
boxed_xval_t variadic_mapdiff_xfunc(
|
||||
boxed_xval_t* pbxvals, int nxvals);
|
||||
|
||||
boxed_xval_t variadic_mapexcept_xfunc(
|
||||
boxed_xval_t* pbxvals, int nxvals);
|
||||
|
||||
boxed_xval_t variadic_mapselect_xfunc(
|
||||
boxed_xval_t* pbxvals, int nxvals);
|
||||
|
||||
boxed_xval_t m_ss_splitnv_xfunc(
|
||||
boxed_xval_t* pstringval,
|
||||
boxed_xval_t* psepval);
|
||||
|
||||
boxed_xval_t m_ss_splitnvx_xfunc(
|
||||
boxed_xval_t* pstringval,
|
||||
boxed_xval_t* psepval);
|
||||
|
||||
boxed_xval_t m_sss_splitkv_xfunc(
|
||||
boxed_xval_t* pstringval,
|
||||
boxed_xval_t* ppairsepval,
|
||||
boxed_xval_t* plistsepval);
|
||||
|
||||
boxed_xval_t m_sss_splitkvx_xfunc(
|
||||
boxed_xval_t* pstringval,
|
||||
boxed_xval_t* ppairsepval,
|
||||
boxed_xval_t* plistsepval);
|
||||
|
||||
boxed_xval_t s_ms_joink_xfunc(
|
||||
boxed_xval_t* pmapval,
|
||||
boxed_xval_t* psepval);
|
||||
|
||||
boxed_xval_t s_ms_joinv_xfunc(
|
||||
boxed_xval_t* pmapval,
|
||||
boxed_xval_t* psepval);
|
||||
|
||||
boxed_xval_t s_mss_joinkv_xfunc(
|
||||
boxed_xval_t* pmapval,
|
||||
boxed_xval_t* ppairsepval,
|
||||
boxed_xval_t* plistsepval);
|
||||
|
||||
#endif // XVFUNCS_H
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
================================================================
|
||||
Offlineable (subway-tunnelable) excerpt from https://tools.ietf.org/html/rfc4180
|
||||
================================================================
|
||||
Definition of the CSV Format
|
||||
|
||||
While there are various specifications and implementations for the
|
||||
CSV format (for ex. [4], [5], [6] and [7]), there is no formal
|
||||
specification in existence, which allows for a wide variety of
|
||||
interpretations of CSV files. This section documents the format that
|
||||
seems to be followed by most implementations:
|
||||
|
||||
1. Each record is located on a separate line, delimited by a line
|
||||
break (CRLF). For example:
|
||||
|
||||
aaa,bbb,ccc CRLF
|
||||
zzz,yyy,xxx CRLF
|
||||
|
||||
2. The last record in the file may or may not have an ending line
|
||||
break. For example:
|
||||
|
||||
aaa,bbb,ccc CRLF
|
||||
zzz,yyy,xxx
|
||||
|
||||
3. There maybe an optional header line appearing as the first line
|
||||
of the file with the same format as normal record lines. This
|
||||
header will contain names corresponding to the fields in the file
|
||||
and should contain the same number of fields as the records in
|
||||
the rest of the file (the presence or absence of the header line
|
||||
should be indicated via the optional "header" parameter of this
|
||||
MIME type). For example:
|
||||
|
||||
field_name,field_name,field_name CRLF
|
||||
aaa,bbb,ccc CRLF
|
||||
zzz,yyy,xxx CRLF
|
||||
|
||||
4. Within the header and each record, there may be one or more
|
||||
fields, separated by commas. Each line should contain the same
|
||||
number of fields throughout the file. Spaces are considered part
|
||||
of a field and should not be ignored. The last field in the
|
||||
record must not be followed by a comma. For example:
|
||||
|
||||
aaa,bbb,ccc
|
||||
|
||||
5. Each field may or may not be enclosed in double quotes (however
|
||||
some programs, such as Microsoft Excel, do not use double quotes
|
||||
at all). If fields are not enclosed with double quotes, then
|
||||
double quotes may not appear inside the fields. For example:
|
||||
|
||||
"aaa","bbb","ccc" CRLF
|
||||
zzz,yyy,xxx
|
||||
|
||||
6. Fields containing line breaks (CRLF), double quotes, and commas
|
||||
should be enclosed in double-quotes. For example:
|
||||
|
||||
"aaa","b CRLF
|
||||
bb","ccc" CRLF
|
||||
zzz,yyy,xxx
|
||||
|
||||
7. If double-quotes are used to enclose fields, then a double-quote
|
||||
appearing inside a field must be escaped by preceding it with
|
||||
another double quote. For example:
|
||||
|
||||
"aaa","b""bb","ccc"
|
||||
|
||||
The ABNF grammar [2] appears as follows:
|
||||
|
||||
file = [header CRLF] record *(CRLF record) [CRLF]
|
||||
|
||||
header = name *(COMMA name)
|
||||
|
||||
record = field *(COMMA field)
|
||||
|
||||
name = field
|
||||
|
||||
field = (escaped / non-escaped)
|
||||
|
||||
escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
|
||||
|
||||
non-escaped = *TEXTDATA
|
||||
|
||||
COMMA = %x2C
|
||||
|
||||
CR = %x0D ;as per section 6.1 of RFC 2234 [2]
|
||||
|
||||
DQUOTE = %x22 ;as per section 6.1 of RFC 2234 [2]
|
||||
|
||||
LF = %x0A ;as per section 6.1 of RFC 2234 [2]
|
||||
|
||||
CRLF = CR LF ;as per section 6.1 of RFC 2234 [2]
|
||||
|
||||
TEXTDATA = %x20-21 / %x23-2B / %x2D-7E
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# Title here
|
||||
|
||||
## Features:
|
||||
|
||||
* The new [**system DSL function**](http://johnkerl.org/miller/doc/reference-dsl.html#system) allows you to run
|
||||
arbitrary shell commands and store them in field values. Some example usages are documented [**here**](http://johnkerl.org/miller/doc/data-sharing.html#Running_shell_commands).
|
||||
|
||||
* There is now support for [**ASV and USV file formats**](http://johnkerl.org/miller/doc/file-formats.html#CSV/TSV/ASV/USV/etc.).
|
||||
|
||||
* The new [**format-values**](http://johnkerl.org/miller/doc/reference-verbs.html#format-values) verb allows you to apply numerical formatting across all record values.
|
||||
|
||||
## Documentation:
|
||||
|
||||
* The new [**DKVP I/O in Python**](http://johnkerl.org/miller/doc/data-sharing.html#DKVP_I/O_in_Python) sample code now works for Python 2 as well as Python 3.
|
||||
|
||||
* There is a new cookbook entry on [**doing multiple joins**](http://johnkerl.org/miller/doc/cookbook.html#Doing_multiple_joins).
|
||||
|
||||
## Bugfixes:
|
||||
|
||||
* The [**toupper**](http://johnkerl.org/miller/doc/reference-dsl.html#toupper), [**tolower**](http://johnkerl.org/miller/doc/reference-dsl.html#tolower), and [**capitalize**](http://johnkerl.org/miller/doc/reference-dsl.html#capitalize) DSL functions are now UTF-8 aware, thanks to @sheredom's marvelous https://github.com/sheredom/utf8.h. The [**internationalization page**]((http://johnkerl.org/miller/doc/internationalization.html) has also been expanded.
|
||||
|
||||
* https://github.com/johnkerl/miller/issues/250 fixes a bug using [**in-place mode**](https://johnkerl.org/miller/doc/reference.html#In-place_mode) in conjunction with verbs (such as [**rename**](http://johnkerl.org/miller/doc/reference-dsl.html#rename) or [**sort**](http://johnkerl.org/miller/doc/reference-dsl.html#sort)) which take field-name lists as arguments.
|
||||
|
||||
* https://github.com/johnkerl/miller/issues/253 fixes a bug in the [**label**](http://johnkerl.org/miller/doc/reference-verbs.html#label) when one or more names are common between old and new.
|
||||
|
||||
* https://github.com/johnkerl/miller/issues/251 fixes a corner-case bug when (a) input is CSV; (b) the last field ends with a comma and no newline; (c) input is from standard input and/or <tt>--no-mmap</tt> is supplied.
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
noinst_LTLIBRARIES= libdsl.la
|
||||
libdsl_la_SOURCES= \
|
||||
context_flags.h \
|
||||
function_manager.c \
|
||||
function_manager.h \
|
||||
keylist_evaluators.c \
|
||||
keylist_evaluators.h \
|
||||
mlr_dsl_ast.c \
|
||||
mlr_dsl_ast.h \
|
||||
mlr_dsl_blocked_ast.c \
|
||||
mlr_dsl_blocked_ast.h \
|
||||
mlr_dsl_cst.c \
|
||||
mlr_dsl_cst.h \
|
||||
mlr_dsl_cst_condish_statements.c \
|
||||
mlr_dsl_cst_for_map_statements.c \
|
||||
mlr_dsl_cst_for_srec_statements.c \
|
||||
mlr_dsl_cst_func_subr.c \
|
||||
mlr_dsl_cst_keywords.c \
|
||||
mlr_dsl_cst_loop_control_statements.c \
|
||||
mlr_dsl_cst_map_assignment_statements.c \
|
||||
mlr_dsl_cst_output_statements.c \
|
||||
mlr_dsl_cst_return_statements.c \
|
||||
mlr_dsl_cst_scalar_assignment_statements.c \
|
||||
mlr_dsl_cst_statements.c \
|
||||
mlr_dsl_cst_triple_for_statements.c \
|
||||
mlr_dsl_cst_unset_statements.c \
|
||||
mlr_dsl_stack_allocate.c \
|
||||
return_state.h \
|
||||
rval_evaluator.h \
|
||||
rval_evaluators.h \
|
||||
rval_expr_evaluators.c \
|
||||
rval_func_evaluators.c \
|
||||
rval_list_evaluators.c \
|
||||
rxval_evaluator.h \
|
||||
rxval_evaluators.h \
|
||||
rxval_expr_evaluators.c \
|
||||
rxval_func_evaluators.c \
|
||||
type_inference.h \
|
||||
variables.h
|
||||
libdsl_la_LIBADD= ../lib/libmlr.la ../cli/libcli.la ../input/libinput.la
|
||||
|
||||
# TODO: replace the interesting content with unit tests; jettison the rest
|
||||
# TODO: Does not build
|
||||
#noinst_PROGRAMS= evl
|
||||
#evl_SOURCES= rval_evaluators.c
|
||||
#evl_LDADD= libdsl.la ../containers/libcontainers.la ../lib/libmlr.la
|
||||
#evl_CPPFLAGS= -D__LREC_EVALUATORS_MAIN__ ${AM_CPPFLAGS}
|
||||
|
||||
AM_CPPFLAGS= -I${srcdir}/../
|
||||
AM_CFLAGS= -std=gnu99
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue