Remove Miller-5 source/doc/manpage directories, along with C-build files (#731)

This commit is contained in:
John Kerl 2021-11-04 00:45:44 -04:00 committed by GitHub
parent 9eefc56487
commit 7578b789f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1354 changed files with 2995 additions and 488407 deletions

89
.gitignore vendored
View file

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

View file

@ -1,6 +0,0 @@
# not GPL, thus no COPYING file
AUTOMAKE_OPTIONS=foreign
EXTRA_DIST= LICENSE.txt README.md
SUBDIRS=c man

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

1801
autotools/config.sub vendored

File diff suppressed because it is too large Load diff

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -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='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # 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:

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +0,0 @@
#!/bin/bash
export CC='clang -fsanitize=address'
make -ef Makefile.no-autoconfig "$@"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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().

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 "???";
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, &copyval);
}
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)
);
}

View file

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

View file

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

View file

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

View file

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